This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR c++/70590 (error: location references block not in block tree)


My recent change that avoided needlessly unsharing expressions during
constexpr evaluation introduced a regression.  If we reuse the result
of the same constexpr call from the constexpr_call_table in two
separate caller functions then both functions will be sharing this
reused tree in their function body.  Because the trees are shared, the
functions will clobber each other's assignments to the TREE_BLOCK of
these trees.  This eventually causes a verification ICE.

To stop this from happening, we could always unshare the result tree of
a constexpr call, as was previously done.  But conceptually it seems
better and perhaps safer to just unshare the final result of the entire
constexpr evaluation.  That's what this patch does.  Either approach
seems to fix the PR though.

gcc/cp/ChangeLog:

	PR c++/70590
	PR c++/70452
	* constexpr.c (cxx_eval_outermost_expression): Call unshare_expr
	on the result if applicable.

gcc/testsuite/ChangeLog:

	PR c++/70590
	PR c++/70452
	* g++.dg/pr70590.C: New test.
	* g++.dg/pr70590-2.C: New test.
---
 gcc/cp/constexpr.c               |  9 +++++++++
 gcc/testsuite/g++.dg/pr70590-2.C | 21 +++++++++++++++++++++
 gcc/testsuite/g++.dg/pr70590.C   | 25 +++++++++++++++++++++++++
 3 files changed, 55 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/pr70590-2.C
 create mode 100644 gcc/testsuite/g++.dg/pr70590.C

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 7f4bb04..d84377b 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -4172,6 +4172,12 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
   if (!non_constant_p && overflow_p)
     non_constant_p = true;
 
+  /* Unshare the result unless it's a CONSTRUCTOR in which case it's already
+     unshared.  */
+  bool should_unshare = true;
+  if (r == t || TREE_CODE (r) == CONSTRUCTOR)
+    should_unshare = false;
+
   if (non_constant_p && !allow_non_constant)
     return error_mark_node;
   else if (non_constant_p && TREE_CONSTANT (r))
@@ -4188,6 +4194,9 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
   else if (non_constant_p || r == t)
     return t;
 
+  if (should_unshare)
+    r = unshare_expr (r);
+
   if (TREE_CODE (r) == CONSTRUCTOR && CLASS_TYPE_P (TREE_TYPE (r)))
     {
       if (TREE_CODE (t) == TARGET_EXPR
diff --git a/gcc/testsuite/g++.dg/pr70590-2.C b/gcc/testsuite/g++.dg/pr70590-2.C
new file mode 100644
index 0000000..409c86e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr70590-2.C
@@ -0,0 +1,21 @@
+// PR c++/70590
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+
+int a;
+
+constexpr int *foo = &a;
+
+void blah (int *);
+
+int
+bar ()
+{
+  blah (foo);
+}
+
+int
+baz ()
+{
+  blah (foo);
+}
diff --git a/gcc/testsuite/g++.dg/pr70590.C b/gcc/testsuite/g++.dg/pr70590.C
new file mode 100644
index 0000000..4886200
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr70590.C
@@ -0,0 +1,25 @@
+// PR c++/70590
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+
+int a;
+
+constexpr int *
+foo ()
+{
+  return &a;
+}
+
+void blah (int *);
+
+int
+bar ()
+{
+  blah (foo ());
+}
+
+int
+baz ()
+{
+  blah (foo ());
+}
-- 
2.8.1.119.gb11c935


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]