aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2016-03-31 20:51:20 +0000
committerNathan Sidwell <nathan@acm.org>2016-03-31 20:51:20 +0000
commit6152db581bd74f5010a48331cbf549d52d05308f (patch)
tree2f3af43696fbf520218912489d04519439744e44
parent580e524ee1bc9da8e60d033151f420907f03c17a (diff)
PR c++/70393
* varasm.c (output_constructor_regular_field): Flush bitfield earlier. Assert we don't want to move backwards. cp/ PR c++/70393 * constexpr.c (cxx_eval_store_expression): Keep CONSTRUCTOR elements in field order. testsuite/ PR c++/70393 * g++.dg/cpp0x/constexpr-virtual6.C: New. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-5-branch@234653 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/constexpr.c35
-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, 112 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b87046dd56a..49c80eac359 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 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* config/arm/sync.md (arm_atomic_loaddi2_ldrd): Fix output template
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8d3578f0bbc..862eda971f0 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-30 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index be93b8afaa3..390cc5a3b14 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -2852,16 +2852,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)
{
- 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 5c17df103fc..0db2ab4112d 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 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* gcc.target/arm/atomic_loaddi_relaxed_cond.c: New test.
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 00000000000..f5abf2cf9b9
--- /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 a62d02fb187..1747605310d 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -4947,6 +4947,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
@@ -4963,22 +4971,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. */