Skip to content

Commit c869ef6

Browse files
authored
[clang][bytecode] Refactor Check* functions (#152300)
... so we don't have to create Pointer instances when we don't need them.
1 parent a445325 commit c869ef6

File tree

7 files changed

+123
-82
lines changed

7 files changed

+123
-82
lines changed

clang/lib/AST/ByteCode/EvalEmitter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ bool EvalEmitter::emitGetLocal(uint32_t I, const SourceInfo &Info) {
292292

293293
Block *B = getLocal(I);
294294

295-
if (!CheckLocalLoad(S, OpPC, Pointer(B)))
295+
if (!CheckLocalLoad(S, OpPC, B))
296296
return false;
297297

298298
S.Stk.push<T>(*reinterpret_cast<T *>(B->data()));

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 85 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -211,25 +211,26 @@ static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
211211
S.Note(VD->getLocation(), diag::note_declared_at);
212212
}
213213

214-
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
214+
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Block *B,
215215
AccessKinds AK) {
216-
if (auto ID = Ptr.getDeclID()) {
217-
if (!Ptr.isStaticTemporary())
216+
if (B->getDeclID()) {
217+
if (!(B->isStatic() && B->isTemporary()))
218218
return true;
219219

220220
const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
221-
Ptr.getDeclDesc()->asExpr());
221+
B->getDescriptor()->asExpr());
222222
if (!MTE)
223223
return true;
224224

225225
// FIXME(perf): Since we do this check on every Load from a static
226226
// temporary, it might make sense to cache the value of the
227227
// isUsableInConstantExpressions call.
228-
if (!MTE->isUsableInConstantExpressions(S.getASTContext()) &&
229-
Ptr.block()->getEvalID() != S.Ctx.getEvalID()) {
228+
if (B->getEvalID() != S.Ctx.getEvalID() &&
229+
!MTE->isUsableInConstantExpressions(S.getASTContext())) {
230230
const SourceInfo &E = S.Current->getSource(OpPC);
231231
S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
232-
S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
232+
S.Note(B->getDescriptor()->getLocation(),
233+
diag::note_constexpr_temporary_here);
233234
return false;
234235
}
235236
}
@@ -658,17 +659,19 @@ static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
658659
return false;
659660
}
660661

661-
bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
662-
AccessKinds AK) {
662+
bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
663+
AccessKinds AK) {
663664
assert(Ptr.isLive());
665+
assert(!Ptr.isInitialized());
666+
return DiagnoseUninitialized(S, OpPC, Ptr.isExtern(), Ptr.getDeclDesc(), AK);
667+
}
664668

665-
if (Ptr.isInitialized())
666-
return true;
667-
668-
if (Ptr.isExtern() && S.checkingPotentialConstantExpression())
669+
bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern,
670+
const Descriptor *Desc, AccessKinds AK) {
671+
if (Extern && S.checkingPotentialConstantExpression())
669672
return false;
670673

671-
if (const auto *VD = Ptr.getDeclDesc()->asVarDecl();
674+
if (const auto *VD = Desc->asVarDecl();
672675
VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
673676

674677
if (VD == S.EvaluatingDecl &&
@@ -703,9 +706,9 @@ bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
703706
return false;
704707
}
705708

706-
static bool CheckLifetime(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
709+
static bool CheckLifetime(InterpState &S, CodePtr OpPC, Lifetime LT,
707710
AccessKinds AK) {
708-
if (Ptr.getLifetime() == Lifetime::Started)
711+
if (LT == Lifetime::Started)
709712
return true;
710713

711714
if (!S.checkingPotentialConstantExpression()) {
@@ -715,11 +718,11 @@ static bool CheckLifetime(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
715718
return false;
716719
}
717720

718-
static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
719-
if (!Ptr.isWeak())
721+
static bool CheckWeak(InterpState &S, CodePtr OpPC, const Block *B) {
722+
if (!B->isWeak())
720723
return true;
721724

722-
const auto *VD = Ptr.getDeclDesc()->asVarDecl();
725+
const auto *VD = B->getDescriptor()->asVarDecl();
723726
assert(VD);
724727
S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_var_init_weak)
725728
<< VD;
@@ -732,32 +735,56 @@ static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
732735
// ones removed that are impossible on primitive global values.
733736
// For example, since those can't be members of structs, they also can't
734737
// be mutable.
735-
bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
736-
if (!CheckExtern(S, OpPC, Ptr))
738+
bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
739+
const auto &Desc =
740+
*reinterpret_cast<const GlobalInlineDescriptor *>(B->rawData());
741+
if (!CheckExtern(S, OpPC, Pointer(const_cast<Block *>(B))))
737742
return false;
738-
if (!CheckConstant(S, OpPC, Ptr))
739-
return false;
740-
if (!CheckDummy(S, OpPC, Ptr, AK_Read))
743+
if (!CheckConstant(S, OpPC, B->getDescriptor()))
741744
return false;
742-
if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
745+
if (!CheckDummy(S, OpPC, B, AK_Read))
743746
return false;
744-
if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
747+
if (Desc.InitState != GlobalInitState::Initialized)
748+
return DiagnoseUninitialized(S, OpPC, B->isExtern(), B->getDescriptor(),
749+
AK_Read);
750+
if (!CheckTemporary(S, OpPC, B, AK_Read))
745751
return false;
746-
if (!CheckWeak(S, OpPC, Ptr))
752+
if (!CheckWeak(S, OpPC, B))
747753
return false;
748-
if (!CheckVolatile(S, OpPC, Ptr, AK_Read))
754+
if (B->getDescriptor()->IsVolatile) {
755+
if (!S.getLangOpts().CPlusPlus)
756+
return Invalid(S, OpPC);
757+
758+
const ValueDecl *D = B->getDescriptor()->asValueDecl();
759+
S.FFDiag(S.Current->getLocation(OpPC),
760+
diag::note_constexpr_access_volatile_obj, 1)
761+
<< AK_Read << 1 << D;
762+
S.Note(D->getLocation(), diag::note_constexpr_volatile_here) << 1;
749763
return false;
764+
}
750765
return true;
751766
}
752767

753768
// Similarly, for local loads.
754-
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
755-
if (!CheckLifetime(S, OpPC, Ptr, AK_Read))
756-
return false;
757-
if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
758-
return false;
759-
if (!CheckVolatile(S, OpPC, Ptr, AK_Read))
769+
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
770+
assert(!B->isExtern());
771+
const auto &Desc = *reinterpret_cast<const InlineDescriptor *>(B->rawData());
772+
if (!CheckLifetime(S, OpPC, Desc.LifeState, AK_Read))
773+
return false;
774+
if (!Desc.IsInitialized)
775+
return DiagnoseUninitialized(S, OpPC, /*Extern=*/false, B->getDescriptor(),
776+
AK_Read);
777+
if (B->getDescriptor()->IsVolatile) {
778+
if (!S.getLangOpts().CPlusPlus)
779+
return Invalid(S, OpPC);
780+
781+
const ValueDecl *D = B->getDescriptor()->asValueDecl();
782+
S.FFDiag(S.Current->getLocation(OpPC),
783+
diag::note_constexpr_access_volatile_obj, 1)
784+
<< AK_Read << 1 << D;
785+
S.Note(D->getLocation(), diag::note_constexpr_volatile_here) << 1;
760786
return false;
787+
}
761788
return true;
762789
}
763790

@@ -769,19 +796,19 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
769796
return false;
770797
if (!CheckConstant(S, OpPC, Ptr))
771798
return false;
772-
if (!CheckDummy(S, OpPC, Ptr, AK))
799+
if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK))
773800
return false;
774801
if (!CheckRange(S, OpPC, Ptr, AK))
775802
return false;
776803
if (!CheckActive(S, OpPC, Ptr, AK))
777804
return false;
778-
if (!CheckLifetime(S, OpPC, Ptr, AK))
779-
return false;
780-
if (!CheckInitialized(S, OpPC, Ptr, AK))
805+
if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK))
781806
return false;
782-
if (!CheckTemporary(S, OpPC, Ptr, AK))
807+
if (!Ptr.isInitialized())
808+
return DiagnoseUninitialized(S, OpPC, Ptr, AK);
809+
if (Ptr.isBlockPointer() && !CheckTemporary(S, OpPC, Ptr.block(), AK))
783810
return false;
784-
if (!CheckWeak(S, OpPC, Ptr))
811+
if (Ptr.isBlockPointer() && !CheckWeak(S, OpPC, Ptr.block()))
785812
return false;
786813
if (!CheckMutable(S, OpPC, Ptr))
787814
return false;
@@ -798,21 +825,21 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
798825
if (!CheckConstant(S, OpPC, Ptr))
799826
return false;
800827

801-
if (!CheckDummy(S, OpPC, Ptr, AK_Read))
828+
if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Read))
802829
return false;
803830
if (!CheckExtern(S, OpPC, Ptr))
804831
return false;
805832
if (!CheckRange(S, OpPC, Ptr, AK_Read))
806833
return false;
807834
if (!CheckActive(S, OpPC, Ptr, AK_Read))
808835
return false;
809-
if (!CheckLifetime(S, OpPC, Ptr, AK_Read))
810-
return false;
811-
if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
836+
if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK_Read))
812837
return false;
813-
if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
838+
if (!Ptr.isInitialized())
839+
return DiagnoseUninitialized(S, OpPC, Ptr, AK_Read);
840+
if (Ptr.isBlockPointer() && !CheckTemporary(S, OpPC, Ptr.block(), AK_Read))
814841
return false;
815-
if (!CheckWeak(S, OpPC, Ptr))
842+
if (Ptr.isBlockPointer() && !CheckWeak(S, OpPC, Ptr.block()))
816843
return false;
817844
if (!CheckMutable(S, OpPC, Ptr))
818845
return false;
@@ -822,9 +849,9 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
822849
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
823850
if (!CheckLive(S, OpPC, Ptr, AK_Assign))
824851
return false;
825-
if (!CheckDummy(S, OpPC, Ptr, AK_Assign))
852+
if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Assign))
826853
return false;
827-
if (!CheckLifetime(S, OpPC, Ptr, AK_Assign))
854+
if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK_Assign))
828855
return false;
829856
if (!CheckExtern(S, OpPC, Ptr))
830857
return false;
@@ -1098,12 +1125,11 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
10981125
return diagnoseUnknownDecl(S, OpPC, D);
10991126
}
11001127

1101-
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
1102-
AccessKinds AK) {
1103-
if (!Ptr.isDummy())
1128+
bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK) {
1129+
const Descriptor *Desc = B->getDescriptor();
1130+
if (!Desc->isDummy())
11041131
return true;
11051132

1106-
const Descriptor *Desc = Ptr.getDeclDesc();
11071133
const ValueDecl *D = Desc->asValueDecl();
11081134
if (!D)
11091135
return false;
@@ -1426,7 +1452,7 @@ static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
14261452
bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
14271453
if (!CheckLive(S, OpPC, Ptr, AK_Destroy))
14281454
return false;
1429-
if (!CheckTemporary(S, OpPC, Ptr, AK_Destroy))
1455+
if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Destroy))
14301456
return false;
14311457
if (!CheckRange(S, OpPC, Ptr, AK_Destroy))
14321458
return false;
@@ -1749,7 +1775,7 @@ static void startLifetimeRecurse(const Pointer &Ptr) {
17491775

17501776
bool StartLifetime(InterpState &S, CodePtr OpPC) {
17511777
const auto &Ptr = S.Stk.peek<Pointer>();
1752-
if (!CheckDummy(S, OpPC, Ptr, AK_Destroy))
1778+
if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
17531779
return false;
17541780
startLifetimeRecurse(Ptr.narrow());
17551781
return true;
@@ -1780,7 +1806,7 @@ static void endLifetimeRecurse(const Pointer &Ptr) {
17801806
/// Ends the lifetime of the peek'd pointer.
17811807
bool EndLifetime(InterpState &S, CodePtr OpPC) {
17821808
const auto &Ptr = S.Stk.peek<Pointer>();
1783-
if (!CheckDummy(S, OpPC, Ptr, AK_Destroy))
1809+
if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
17841810
return false;
17851811
endLifetimeRecurse(Ptr.narrow());
17861812
return true;
@@ -1789,7 +1815,7 @@ bool EndLifetime(InterpState &S, CodePtr OpPC) {
17891815
/// Ends the lifetime of the pop'd pointer.
17901816
bool EndLifetimePop(InterpState &S, CodePtr OpPC) {
17911817
const auto &Ptr = S.Stk.pop<Pointer>();
1792-
if (!CheckDummy(S, OpPC, Ptr, AK_Destroy))
1818+
if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
17931819
return false;
17941820
endLifetimeRecurse(Ptr.narrow());
17951821
return true;
@@ -1804,16 +1830,16 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
18041830

18051831
// Similar to CheckStore(), but with the additional CheckTemporary() call and
18061832
// the AccessKinds are different.
1807-
if (!CheckTemporary(S, OpPC, Ptr, AK_Construct))
1833+
if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Construct))
18081834
return false;
18091835
if (!CheckLive(S, OpPC, Ptr, AK_Construct))
18101836
return false;
1811-
if (!CheckDummy(S, OpPC, Ptr, AK_Construct))
1837+
if (!CheckDummy(S, OpPC, Ptr.block(), AK_Construct))
18121838
return false;
18131839

18141840
// CheckLifetime for this and all base pointers.
18151841
for (Pointer P = Ptr;;) {
1816-
if (!CheckLifetime(S, OpPC, P, AK_Construct))
1842+
if (!CheckLifetime(S, OpPC, P.getLifetime(), AK_Construct))
18171843
return false;
18181844

18191845
if (P.isRoot())

0 commit comments

Comments
 (0)