Commit 88504f34 by Nathan Sidwell Committed by Nathan Sidwell

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
parent 95d34b96
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> 2016-03-31 Kirill Yukhin <kirill.yukhin@intel.com>
PR target/70453 PR target/70453
......
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> 2016-03-31 Marek Polacek <polacek@redhat.com>
PR c/70297 PR c/70297
......
...@@ -2959,16 +2959,39 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, ...@@ -2959,16 +2959,39 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
else else
{ {
gcc_assert (TREE_CODE (index) == FIELD_DECL); 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); vec_safe_iterate (CONSTRUCTOR_ELTS (*valp), idx, &cep);
idx++) idx++, fields = DECL_CHAIN (fields))
if (index == cep->index)
break;
if (!cep)
{ {
constructor_elt ce = { index, NULL_TREE }; if (index == cep->index)
cep = vec_safe_push (CONSTRUCTOR_ELTS (*valp), ce); 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; valp = &cep->value;
} }
......
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> 2016-03-31 Kirill Yukhin <kirill.yukhin@intel.com>
PR target/70453 PR target/70453
......
// 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();
}
...@@ -4929,6 +4929,14 @@ output_constructor_regular_field (oc_local_state *local) ...@@ -4929,6 +4929,14 @@ output_constructor_regular_field (oc_local_state *local)
unsigned int align2; 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) if (local->index != NULL_TREE)
{ {
/* Perform the index calculation in modulo arithmetic but /* Perform the index calculation in modulo arithmetic but
...@@ -4945,22 +4953,19 @@ output_constructor_regular_field (oc_local_state *local) ...@@ -4945,22 +4953,19 @@ output_constructor_regular_field (oc_local_state *local)
else else
fieldpos = 0; 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. /* Advance to offset of this element.
Note no alignment needed in an array, since that is guaranteed Note no alignment needed in an array, since that is guaranteed
if each element has the proper size. */ if each element has the proper size. */
if ((local->field != NULL_TREE || local->index != NULL_TREE) if (local->field != NULL_TREE || local->index != NULL_TREE)
&& fieldpos > local->total_bytes)
{ {
assemble_zeros (fieldpos - local->total_bytes); if (fieldpos > local->total_bytes)
local->total_bytes = fieldpos; {
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. */ /* Find the alignment of this element. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment