From: Jason Merrill Date: Fri, 3 Feb 2017 22:42:37 +0000 (-0500) Subject: PR c++/78689 - ICE on constructor with label X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=77095a6ab13996a38b0a360d8ef9fc6cc6bc5234;p=gcc.git 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. From-SVN: r245172 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5bfbff585a5..044f720e990 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2017-02-03 Jason Merrill + + 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 PR tree-optimization/79340 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f77e6cb985f..d032028d17c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2017-02-03 Jason Merrill + 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. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index d99ebcdc7df..7ec07c9c753 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 f61d035337f..933612ced76 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 0c862f7573f..c0cf040048c 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 00000000000..7c1aab7255c --- /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 d63c70f2a12..138b992552e 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