From: Jason Merrill Date: Sat, 15 Apr 2023 02:40:43 +0000 (-0400) Subject: c++: constexpr aggregate destruction [PR109357] X-Git-Tag: releases/gcc-12.3.0~71 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=618b90f5688fa7c0923a3e07a0741c6ede0e6e4e;p=thirdparty%2Fgcc.git c++: constexpr aggregate destruction [PR109357] We were assuming that the result of evaluation of TARGET_EXPR_INITIAL would always be the new value of the temporary, but that's not necessarily true when the initializer is complex (i.e. target_expr_needs_replace). In that case evaluating the initializer initializes the temporary as a side-effect. PR c++/109357 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_constant_expression) [TARGET_EXPR]: Check for complex initializer. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/constexpr-dtor15.C: New test. --- diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index a67a7da31ef1..b4e2898d90b7 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -6853,16 +6853,23 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, non_constant_p, overflow_p); if (*non_constant_p) break; - /* Adjust the type of the result to the type of the temporary. */ - r = adjust_temp_type (type, r); + /* If the initializer is complex, evaluate it to initialize slot. */ + bool is_complex = target_expr_needs_replace (t); + if (!is_complex) + { + r = unshare_constructor (r); + /* Adjust the type of the result to the type of the temporary. */ + r = adjust_temp_type (type, r); + ctx->global->values.put (slot, r); + } if (TARGET_EXPR_CLEANUP (t) && !CLEANUP_EH_ONLY (t)) ctx->global->cleanups->safe_push (TARGET_EXPR_CLEANUP (t)); - r = unshare_constructor (r); - ctx->global->values.put (slot, r); if (ctx->save_exprs) ctx->save_exprs->safe_push (slot); if (lval) return slot; + if (is_complex) + r = *ctx->global->values.get (slot); } break; diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor15.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor15.C new file mode 100644 index 000000000000..d34c27eee45e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor15.C @@ -0,0 +1,19 @@ +// PR c++/109357 +// { dg-do compile { target c++20 } } +// { dg-prune-output "used but never defined" } + +struct basic_string { + char _M_local_buf; + basic_string(); + constexpr basic_string(const char *) {} + constexpr ~basic_string(); + constexpr basic_string& operator=(basic_string); +}; +struct S1 { + basic_string x; + basic_string y; +} s1; +struct s2 { + ~s2(); +}; +s2::~s2() { s1 = {"", ""}; }