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