diff mbox

C++ PATCH for c++/78689 (ICE on constructor with label)

Message ID CADzB+2kQbwO6-JzwjVqMD7GwaZ0QVH413e9i=13QSk1wu-Ed2g@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill Feb. 3, 2017, 10:42 p.m. UTC
My patch for the new inheriting constructor semantics changed
tree-inline.c to avoid copying non-taken branches, in order to avoid
trying to refer to parameters that are omitted from base constructor
clones; this overlooked that we might enter such branches via goto.
This patch reverts that change, and addresses the omitted parameter
issue in the front end by providing a suitable replacement.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit e4a9364d66494c3cfd6cf528d8176a02b24b9d00
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Feb 3 15:30:24 2017 -0500

            PR c++/78689 - ICE on constructor with label
    
    gcc/
            * tree-inline.c (copy_tree_body_r) [COND_EXPR]: Revert change to
            avoid copying non-taken branch.
    gcc/cp/
            * optimize.c (maybe_clone_body): Replace omitted parameters with
            null lvalues.
            * class.c (build_clone): Fix logic for omitting inherited parms.
diff mbox

Patch

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index d99ebcd..7ec07c9 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4818,7 +4818,7 @@  build_clone (tree fn, tree name)
 
   /* A base constructor inheriting from a virtual base doesn't get the
      arguments.  */
-  if (ctor_omit_inherited_parms (fn))
+  if (ctor_omit_inherited_parms (clone))
     DECL_CHAIN (DECL_CHAIN (DECL_ARGUMENTS (clone))) = NULL_TREE;
 
   for (parms = DECL_ARGUMENTS (clone); parms; parms = DECL_CHAIN (parms))
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index f61d035..933612c 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -621,9 +621,21 @@  maybe_clone_body (tree fn)
                  function.  */
               else
                 {
-                  decl_map->put (parm, clone_parm);
+		  tree replacement;
 		  if (clone_parm)
-		    clone_parm = DECL_CHAIN (clone_parm);
+		    {
+		      replacement = clone_parm;
+		      clone_parm = DECL_CHAIN (clone_parm);
+		    }
+		  else
+		    {
+		      /* Inheriting ctors can omit parameters from the base
+			 clone.  Replace them with null lvalues.  */
+		      tree reftype = build_reference_type (TREE_TYPE (parm));
+		      replacement = fold_convert (reftype, null_pointer_node);
+		      replacement = convert_from_reference (replacement);
+		    }
+                  decl_map->put (parm, replacement);
                 }
             }
 
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C
index 0c862f7..c0cf040 100644
--- a/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C
@@ -14,6 +14,9 @@  Z z(0); // OK: initialization of Y does not invoke default constructor of X
 // { dg-final { scan-assembler "_ZN1YCI21WEi" } }
 // { dg-final { scan-tree-dump "Y::Y ._2, _3.;" "gimple" } }
 
+// And that we aren't expecting the int, either.
+// { dg-final { scan-tree-dump-not "Y::Y.int\[^\n\]*int" "gimple" } }
+
 // And that we *are* passing the int along to V::V.
 // { dg-final { scan-assembler "_ZN1VCI21WEi" } }
 // { dg-final { scan-tree-dump "V::V .this, _1.;" "gimple" } }
diff --git a/gcc/testsuite/g++.dg/init/ctor12.C b/gcc/testsuite/g++.dg/init/ctor12.C
new file mode 100644
index 0000000..7c1aab72
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/ctor12.C
@@ -0,0 +1,14 @@ 
+// PR c++/78689 - ICE on constructor with label
+
+struct e {
+  e() {
+    goto aj;
+    if (0)
+    aj:;
+  }
+};
+
+void f()
+{
+  struct e x;
+}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index d63c70f..138b992 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1045,7 +1045,6 @@  copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
   copy_body_data *id = (copy_body_data *) data;
   tree fn = id->src_fn;
   tree new_block;
-  bool copied = false;
 
   /* Begin by recognizing trees that we'll completely rewrite for the
      inlining context.  Our output for these trees is completely
@@ -1242,40 +1241,10 @@  copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
 	  *walk_subtrees = 0;
 	  return NULL;
 	}
-      else if (TREE_CODE (*tp) == COND_EXPR)
-	{
-	  tree cond = TREE_OPERAND (*tp, 0);
-	  walk_tree (&cond, copy_tree_body_r, data, NULL);
-	  tree folded = fold (cond);
-	  if (TREE_CODE (folded) == INTEGER_CST)
-	    {
-	      /* Only copy the taken branch; for a C++ base constructor clone
-		 inherited from a virtual base, copying the other branch leads
-		 to references to parameters that were optimized away.  */
-	      tree branch = (integer_nonzerop (folded)
-			     ? TREE_OPERAND (*tp, 1)
-			     : TREE_OPERAND (*tp, 2));
-	      tree type = TREE_TYPE (*tp);
-	      if (VOID_TYPE_P (type)
-		  || type == TREE_TYPE (branch))
-		{
-		  *tp = branch;
-		  return copy_tree_body_r (tp, walk_subtrees, data);
-		}
-	    }
-	  /* Avoid copying the condition twice.  */
-	  copy_tree_r (tp, walk_subtrees, NULL);
-	  TREE_OPERAND (*tp, 0) = cond;
-	  walk_tree (&TREE_OPERAND (*tp, 1), copy_tree_body_r, data, NULL);
-	  walk_tree (&TREE_OPERAND (*tp, 2), copy_tree_body_r, data, NULL);
-	  *walk_subtrees = 0;
-	  copied = true;
-	}
 
       /* Here is the "usual case".  Copy this tree node, and then
 	 tweak some special cases.  */
-      if (!copied)
-	copy_tree_r (tp, walk_subtrees, NULL);
+      copy_tree_r (tp, walk_subtrees, NULL);
 
       /* If EXPR has block defined, map it to newly constructed block.
          When inlining we want EXPRs without block appear in the block