]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Fix up constexpr evaluation of deleting dtors [PR100495]
authorJakub Jelinek <jakub@redhat.com>
Tue, 7 Sep 2021 17:33:28 +0000 (19:33 +0200)
committerJakub Jelinek <jakub@redhat.com>
Tue, 7 Sep 2021 17:41:47 +0000 (19:41 +0200)
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.

2021-09-07  Jakub Jelinek  <jakub@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.

(cherry picked from commit 81f9718139cb1cc164ada411ada8cca9f32b8be8)

gcc/cp/constexpr.c
gcc/testsuite/g++.dg/cpp2a/constexpr-new21.C [new file with mode: 0644]

index 9f9121e4c45487801eed40067fd06011a38d03b6..cd81c7edb11cec6772aa1a074587ed6bd9aefe9d 100644 (file)
@@ -871,7 +871,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)))
@@ -2353,7 +2353,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
       *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))
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new21.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new21.C
new file mode 100644 (file)
index 0000000..8231e99
--- /dev/null
@@ -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);