Patchwork C++ PATCH for c++/51009 (ICE regression with aggregate initializer)

login
register
mail settings
Submitter Jason Merrill
Date Dec. 1, 2011, 6:16 a.m.
Message ID <4ED71BAD.6040907@redhat.com>
Download mbox | patch
Permalink /patch/128647/
State New
Headers show

Comments

Jason Merrill - Dec. 1, 2011, 6:16 a.m.
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.

Patch

commit ed588cf8d90c740ea189727eecb7dac3b7c24320
Author: Jason Merrill <jason@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 = {};