[C++] Fix replace_placeholders (PR c++/83556)

Message ID 20171223082851.GR2353@tucnak
State New
Headers show
Series
  • [C++] Fix replace_placeholders (PR c++/83556)
Related show

Commit Message

Jakub Jelinek Dec. 23, 2017, 8:28 a.m.
Hi!

Recently I've changed replace_placeholders to walk trees without duplicates
to avoid compile time explosion with lots of nested SAVE_EXPRs.
The problem as the following testcase shows is that it also prevents
replacement of PLACEHOLDER_EXPRs we want to replace, if the same
PLACEHOLDER_EXPR appears multiple time in the expression.

The following patch changes the walk_tree not to use pset itself, but rather
stops walking children if we've seen some tree already.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/7.3?

2017-12-23  Jakub Jelinek  <jakub@redhat.com>

	PR c++/83556
	* tree.c (replace_placeholders_r): Pass NULL as last argument to
	cp_walk_tree instead of d->pset.  If non-TREE_CONSTANT and
	non-PLACEHOLDER_EXPR tree has been seen already, set *walk_subtrees
	to false and return.
	(replace_placeholders): Pass NULL instead of &pset as last argument
	to cp_walk_tree.

	* g++.dg/cpp0x/pr83556.C: New test.


	Jakub

Comments

Nathan Sidwell Jan. 2, 2018, 4:38 p.m. | #1
On 12/23/2017 03:28 AM, Jakub Jelinek wrote:
> Hi!

> 

> Recently I've changed replace_placeholders to walk trees without duplicates

> to avoid compile time explosion with lots of nested SAVE_EXPRs.

> The problem as the following testcase shows is that it also prevents

> replacement of PLACEHOLDER_EXPRs we want to replace, if the same

> PLACEHOLDER_EXPR appears multiple time in the expression.

> 

> The following patch changes the walk_tree not to use pset itself, but rather

> stops walking children if we've seen some tree already.

> 

> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/7.3?


ok, thanks.
nathan

-- 
Nathan Sidwell

Patch

--- gcc/cp/tree.c.jj	2017-12-15 16:10:37.000000000 +0100
+++ gcc/cp/tree.c	2017-12-22 23:24:16.720428548 +0100
@@ -3106,6 +3106,11 @@  replace_placeholders_r (tree* t, int* wa
       {
 	constructor_elt *ce;
 	vec<constructor_elt,va_gc> *v = CONSTRUCTOR_ELTS (*t);
+	if (d->pset->add (*t))
+	  {
+	    *walk_subtrees = false;
+	    return NULL_TREE;
+	  }
 	for (unsigned i = 0; vec_safe_iterate (v, i, &ce); ++i)
 	  {
 	    tree *valp = &ce->value;
@@ -3125,7 +3130,7 @@  replace_placeholders_r (tree* t, int* wa
 		  valp = &TARGET_EXPR_INITIAL (*valp);
 	      }
 	    d->obj = subob;
-	    cp_walk_tree (valp, replace_placeholders_r, data_, d->pset);
+	    cp_walk_tree (valp, replace_placeholders_r, data_, NULL);
 	    d->obj = obj;
 	  }
 	*walk_subtrees = false;
@@ -3133,6 +3138,8 @@  replace_placeholders_r (tree* t, int* wa
       }
 
     default:
+      if (d->pset->add (*t))
+	*walk_subtrees = false;
       break;
     }
 
@@ -3161,7 +3168,7 @@  replace_placeholders (tree exp, tree obj
   replace_placeholders_t data = { obj, false, &pset };
   if (TREE_CODE (exp) == TARGET_EXPR)
     tp = &TARGET_EXPR_INITIAL (exp);
-  cp_walk_tree (tp, replace_placeholders_r, &data, &pset);
+  cp_walk_tree (tp, replace_placeholders_r, &data, NULL);
   if (seen_p)
     *seen_p = data.seen;
   return exp;
--- gcc/testsuite/g++.dg/cpp0x/pr83556.C.jj	2017-12-22 23:30:10.771126002 +0100
+++ gcc/testsuite/g++.dg/cpp0x/pr83556.C	2017-12-22 23:29:21.000000000 +0100
@@ -0,0 +1,28 @@ 
+// PR c++/83556
+// { dg-do run { target c++11 } }
+
+int
+foo ()
+{
+  return 1;
+}
+
+struct A
+{
+  int a = foo ();
+  int b = 1;
+  int c = a ? 1 * b : 2 * b;
+};
+
+struct B
+{
+  A d {};
+};
+
+int
+main ()
+{
+  B e {};
+  if (e.d.c != 1)
+    __builtin_abort ();
+}