Commit 9f143008 by Jason Merrill

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.
parent 2523d721
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
......
......@@ -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;
......
......@@ -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();
......
// 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); });
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment