[gcc/devel/ranger] c++: Fix reuse of class constants [PR94453]

Aldy Hernandez aldyh@gcc.gnu.org
Wed Jun 17 20:11:07 GMT 2020


https://gcc.gnu.org/g:9f143008c73c60e02634d6b433139a035ef7bb65

commit 9f143008c73c60e02634d6b433139a035ef7bb65
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Apr 4 11:04:55 2020 -0400

    c++: Fix reuse of class constants [PR94453]
    
    The testcase hit an ICE trying to expand a TARGET_EXPR temporary cached from
    the other lambda-expression.  This patch fixes this in two ways:
    
    1) Avoid reusing a TARGET_EXPR from another function.
    2) Avoid ending up with a TARGET_EXPR at all; the use of 'p' had become
    <TARGET_EXPR<NON_LVALUE_EXPR<TARGET_EXPR ...>>>, which doesn't make any
    sense.
    
    gcc/cp/ChangeLog
    2020-04-04  Jason Merrill  <jason@redhat.com>
    
            PR c++/94453
            * constexpr.c (maybe_constant_value): Use break_out_target_exprs.
            * expr.c (mark_use) [VIEW_CONVERT_EXPR]: Don't wrap a TARGET_EXPR in
            NON_LVALUE_EXPR.

Diff:
---
 gcc/cp/ChangeLog                                   |  7 ++++++
 gcc/cp/constexpr.c                                 |  2 +-
 gcc/cp/expr.c                                      | 22 +++++++++++++----
 .../g++.dg/cpp0x/lambda/lambda-constexpr1.C        | 28 ++++++++++++++++++++++
 4 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 14038ccfe90..f8229368eb9 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2020-04-04  Jason Merrill  <jason@redhat.com>
+
+	PR c++/94453
+	* constexpr.c (maybe_constant_value): Use break_out_target_exprs.
+	* expr.c (mark_use) [VIEW_CONVERT_EXPR]: Don't wrap a TARGET_EXPR in
+	NON_LVALUE_EXPR.
+
 2020-04-04  Jakub Jelinek  <jakub@redhat.com>
 
 	PR debug/94441
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 91f0c3ba269..8c693ea89ef 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -6793,7 +6793,7 @@ maybe_constant_value (tree t, tree decl, bool manifestly_const_eval,
       r = *cached;
       if (r != t)
 	{
-	  r = unshare_expr_without_location (r);
+	  r = break_out_target_exprs (r, /*clear_loc*/true);
 	  protected_set_expr_location (r, EXPR_LOCATION (t));
 	}
       return r;
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 04e4418c671..9b535708c57 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -195,11 +195,23 @@ mark_use (tree expr, bool rvalue_p, bool read_p,
 	  tree nop = RECUR (op);
 	  if (nop == error_mark_node)
 	    return error_mark_node;
-	  TREE_OPERAND (expr, 0) = nop;
-	  /* If we're replacing a DECL with a constant, we also need to change
-	     the TREE_CODE of the location wrapper.  */
-	  if (op != nop && rvalue_p)
-	    TREE_SET_CODE (expr, NON_LVALUE_EXPR);
+	  else if (op == nop)
+	    /* No change.  */;
+	  else if (DECL_P (nop) || CONSTANT_CLASS_P (nop))
+	    {
+	      /* Reuse the location wrapper.  */
+	      TREE_OPERAND (expr, 0) = nop;
+	      /* If we're replacing a DECL with a constant, we also need to
+		 change the TREE_CODE of the location wrapper.  */
+	      if (rvalue_p)
+		TREE_SET_CODE (expr, NON_LVALUE_EXPR);
+	    }
+	  else
+	    {
+	      /* Drop the location wrapper.  */
+	      expr = nop;
+	      protected_set_expr_location (expr, loc);
+	    }
 	  return expr;
 	}
       gcc_fallthrough();
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr1.C
new file mode 100644
index 00000000000..7cb1e239ebb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr1.C
@@ -0,0 +1,28 @@
+// PR c++/94453
+// { dg-do compile { target c++11 } }
+
+void *ay();
+template <typename f> f ay() { return *static_cast<f *>(ay()); }
+template <typename h>
+void bf() {
+  ay<h>()();
+}
+struct az {
+  template <typename h>
+  az(h);
+  using bk = void (*)();
+  bk bl;
+};
+template <typename h>
+az::az(h) { bl = bf<h>; }
+struct A {};
+void da(az);
+void di(A, int);
+void dk(A, az, az);
+void b() {
+  int data = 0;
+  auto n = [] {};
+  constexpr auto p = A{};
+  auto q = [=] { di(p, data); };
+  da([=] { dk(p, n, q); });
+}


More information about the Gcc-cvs mailing list