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());
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to