aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2016-03-31 15:30:33 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2016-03-31 15:30:33 +0000
commit88504f3435845976b92ee7e9d358f8e687502772 (patch)
tree6129d53eb107465f19b3b61d2bbcc066a80e270f /gcc
parent95d34b9618011fea39c48544cc8937577720dcc1 (diff)
downloadgcc-88504f3435845976b92ee7e9d358f8e687502772.zip
gcc-88504f3435845976b92ee7e9d358f8e687502772.tar.gz
gcc-88504f3435845976b92ee7e9d358f8e687502772.tar.bz2
re PR c++/70393 (Miscompilation: missing constructor call for static object)
PR c++/70393 * varasm.c (output_constructor_regular_field): Flush bitfield earlier. Assert we don't want to move backwards. cp/ * constexpr.c (cxx_eval_store_expression): Keep CONSTRUCTOR elements in field order. testsuite/ * g++.dg/cpp0x/constexpr-virtual6.C: New. From-SVN: r234636
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/constexpr.c37
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-virtual6.C49
-rw-r--r--gcc/varasm.c29
6 files changed, 113 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5a9b321..c58b659 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2016-03-31 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/70393
+ * varasm.c (output_constructor_regular_field): Flush bitfield
+ earlier. Assert we don't want to move backwards.
+
2016-03-31 Kirill Yukhin <kirill.yukhin@intel.com>
PR target/70453
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8aad906..4a6dc51 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2016-03-31 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/70393
+ * constexpr.c (cxx_eval_store_expression): Keep CONSTRUCTOR
+ elements in field order.
+
2016-03-31 Marek Polacek <polacek@redhat.com>
PR c/70297
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 8ea7111..ea605dc 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -2959,16 +2959,39 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
else
{
gcc_assert (TREE_CODE (index) == FIELD_DECL);
- for (unsigned HOST_WIDE_INT idx = 0;
+
+ /* We must keep the CONSTRUCTOR's ELTS in FIELD order.
+ Usually we meet initializers in that order, but it is
+ possible for base types to be placed not in program
+ order. */
+ tree fields = TYPE_FIELDS (DECL_CONTEXT (index));
+ unsigned HOST_WIDE_INT idx;
+
+ for (idx = 0;
vec_safe_iterate (CONSTRUCTOR_ELTS (*valp), idx, &cep);
- idx++)
- if (index == cep->index)
- break;
- if (!cep)
+ idx++, fields = DECL_CHAIN (fields))
{
- constructor_elt ce = { index, NULL_TREE };
- cep = vec_safe_push (CONSTRUCTOR_ELTS (*valp), ce);
+ if (index == cep->index)
+ goto found;
+
+ /* The field we're initializing must be on the field
+ list. Look to see if it is present before the
+ field the current ELT initializes. */
+ for (; fields != cep->index; fields = DECL_CHAIN (fields))
+ if (index == fields)
+ goto insert;
}
+
+ /* We fell off the end of the CONSTRUCTOR, so insert a new
+ entry at the end. */
+ insert:
+ {
+ constructor_elt ce = { index, NULL_TREE };
+
+ vec_safe_insert (CONSTRUCTOR_ELTS (*valp), idx, ce);
+ cep = CONSTRUCTOR_ELT (*valp, idx);
+ }
+ found:;
}
valp = &cep->value;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4cab394..f977fc8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-03-31 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/70393
+ * g++.dg/cpp0x/constexpr-virtual6.C: New.
+
2016-03-31 Kirill Yukhin <kirill.yukhin@intel.com>
PR target/70453
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual6.C
new file mode 100644
index 0000000..f5abf2c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual6.C
@@ -0,0 +1,49 @@
+// PR c++/70393
+// { dg-do run { target c++11 } }
+
+/* 'ab' has a static initializer, but we flubbed the initializer,
+ because of B being the primary base. */
+
+struct A
+{
+ int a = 1;
+};
+
+struct B
+{
+ B *element = (B*)2;
+
+ virtual int vfunc() = 0;
+
+ int call_element()
+ {
+ return element->vfunc();
+ }
+
+ void set_element()
+ {
+ element = this;
+ }
+};
+
+struct AB : public A, public B
+{
+ int vfunc()
+ {
+ return 0;
+ }
+};
+
+static AB ab;
+
+int main()
+{
+ if (ab.a != 1)
+ return 1;
+ if (ab.element != (void*)2)
+ return 2;
+
+ ab.set_element();
+ return ab.call_element();
+}
+
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 3a3573e..b0f2af0 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -4929,6 +4929,14 @@ output_constructor_regular_field (oc_local_state *local)
unsigned int align2;
+ /* Output any buffered-up bit-fields preceding this element. */
+ if (local->byte_buffer_in_use)
+ {
+ assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
+ local->total_bytes++;
+ local->byte_buffer_in_use = false;
+ }
+
if (local->index != NULL_TREE)
{
/* Perform the index calculation in modulo arithmetic but
@@ -4945,22 +4953,19 @@ output_constructor_regular_field (oc_local_state *local)
else
fieldpos = 0;
- /* Output any buffered-up bit-fields preceding this element. */
- if (local->byte_buffer_in_use)
- {
- assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
- local->total_bytes++;
- local->byte_buffer_in_use = false;
- }
-
/* Advance to offset of this element.
Note no alignment needed in an array, since that is guaranteed
if each element has the proper size. */
- if ((local->field != NULL_TREE || local->index != NULL_TREE)
- && fieldpos > local->total_bytes)
+ if (local->field != NULL_TREE || local->index != NULL_TREE)
{
- assemble_zeros (fieldpos - local->total_bytes);
- local->total_bytes = fieldpos;
+ if (fieldpos > local->total_bytes)
+ {
+ assemble_zeros (fieldpos - local->total_bytes);
+ local->total_bytes = fieldpos;
+ }
+ else
+ /* Must not go backwards. */
+ gcc_assert (fieldpos == local->total_bytes);
}
/* Find the alignment of this element. */