Hi! We do not save bodies of constexpr clones and instead evaluate the bodies of the constexpr functions they were cloned from. I believe that is just fine for constructors because complete vs. base ctors differ only in classes that have virtual bases and such constructors aren't constexpr, similarly complete/base destructors. But as the testcase below shows, for deleting destructors it is not fine, deleting dtors while marked as clones in fact are just artificial functions with synthetized body which calls the user destructor and deallocation.
So, either we'd need to evaluate the destructor and afterwards synthetize and evaluate the deallocation, or we can just save and use the deleting dtors bodies. The latter seems much easier to me. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/11.3? 2021-09-07 Jakub Jelinek <ja...@redhat.com> PR c++/100495 * constexpr.c (maybe_save_constexpr_fundef): Save body even for constexpr deleting dtors. (cxx_eval_call_expression): Don't use DECL_CLONED_FUNCTION for deleting dtors. * g++.dg/cpp2a/constexpr-new21.C: New test. --- gcc/cp/constexpr.c.jj 2021-09-01 11:37:41.889557426 +0200 +++ gcc/cp/constexpr.c 2021-09-06 13:05:04.098652914 +0200 @@ -865,7 +865,7 @@ maybe_save_constexpr_fundef (tree fun) if (processing_template_decl || !DECL_DECLARED_CONSTEXPR_P (fun) || cp_function_chain->invalid_constexpr - || DECL_CLONED_FUNCTION_P (fun)) + || (DECL_CLONED_FUNCTION_P (fun) && !DECL_DELETING_DESTRUCTOR_P (fun))) return; if (!is_valid_constexpr_fn (fun, !DECL_GENERATED_P (fun))) @@ -2372,7 +2372,7 @@ cxx_eval_call_expression (const constexp *non_constant_p = true; return t; } - if (DECL_CLONED_FUNCTION_P (fun)) + if (DECL_CLONED_FUNCTION_P (fun) && !DECL_DELETING_DESTRUCTOR_P (fun)) fun = DECL_CLONED_FUNCTION (fun); if (is_ubsan_builtin_p (fun)) --- gcc/testsuite/g++.dg/cpp2a/constexpr-new21.C.jj 2021-09-06 13:09:59.326484091 +0200 +++ gcc/testsuite/g++.dg/cpp2a/constexpr-new21.C 2021-09-06 13:08:46.574511401 +0200 @@ -0,0 +1,17 @@ +// PR c++/100495 +// { dg-do compile { target c++20 } } + +struct S { + constexpr virtual ~S () {} +}; + +constexpr bool +foo () +{ + S *p = new S (); + delete p; + return true; +} + +constexpr bool x = foo (); +static_assert (x); Jakub