From: Jason Merrill Date: Sat, 15 Apr 2023 02:40:43 +0000 (-0400) Subject: c++: constexpr aggregate destruction [PR109357] X-Git-Tag: upstream/13.1.0~51 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=13669741e673fa6a7b7c8d68f992e58ecd393160;p=platform%2Fupstream%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 3de60cf..d109776 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -7230,16 +7230,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->put_value (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->put_value (slot, r); if (ctx->save_exprs) ctx->save_exprs->safe_push (slot); if (lval) return slot; + if (is_complex) + r = ctx->global->get_value (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 0000000..d34c27e --- /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 = {"", ""}; }