Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
Yet another problem that started with r15-6052, compile time evaluation of
prvalues.
cp_fold_r/TARGET_EXPR sees:
TARGET_EXPR <D.2701, <<< Unknown tree: expr_stmt
D.2701.__p = TARGET_EXPR <D.2684, <<< Unknown tree: aggr_init_expr
3
f1
D.2684 >>>> >>>>
so when we call maybe_constant_init, the object we're initializing is D.2701,
and the init is the expr_stmt. We unwrap the EXPR_STMT/INIT_EXPR/TARGET_EXPR
in maybe_constant_init_1 and so end up evaluating the f1 call. But f1 returns
c2 whereas the type of D.2701 is ._anon_0 -- the closure.
So then we crash in replace_decl on:
gcc_checking_assert (same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (decl), TREE_TYPE (replacement)));
due to the mismatched types.
cxx_eval_outermost_constant_expr is already ready for the types to be
different, in which case the result isn't constant. But replace_decl
is called before that check.
I'm leaving the assert in replace_decl on purpose, maybe we'll find
another use for it.
PR c++/118986
gcc/cp/ChangeLog:
* constexpr.cc (cxx_eval_call_expression): Check that the types match
before calling replace_decl.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/constexpr-prvalue1.C: New test.
---
gcc/cp/constexpr.cc | 4 +++-
.../g++.dg/cpp2a/constexpr-prvalue1.C | 23 +++++++++++++++++++
2 files changed, 26 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-prvalue1.C
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 59dd0668af3..204cda2a222 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3390,7 +3390,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree
t,
current object under construction. */
if (!*non_constant_p && ctx->object
&& CLASS_TYPE_P (TREE_TYPE (res))
- && !is_empty_class (TREE_TYPE (res)))
+ && !is_empty_class (TREE_TYPE (res))
+ && same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (res), TREE_TYPE (ctx->object)))
if (replace_decl (&result, res, ctx->object))
{
cacheable = false;
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-prvalue1.C
b/gcc/testsuite/g++.dg/cpp2a/constexpr-prvalue1.C
new file mode 100644
index 00000000000..f4e704d9487
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-prvalue1.C
@@ -0,0 +1,23 @@
+// PR c++/118986
+// { dg-do compile { target c++20 } }
+// { dg-options "-O" }
+
+struct c1 {
+ constexpr c1(int *ptr) {}
+};
+struct c2 {
+ c1 _M_t;
+ constexpr ~c2() {}
+};
+constexpr inline
+c2 f1 ()
+{
+ return c2(new int);
+}
+
+void
+f ()
+{
+ auto l = [p = f1()](){};
+ [p = f1()](){};
+}
base-commit: ad2908ed4ec5eff3cad3fd142cde5c1fac4788e9
--
2.48.1