diff options
author | Jason Merrill <jason@redhat.com> | 2023-04-14 22:40:43 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2023-04-15 12:35:15 -0400 |
commit | 13669741e673fa6a7b7c8d68f992e58ecd393160 (patch) | |
tree | f190676b790120b2bb39791625db4b245e47b6bd /gcc | |
parent | de0ee9d14165eebb3d31c84e98260c05c3b33acb (diff) | |
download | gcc-13669741e673fa6a7b7c8d68f992e58ecd393160.zip gcc-13669741e673fa6a7b7c8d68f992e58ecd393160.tar.gz gcc-13669741e673fa6a7b7c8d68f992e58ecd393160.tar.bz2 |
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/constexpr.cc | 15 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-dtor15.C | 19 |
2 files changed, 30 insertions, 4 deletions
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 = {"", ""}; } |