The problem here was that split_nonconstant_init depends on the value of
stmts_are_full_exprs_p(), but it wasn't being set properly at namespace
scope. Fixed thus. build_aggr_init_full_exprs seems to be an ancient
workaround for this same issue.
Tested x86_64-pc-linux-gnu, applied to trunk.
commit ed588cf8d90c740ea189727eecb7dac3b7c24320
Author: Jason Merrill <ja...@redhat.com>
Date: Wed Nov 30 16:32:22 2011 -0500
PR c++/51009
* name-lookup.c (push_to_top_level): Set stmts_are_full_exprs_p.
* decl.c (build_aggr_init_full_exprs): Just assert that it's true.
(check_initializer): Here too.
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 4d65dd1..8ef95aa 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -487,18 +487,13 @@ struct GTY(()) stmt_tree_s {
VEC(tree,gc) *x_cur_stmt_list;
/* In C++, Nonzero if we should treat statements as full
- expressions. In particular, this variable is no-zero if at the
+ expressions. In particular, this variable is non-zero if at the
end of a statement we should destroy any temporaries created
during that statement. Similarly, if, at the end of a block, we
should destroy any local variables in this block. Normally, this
variable is nonzero, since those are the normal semantics of
C++.
- However, in order to represent aggregate initialization code as
- tree structure, we use statement-expressions. The statements
- within the statement expression should not result in cleanups
- being run until the entire enclosing statement is complete.
-
This flag has no effect in C. */
int stmts_are_full_exprs_p;
};
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 8406432..055c1b2 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5367,17 +5367,8 @@ static tree
build_aggr_init_full_exprs (tree decl, tree init, int flags)
{
- int saved_stmts_are_full_exprs_p = 0;
- if (building_stmt_list_p ())
- {
- saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
- current_stmt_tree ()->stmts_are_full_exprs_p = 1;
- }
- init = build_aggr_init (decl, init, flags, tf_warning_or_error);
- if (building_stmt_list_p ())
- current_stmt_tree ()->stmts_are_full_exprs_p =
- saved_stmts_are_full_exprs_p;
- return init;
+ gcc_assert (stmts_are_full_exprs_p ());
+ return build_aggr_init (decl, init, flags, tf_warning_or_error);
}
/* Verify INIT (the initializer for DECL), and record the
@@ -5550,7 +5541,13 @@ check_initializer (tree decl, tree init, int flags, VEC(tree,gc) **cleanups)
if (init && TREE_CODE (init) != TREE_VEC)
{
+ /* In aggregate initialization of a variable, each element
+ initialization is a full-expression because there is no
+ enclosing expression. */
+ gcc_assert (stmts_are_full_exprs_p ());
+
init_code = store_init_value (decl, init, cleanups, flags);
+
if (pedantic && TREE_CODE (type) == ARRAY_TYPE
&& DECL_INITIAL (decl)
&& TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 7f6b8cd..ceecdef 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -5916,6 +5916,7 @@ push_to_top_level (void)
s->function_decl = current_function_decl;
s->unevaluated_operand = cp_unevaluated_operand;
s->inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
+ s->x_stmt_tree.stmts_are_full_exprs_p = true;
scope_chain = s;
current_function_decl = NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/init/aggr8.C b/gcc/testsuite/g++.dg/init/aggr8.C
new file mode 100644
index 0000000..7e6edc9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/aggr8.C
@@ -0,0 +1,19 @@
+// PR c++/51009
+
+struct A
+{
+ ~A();
+};
+
+struct B
+{
+ A a;
+ B(const A& = A());
+};
+
+struct C
+{
+ B b1, b2;
+};
+
+C c = {};