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.
This commit is contained in:
Richard Smith 2021-02-08 17:58:05 -08:00
parent c945dc4a50
commit 21e8bb8325
2 changed files with 36 additions and 2 deletions

View File

@ -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) {

View File

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