mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 00:36:06 +00:00
[clang][bytecode] Diagnose member calls on deleted blocks (#106529)
This requires a bit of restructuring of ctor calls when checking for a potential constant expression.
This commit is contained in:
parent
1f8f2ed66a
commit
df11ee213e
@ -305,14 +305,18 @@ bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
|
||||
|
||||
if (!Ptr.isLive()) {
|
||||
const auto &Src = S.Current->getSource(OpPC);
|
||||
bool IsTemp = Ptr.isTemporary();
|
||||
|
||||
S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
|
||||
if (Ptr.isDynamic()) {
|
||||
S.FFDiag(Src, diag::note_constexpr_access_deleted_object) << AK;
|
||||
} else {
|
||||
bool IsTemp = Ptr.isTemporary();
|
||||
S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
|
||||
|
||||
if (IsTemp)
|
||||
S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
|
||||
else
|
||||
S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
|
||||
if (IsTemp)
|
||||
S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
|
||||
else
|
||||
S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -2630,7 +2630,11 @@ inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
|
||||
if (!CheckCallable(S, OpPC, Func))
|
||||
return false;
|
||||
|
||||
if (Func->hasThisPointer() && S.checkingPotentialConstantExpression())
|
||||
// FIXME: The isConstructor() check here is not always right. The current
|
||||
// constant evaluator is somewhat inconsistent in when it allows a function
|
||||
// call when checking for a constant expression.
|
||||
if (Func->hasThisPointer() && S.checkingPotentialConstantExpression() &&
|
||||
!Func->isConstructor())
|
||||
return false;
|
||||
|
||||
if (!CheckCallDepth(S, OpPC))
|
||||
|
@ -110,6 +110,8 @@ DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk)
|
||||
Prev = nullptr;
|
||||
Root = this;
|
||||
|
||||
B.IsDynamic = Blk->IsDynamic;
|
||||
|
||||
// Transfer pointers.
|
||||
B.Pointers = Blk->Pointers;
|
||||
for (Pointer *P = Blk->Pointers; P; P = P->Next)
|
||||
|
@ -491,6 +491,14 @@ public:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// Checks if the storage has been dynamically allocated.
|
||||
bool isDynamic() const {
|
||||
if (isBlockPointer()) {
|
||||
assert(asBlockPointer().Pointee);
|
||||
return asBlockPointer().Pointee->isDynamic();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// Checks if the storage is a static temporary.
|
||||
bool isStaticTemporary() const { return isStatic() && isTemporary(); }
|
||||
|
||||
|
@ -579,6 +579,13 @@ namespace CastedDelete {
|
||||
// expected-note {{in call to}}
|
||||
}
|
||||
|
||||
constexpr void use_after_free_2() { // both-error {{never produces a constant expression}}
|
||||
struct X { constexpr void f() {} };
|
||||
X *p = new X;
|
||||
delete p;
|
||||
p->f(); // both-note {{member call on heap allocated object that has been deleted}}
|
||||
}
|
||||
|
||||
#else
|
||||
/// Make sure we reject this prior to C++20
|
||||
constexpr int a() { // both-error {{never produces a constant expression}}
|
||||
|
@ -86,7 +86,7 @@ namespace DefaultInit {
|
||||
|
||||
#if __cplusplus >= 202002L
|
||||
namespace SimpleActivate {
|
||||
constexpr int foo() { // ref-error {{never produces a constant expression}}
|
||||
constexpr int foo() { // both-error {{never produces a constant expression}}
|
||||
union {
|
||||
int a;
|
||||
int b;
|
||||
@ -94,8 +94,7 @@ namespace SimpleActivate {
|
||||
|
||||
Z.a = 10;
|
||||
Z.b = 20;
|
||||
return Z.a; // both-note {{read of member 'a' of union with active member 'b'}} \
|
||||
// ref-note {{read of member 'a' of union with active member 'b}}
|
||||
return Z.a; // both-note 2{{read of member 'a' of union with active member 'b'}}
|
||||
}
|
||||
static_assert(foo() == 20); // both-error {{not an integral constant expression}} \
|
||||
// both-note {{in call to}}
|
||||
@ -212,11 +211,10 @@ namespace Nested {
|
||||
int y;
|
||||
};
|
||||
|
||||
constexpr int foo() { // ref-error {{constexpr function never produces a constant expression}}
|
||||
constexpr int foo() { // both-error {{constexpr function never produces a constant expression}}
|
||||
U2 u;
|
||||
u.u.a = 10;
|
||||
int a = u.y; // both-note {{read of member 'y' of union with active member 'u' is not allowed in a constant expression}} \
|
||||
// ref-note {{read of member 'y' of union with active member 'u' is not allowed in a constant expression}}
|
||||
int a = u.y; // both-note 2{{read of member 'y' of union with active member 'u' is not allowed in a constant expression}}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -230,24 +228,22 @@ namespace Nested {
|
||||
}
|
||||
static_assert(foo2() == 10);
|
||||
|
||||
constexpr int foo3() { // ref-error {{constexpr function never produces a constant expression}}
|
||||
constexpr int foo3() { // both-error {{constexpr function never produces a constant expression}}
|
||||
U2 u;
|
||||
u.u.a = 10;
|
||||
int a = u.u.b; // both-note {{read of member 'b' of union with active member 'a' is not allowed in a constant expression}} \
|
||||
// ref-note {{read of member 'b' of union with active member 'a' is not allowed in a constant expression}}
|
||||
int a = u.u.b; // both-note 2{{read of member 'b' of union with active member 'a' is not allowed in a constant expression}}
|
||||
|
||||
return 1;
|
||||
}
|
||||
static_assert(foo3() == 1); // both-error {{not an integral constant expression}} \
|
||||
// both-note {{in call to}}
|
||||
|
||||
constexpr int foo4() { // ref-error {{constexpr function never produces a constant expression}}
|
||||
constexpr int foo4() { // both-error {{constexpr function never produces a constant expression}}
|
||||
U2 u;
|
||||
|
||||
u.x = 10;
|
||||
|
||||
return u.u.a;// both-note {{read of member 'u' of union with active member 'x' is not allowed in a constant expression}} \
|
||||
// ref-note {{read of member 'u' of union with active member 'x' is not allowed in a constant expression}}
|
||||
return u.u.a; // both-note 2{{read of member 'u' of union with active member 'x' is not allowed in a constant expression}}
|
||||
}
|
||||
static_assert(foo4() == 1); // both-error {{not an integral constant expression}} \
|
||||
// both-note {{in call to}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user