aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-03-01 10:02:12 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2017-03-01 10:02:12 +0100
commit42132674e5c9e7978a7d7d9283682f89639e236e (patch)
tree90bace33bc8bb839de2a9bf73929c8d73b391cde
parent0100ae430272feaa208b02c32e52d530cd9c8644 (diff)
downloadgcc-42132674e5c9e7978a7d7d9283682f89639e236e.zip
gcc-42132674e5c9e7978a7d7d9283682f89639e236e.tar.gz
gcc-42132674e5c9e7978a7d7d9283682f89639e236e.tar.bz2
re PR c++/79681 (ICE with constexpr and bitfield)
PR c++/79681 * fold-const.c (make_bit_field_ref): If orig_inner is COMPONENT_REF, attempt to use its first operand as BIT_FIELD_REF base. * g++.dg/cpp1y/constexpr-79681-1.C: New test. * g++.dg/cpp1y/constexpr-79681-2.C: New test. From-SVN: r245804
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/fold-const.c25
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-79681-1.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-79681-2.C39
5 files changed, 91 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 253eab3..4873ae8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2017-03-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/79681
+ * fold-const.c (make_bit_field_ref): If orig_inner is COMPONENT_REF,
+ attempt to use its first operand as BIT_FIELD_REF base.
+
2017-03-01 Richard Biener <rguenther@suse.de>
PR middle-end/79721
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 3d63836..e64fa64 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -3862,6 +3862,31 @@ make_bit_field_ref (location_t loc, tree inner, tree orig_inner, tree type,
{
tree result, bftype;
+ /* Attempt not to lose the access path if possible. */
+ if (TREE_CODE (orig_inner) == COMPONENT_REF)
+ {
+ tree ninner = TREE_OPERAND (orig_inner, 0);
+ machine_mode nmode;
+ HOST_WIDE_INT nbitsize, nbitpos;
+ tree noffset;
+ int nunsignedp, nreversep, nvolatilep = 0;
+ tree base = get_inner_reference (ninner, &nbitsize, &nbitpos,
+ &noffset, &nmode, &nunsignedp,
+ &nreversep, &nvolatilep);
+ if (base == inner
+ && noffset == NULL_TREE
+ && nbitsize >= bitsize
+ && nbitpos <= bitpos
+ && bitpos + bitsize <= nbitpos + nbitsize
+ && !reversep
+ && !nreversep
+ && !nvolatilep)
+ {
+ inner = ninner;
+ bitpos -= nbitpos;
+ }
+ }
+
alias_set_type iset = get_alias_set (orig_inner);
if (iset == 0 && get_alias_set (inner) != iset)
inner = fold_build2 (MEM_REF, TREE_TYPE (inner),
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7aac384..5d7e177 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -5,6 +5,10 @@
2017-03-01 Jakub Jelinek <jakub@redhat.com>
+ PR c++/79681
+ * g++.dg/cpp1y/constexpr-79681-1.C: New test.
+ * g++.dg/cpp1y/constexpr-79681-2.C: New test.
+
PR c++/79746
* g++.dg/warn/Wunused-parm-9.C: New test.
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-79681-1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-79681-1.C
new file mode 100644
index 0000000..000afd8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-79681-1.C
@@ -0,0 +1,17 @@
+// PR c++/79681
+// { dg-do compile { target c++14 } }
+// { dg-options "-O2" }
+
+struct A
+{
+ int i : 4;
+};
+
+constexpr bool
+foo ()
+{
+ A x[] = { 1 };
+ return x[0].i;
+}
+
+static_assert (foo(), "");
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-79681-2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-79681-2.C
new file mode 100644
index 0000000..edca161
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-79681-2.C
@@ -0,0 +1,39 @@
+// PR c++/79681
+// { dg-do compile { target c++14 } }
+// { dg-options "-O2" }
+
+struct A
+{
+ char i : 4;
+ char k : 1;
+ char l : 3;
+};
+struct B
+{
+ char j : 4;
+};
+struct C
+{
+ long long u;
+ A a[1];
+ B b[1];
+};
+
+constexpr bool
+foo ()
+{
+ C c = { 0, { { 5, 0, 2 } }, { { 6 } } };
+ C d = { 0, { { 6, 0, 1 } }, { { 5 } } };
+ return c.a[0].i == d.a[0].i && c.b[0].j == d.b[0].j;
+}
+
+constexpr bool
+bar ()
+{
+ C c = { 0, { { 5, 0, 2 } }, { { 6 } } };
+ C d = { 0, { { 6, 0, 1 } }, { { 5 } } };
+ return c.a[0].i == d.a[0].i && c.a[0].l == d.a[0].l;
+}
+
+static_assert (foo () == false, "");
+static_assert (bar () == false, "");