PR c++/78689 - ICE on constructor with label
authorJason Merrill <jason@redhat.com>
Fri, 3 Feb 2017 22:42:37 +0000 (17:42 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 3 Feb 2017 22:42:37 +0000 (17:42 -0500)
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.

From-SVN: r245172

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/optimize.c
gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C
gcc/testsuite/g++.dg/init/ctor12.C [new file with mode: 0644]
gcc/tree-inline.c

index 5bfbff5..044f720 100644 (file)
@@ -1,3 +1,9 @@
+2017-02-03  Jason Merrill  <jason@redhat.com>
+
+       PR c++/78689
+       * tree-inline.c (copy_tree_body_r) [COND_EXPR]: Revert change to
+       avoid copying non-taken branch.
+
 2017-02-03  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/79340
index f77e6cb..d032028 100644 (file)
@@ -1,5 +1,10 @@
 2017-02-03  Jason Merrill  <jason@redhat.com>
 
+       PR c++/78689 - ICE on constructor with label
+       * optimize.c (maybe_clone_body): Replace omitted parameters with
+       null lvalues.
+       * class.c (build_clone): Fix logic for omitting inherited parms.
+
        PR c++/12245 - excessive memory use
        * constexpr.c (maybe_constant_value): Fold maybe_constant_value_1
        back in.  Don't cache constants.
index d99ebcd..7ec07c9 100644 (file)
@@ -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))
index f61d035..933612c 100644 (file)
@@ -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);
                 }
             }
 
index 0c862f7..c0cf040 100644 (file)
@@ -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 (file)
index 0000000..7c1aab7
--- /dev/null
@@ -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;
+}
index d63c70f..138b992 100644 (file)
@@ -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