diff options
author | Nathan Sidwell <nathan@acm.org> | 2016-03-31 20:51:20 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@acm.org> | 2016-03-31 20:51:20 +0000 |
commit | 6152db581bd74f5010a48331cbf549d52d05308f (patch) | |
tree | 2f3af43696fbf520218912489d04519439744e44 | |
parent | 580e524ee1bc9da8e60d033151f420907f03c17a (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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 35 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-virtual6.C | 49 | ||||
-rw-r--r-- | gcc/varasm.c | 29 |
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. */ |