[clang] 21e8bb8 - PR48606: The lifetime of a constexpr heap allocation always started

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 8 18:02:55 PST 2021


Author: Richard Smith
Date: 2021-02-08T17:58:05-08:00
New Revision: 21e8bb83253e1a2f4b6fad9b53cafe8c530a38e2

URL: https://github.com/llvm/llvm-project/commit/21e8bb83253e1a2f4b6fad9b53cafe8c530a38e2
DIFF: https://github.com/llvm/llvm-project/commit/21e8bb83253e1a2f4b6fad9b53cafe8c530a38e2.diff

LOG: PR48606: The lifetime of a constexpr heap allocation always started
during the same evaluation.

It looks like the only case for which this matters is determining
whether mutable subobjects of a heap allocation can be modified during
constant evaluation.

Added: 
    

Modified: 
    clang/lib/AST/ExprConstant.cpp
    clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 1ed9bbea84ee..d27f655011ae 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -3497,8 +3497,8 @@ static bool diagnoseMutableFields(EvalInfo &Info, const Expr *E, AccessKinds AK,
 static bool lifetimeStartedInEvaluation(EvalInfo &Info,
                                         APValue::LValueBase Base,
                                         bool MutableSubobject = false) {
-  // A temporary we created.
-  if (Base.getCallIndex())
+  // A temporary or transient heap allocation we created.
+  if (Base.getCallIndex() || Base.is<DynamicAllocLValue>())
     return true;
 
   switch (Info.IsEvaluatingDecl) {

diff  --git a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
index 3647526ff0af..097ca00640e9 100644
--- a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
+++ b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
@@ -176,3 +176,37 @@ constexpr bool construct_after_lifetime_2() {
   return true;
 }
 static_assert(construct_after_lifetime_2()); // expected-error {{}} expected-note {{in call}}
+
+namespace PR48606 {
+  struct A { mutable int n = 0; };
+
+  constexpr bool f() {
+    A a;
+    A *p = &a;
+    p->~A();
+    std::construct_at<A>(p);
+    return true;
+  }
+  static_assert(f());
+
+  constexpr bool g() {
+    A *p = new A;
+    p->~A();
+    std::construct_at<A>(p);
+    delete p;
+    return true;
+  }
+  static_assert(g());
+
+  constexpr bool h() {
+    std::allocator<A> alloc;
+    A *p = alloc.allocate(1);
+    std::construct_at<A>(p);
+    p->~A();
+    std::construct_at<A>(p);
+    p->~A();
+    alloc.deallocate(p);
+    return true;
+  }
+  static_assert(h());
+}


        


More information about the cfe-commits mailing list