mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
65f9e78999
commit
3a6a88c863
|
|
@ -1,3 +1,11 @@
|
||||||
|
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)
|
||||||
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);
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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);
|
if (ctx && TREE_CODE (ctx) == UNION_TYPE)
|
||||||
while (1)
|
|
||||||
{
|
{
|
||||||
if (same_type_p (last_ctx, ctx))
|
/* A mem-initializer hides an NSDMI. */
|
||||||
{
|
if (TREE_VALUE (init) && !TREE_VALUE (*last_p))
|
||||||
if (TREE_CODE (ctx) == UNION_TYPE)
|
*last_p = TREE_CHAIN (*last_p);
|
||||||
|
else if (TREE_VALUE (*last_p) && !TREE_VALUE (init))
|
||||||
|
goto splice;
|
||||||
|
else
|
||||||
error_at (DECL_SOURCE_LOCATION (current_function_decl),
|
error_at (DECL_SOURCE_LOCATION (current_function_decl),
|
||||||
"initializations for multiple members of %qT",
|
"initializations for multiple members of %qT",
|
||||||
last_ctx);
|
ctx);
|
||||||
done = 1;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (same_type_p (last_ctx, t))
|
last_p = p;
|
||||||
break;
|
|
||||||
|
|
||||||
last_ctx = TYPE_CONTEXT (last_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we've reached the outermost class, then we're
|
|
||||||
done. */
|
|
||||||
if (same_type_p (ctx, t))
|
|
||||||
break;
|
|
||||||
|
|
||||||
ctx = TYPE_CONTEXT (ctx);
|
|
||||||
}
|
|
||||||
while (!done);
|
|
||||||
|
|
||||||
last_field = field;
|
|
||||||
|
|
||||||
next:
|
next:
|
||||||
p = &TREE_CHAIN (*p);
|
p = &TREE_CHAIN (*p);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
// 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;
|
||||||
Loading…
Reference in New Issue