Commit 3a6a88c8 by Jason Merrill Committed by Jason Merrill

re PR c++/52377 (C++11 non-static initializers in unions are not used)

	PR c++/52377
	* class.c (common_enclosing_class): New.
	* cp-tree.h: Declare it.
	* init.c (sort_mem_initializers): Don't splice out a union member
	with an NSDMI.

From-SVN: r199455
parent 65f9e789
2013-05-30 Jason Merrill <jason@redhat.com>
PR c++/52377
* class.c (common_enclosing_class): New.
* cp-tree.h: Declare it.
* init.c (sort_mem_initializers): Don't splice out a union member
with an NSDMI.
2013-05-29 Jan Hubicka <jh@suse.cz> 2013-05-29 Jan Hubicka <jh@suse.cz>
* tree.c (cp_fix_function_decl_p): Update for new symtab flags. * tree.c (cp_fix_function_decl_p): Update for new symtab flags.
......
...@@ -9259,4 +9259,30 @@ publicly_uniquely_derived_p (tree parent, tree type) ...@@ -9259,4 +9259,30 @@ publicly_uniquely_derived_p (tree parent, tree type)
return base && base != error_mark_node; return base && base != error_mark_node;
} }
/* CTX1 and CTX2 are declaration contexts. Return the innermost common
class between them, if any. */
tree
common_enclosing_class (tree ctx1, tree ctx2)
{
if (!TYPE_P (ctx1) || !TYPE_P (ctx2))
return NULL_TREE;
gcc_assert (ctx1 == TYPE_MAIN_VARIANT (ctx1)
&& ctx2 == TYPE_MAIN_VARIANT (ctx2));
if (ctx1 == ctx2)
return ctx1;
for (tree t = ctx1; TYPE_P (t); t = TYPE_CONTEXT (t))
TYPE_MARKED_P (t) = true;
tree found = NULL_TREE;
for (tree t = ctx2; TYPE_P (t); t = TYPE_CONTEXT (t))
if (TYPE_MARKED_P (t))
{
found = t;
break;
}
for (tree t = ctx1; TYPE_P (t); t = TYPE_CONTEXT (t))
TYPE_MARKED_P (t) = false;
return found;
}
#include "gt-cp-class.h" #include "gt-cp-class.h"
...@@ -5112,6 +5112,7 @@ extern void deduce_noexcept_on_destructor (tree); ...@@ -5112,6 +5112,7 @@ extern void deduce_noexcept_on_destructor (tree);
extern void insert_late_enum_def_into_classtype_sorted_fields (tree, tree); extern void insert_late_enum_def_into_classtype_sorted_fields (tree, tree);
extern bool uniquely_derived_from_p (tree, tree); extern bool uniquely_derived_from_p (tree, tree);
extern bool publicly_uniquely_derived_p (tree, tree); extern bool publicly_uniquely_derived_p (tree, tree);
extern tree common_enclosing_class (tree, tree);
/* in cvt.c */ /* in cvt.c */
extern tree convert_to_reference (tree, tree, int, int, tree, extern tree convert_to_reference (tree, tree, int, int, tree,
......
...@@ -914,13 +914,12 @@ sort_mem_initializers (tree t, tree mem_inits) ...@@ -914,13 +914,12 @@ sort_mem_initializers (tree t, tree mem_inits)
Here we also splice out uninitialized union members. */ Here we also splice out uninitialized union members. */
if (uses_unions_p) if (uses_unions_p)
{ {
tree last_field = NULL_TREE; tree *last_p = NULL;
tree *p; tree *p;
for (p = &sorted_inits; *p; ) for (p = &sorted_inits; *p; )
{ {
tree field; tree field;
tree ctx; tree ctx;
int done;
init = *p; init = *p;
...@@ -940,22 +939,25 @@ sort_mem_initializers (tree t, tree mem_inits) ...@@ -940,22 +939,25 @@ sort_mem_initializers (tree t, tree mem_inits)
for (ctx = DECL_CONTEXT (field); for (ctx = DECL_CONTEXT (field);
!same_type_p (ctx, t); !same_type_p (ctx, t);
ctx = TYPE_CONTEXT (ctx)) ctx = TYPE_CONTEXT (ctx))
if (TREE_CODE (ctx) == UNION_TYPE) if (TREE_CODE (ctx) == UNION_TYPE
|| !ANON_AGGR_TYPE_P (ctx))
break; break;
/* If this field is not a member of a union, skip it. */ /* If this field is not a member of a union, skip it. */
if (TREE_CODE (ctx) != UNION_TYPE) if (TREE_CODE (ctx) != UNION_TYPE)
goto next; goto next;
/* If this union member has no explicit initializer, splice /* If this union member has no explicit initializer and no NSDMI,
it out. */ splice it out. */
if (!TREE_VALUE (init)) if (TREE_VALUE (init) || DECL_INITIAL (field))
/* OK. */;
else
goto splice; goto splice;
/* It's only an error if we have two initializers for the same /* It's only an error if we have two initializers for the same
union type. */ union type. */
if (!last_field) if (!last_p)
{ {
last_field = field; last_p = p;
goto next; goto next;
} }
...@@ -967,41 +969,23 @@ sort_mem_initializers (tree t, tree mem_inits) ...@@ -967,41 +969,23 @@ sort_mem_initializers (tree t, tree mem_inits)
union { struct { int i; int j; }; }; union { struct { int i; int j; }; };
initializing both `i' and `j' makes sense. */ initializing both `i' and `j' makes sense. */
ctx = DECL_CONTEXT (field); ctx = common_enclosing_class (DECL_CONTEXT (field),
done = 0; DECL_CONTEXT (TREE_PURPOSE (*last_p)));
do
{
tree last_ctx;
last_ctx = DECL_CONTEXT (last_field);
while (1)
{
if (same_type_p (last_ctx, ctx))
{
if (TREE_CODE (ctx) == UNION_TYPE)
error_at (DECL_SOURCE_LOCATION (current_function_decl),
"initializations for multiple members of %qT",
last_ctx);
done = 1;
break;
}
if (same_type_p (last_ctx, t)) if (ctx && TREE_CODE (ctx) == UNION_TYPE)
break; {
/* A mem-initializer hides an NSDMI. */
last_ctx = TYPE_CONTEXT (last_ctx); if (TREE_VALUE (init) && !TREE_VALUE (*last_p))
} *last_p = TREE_CHAIN (*last_p);
else if (TREE_VALUE (*last_p) && !TREE_VALUE (init))
/* If we've reached the outermost class, then we're goto splice;
done. */ else
if (same_type_p (ctx, t)) error_at (DECL_SOURCE_LOCATION (current_function_decl),
break; "initializations for multiple members of %qT",
ctx);
ctx = TYPE_CONTEXT (ctx);
} }
while (!done);
last_field = field; last_p = p;
next: next:
p = &TREE_CHAIN (*p); p = &TREE_CHAIN (*p);
......
// PR c++/52377
// { dg-do run { target c++11 } }
union Test
{
int a{4};
};
union B
{
int i = 42;
double d;
B() = default;
B(double d): d(d) { }
};
int main()
{
Test t;
B b;
B b2(4.2);
if (t.a != 4 || b.i != 42 || b2.d != 4.2)
__builtin_abort();
}
// PR c++/52377
// { dg-do run { target c++11 } }
union A // { dg-error "multiple" }
{
int i = 4;
int j = 2;
};
A a;
union B
{
int i,j;
B(): i(1), j(2) {} // { dg-error "multiple" }
};
B b;
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