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
This commit is contained in:
Nathan Sidwell 2016-03-31 15:30:33 +00:00 committed by Nathan Sidwell
parent 95d34b9618
commit 88504f3435
6 changed files with 113 additions and 19 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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. */