Commit 9b2f0394 by Jason Merrill Committed by Jason Merrill

re PR c++/54922 ([C++11][DR 1359] constexpr constructors require initialization…

re PR c++/54922 ([C++11][DR 1359] constexpr constructors require initialization of all union members)

	PR c++/54922
	* semantics.c (build_anon_member_initialization): New.
	(build_data_member_initialization): Use it.

From-SVN: r196070
parent b24cd3d1
2013-02-14 Jason Merrill <jason@redhat.com>
PR c++/54922
* semantics.c (build_anon_member_initialization): New.
(build_data_member_initialization): Use it.
PR c++/55003
* decl.c (cp_finish_decl): Force instantiation of an
auto static data member.
......
......@@ -5815,6 +5815,59 @@ is_valid_constexpr_fn (tree fun, bool complain)
return ret;
}
/* Subroutine of build_data_member_initialization. MEMBER is a COMPONENT_REF
for a member of an anonymous aggregate, INIT is the initializer for that
member, and VEC_OUTER is the vector of constructor elements for the class
whose constructor we are processing. Add the initializer to the vector
and return true to indicate success. */
static bool
build_anon_member_initialization (tree member, tree init,
vec<constructor_elt, va_gc> **vec_outer)
{
/* MEMBER presents the relevant fields from the inside out, but we need
to build up the initializer from the outside in so that we can reuse
previously built CONSTRUCTORs if this is, say, the second field in an
anonymous struct. So we use a vec as a stack. */
vec<tree> fields;
fields.create (2);
do
{
fields.safe_push (TREE_OPERAND (member, 1));
member = TREE_OPERAND (member, 0);
}
while (ANON_AGGR_TYPE_P (TREE_TYPE (member)));
/* VEC has the constructor elements vector for the context of FIELD.
If FIELD is an anonymous aggregate, we will push inside it. */
vec<constructor_elt, va_gc> **vec = vec_outer;
tree field;
while (field = fields.pop(),
ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{
tree ctor;
/* If there is already an outer constructor entry for the anonymous
aggregate FIELD, use it; otherwise, insert one. */
if (vec_safe_is_empty (*vec)
|| (*vec)->last().index != field)
{
ctor = build_constructor (TREE_TYPE (field), NULL);
CONSTRUCTOR_APPEND_ELT (*vec, field, ctor);
}
else
ctor = (*vec)->last().value;
vec = &CONSTRUCTOR_ELTS (ctor);
}
/* Now we're at the innermost field, the one that isn't an anonymous
aggregate. Add its initializer to the CONSTRUCTOR and we're done. */
gcc_assert (fields.is_empty());
fields.release ();
CONSTRUCTOR_APPEND_ELT (*vec, field, init);
return true;
}
/* Subroutine of build_constexpr_constructor_member_initializers.
The expression tree T represents a data member initialization
in a (constexpr) constructor definition. Build a pairing of
......@@ -5901,12 +5954,21 @@ build_data_member_initialization (tree t, vec<constructor_elt, va_gc> **vec)
}
if (TREE_CODE (member) == ADDR_EXPR)
member = TREE_OPERAND (member, 0);
if (TREE_CODE (member) == COMPONENT_REF
/* If we're initializing a member of a subaggregate, it's a vtable
pointer. Leave it as COMPONENT_REF so we remember the path to get
to the vfield. */
&& TREE_CODE (TREE_OPERAND (member, 0)) != COMPONENT_REF)
member = TREE_OPERAND (member, 1);
if (TREE_CODE (member) == COMPONENT_REF)
{
tree aggr = TREE_OPERAND (member, 0);
if (TREE_CODE (aggr) != COMPONENT_REF)
/* Normal member initialization. */
member = TREE_OPERAND (member, 1);
else if (ANON_AGGR_TYPE_P (TREE_TYPE (aggr)))
/* Initializing a member of an anonymous union. */
return build_anon_member_initialization (member, init, vec);
else
/* We're initializing a vtable pointer in a base. Leave it as
COMPONENT_REF so we remember the path to get to the vfield. */
gcc_assert (TREE_TYPE (member) == vtbl_ptr_type_node);
}
CONSTRUCTOR_APPEND_ELT (*vec, member, init);
return true;
}
......
// PR c++/54922
// { dg-do compile { target c++11 } }
struct nullable_int
{
bool init_;
union {
unsigned char for_value_init;
int value_;
};
constexpr nullable_int() : init_(false), for_value_init() {}
};
#define SA(X) static_assert(X,#X)
constexpr nullable_int n;
SA((n.for_value_init == 0));
// PR c++/54922
// { dg-options "-std=c++11 -pedantic" }
#define SA(X) static_assert(X,#X)
struct A
{
union {
union {
union {
unsigned char i;
int j;
};
};
};
constexpr A() : i(42) {}
};
constexpr A a;
SA((a.i == 42));
struct B
{
struct {
int h;
struct {
union {
unsigned char i;
int j;
};
int k;
}; // { dg-warning "anonymous struct" }
}; // { dg-warning "anonymous struct" }
int l;
constexpr B(): h(1), i(2), k(3), l(4) {}
};
constexpr B b;
SA((b.h == 1 && b.i == 2 && b.k == 3 && b.l == 4));
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