Skip to content

Commit ddfc7e2

Browse files
committed
[clang][Interp] Emit more dummy pointers in C++ mode
1 parent 325f512 commit ddfc7e2

File tree

6 files changed

+59
-33
lines changed

6 files changed

+59
-33
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3213,19 +3213,16 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
32133213
// we haven't seen yet.
32143214
if (Ctx.getLangOpts().CPlusPlus) {
32153215
if (const auto *VD = dyn_cast<VarDecl>(D)) {
3216-
// Dummy for static locals
3217-
if (VD->isStaticLocal()) {
3218-
if (std::optional<unsigned> I = P.getOrCreateDummy(D))
3219-
return this->emitGetPtrGlobal(*I, E);
3220-
return false;
3221-
}
32223216
// Visit local const variables like normal.
32233217
if (VD->isLocalVarDecl() && VD->getType().isConstQualified()) {
32243218
if (!this->visitVarDecl(VD))
32253219
return false;
32263220
// Retry.
32273221
return this->VisitDeclRefExpr(E);
32283222
}
3223+
3224+
if (VD->hasExternalStorage())
3225+
return this->emitInvalidDeclRef(E, E);
32293226
}
32303227
} else {
32313228
if (const auto *VD = dyn_cast<VarDecl>(D);
@@ -3235,11 +3232,11 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
32353232
// Retry.
32363233
return this->VisitDeclRefExpr(E);
32373234
}
3238-
3239-
if (std::optional<unsigned> I = P.getOrCreateDummy(D))
3240-
return this->emitGetPtrGlobal(*I, E);
32413235
}
32423236

3237+
if (std::optional<unsigned> I = P.getOrCreateDummy(D))
3238+
return this->emitGetPtrGlobal(*I, E);
3239+
32433240
return this->emitInvalidDeclRef(E, E);
32443241
}
32453242

clang/lib/AST/Interp/Interp.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,6 @@ static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
285285
return CheckConstant(S, OpPC, Ptr.getDeclDesc());
286286
}
287287

288-
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
289-
return !Ptr.isDummy();
290-
}
291-
292288
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
293289
CheckSubobjectKind CSK) {
294290
if (!Ptr.isZero())
@@ -595,10 +591,8 @@ bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
595591
return true;
596592
}
597593

598-
/// We aleady know the given DeclRefExpr is invalid for some reason,
599-
/// now figure out why and print appropriate diagnostics.
600-
bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
601-
const ValueDecl *D = DR->getDecl();
594+
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC,
595+
const ValueDecl *D) {
602596
const SourceInfo &E = S.Current->getSource(OpPC);
603597

604598
if (isa<ParmVarDecl>(D)) {
@@ -621,10 +615,28 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
621615
return false;
622616
}
623617
}
624-
625618
return false;
626619
}
627620

621+
/// We aleady know the given DeclRefExpr is invalid for some reason,
622+
/// now figure out why and print appropriate diagnostics.
623+
bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
624+
const ValueDecl *D = DR->getDecl();
625+
return diagnoseUnknownDecl(S, OpPC, D);
626+
}
627+
628+
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
629+
if (!Ptr.isDummy())
630+
return true;
631+
632+
const Descriptor *Desc = Ptr.getDeclDesc();
633+
const ValueDecl *D = Desc->asValueDecl();
634+
if (!D)
635+
return false;
636+
637+
return diagnoseUnknownDecl(S, OpPC, D);
638+
}
639+
628640
bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F,
629641
const CallExpr *CE, unsigned ArgSize) {
630642
auto Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());

clang/lib/AST/Interp/Interp.h

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,8 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
572572
template <PrimType Name, class T = typename PrimConv<Name>::T>
573573
bool Inc(InterpState &S, CodePtr OpPC) {
574574
const Pointer &Ptr = S.Stk.pop<Pointer>();
575-
575+
if (Ptr.isDummy())
576+
return false;
576577
if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
577578
return false;
578579

@@ -585,7 +586,8 @@ bool Inc(InterpState &S, CodePtr OpPC) {
585586
template <PrimType Name, class T = typename PrimConv<Name>::T>
586587
bool IncPop(InterpState &S, CodePtr OpPC) {
587588
const Pointer &Ptr = S.Stk.pop<Pointer>();
588-
589+
if (Ptr.isDummy())
590+
return false;
589591
if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
590592
return false;
591593

@@ -599,7 +601,8 @@ bool IncPop(InterpState &S, CodePtr OpPC) {
599601
template <PrimType Name, class T = typename PrimConv<Name>::T>
600602
bool Dec(InterpState &S, CodePtr OpPC) {
601603
const Pointer &Ptr = S.Stk.pop<Pointer>();
602-
604+
if (Ptr.isDummy())
605+
return false;
603606
if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
604607
return false;
605608

@@ -612,7 +615,8 @@ bool Dec(InterpState &S, CodePtr OpPC) {
612615
template <PrimType Name, class T = typename PrimConv<Name>::T>
613616
bool DecPop(InterpState &S, CodePtr OpPC) {
614617
const Pointer &Ptr = S.Stk.pop<Pointer>();
615-
618+
if (Ptr.isDummy())
619+
return false;
616620
if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
617621
return false;
618622

@@ -641,7 +645,8 @@ bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
641645

642646
inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
643647
const Pointer &Ptr = S.Stk.pop<Pointer>();
644-
648+
if (Ptr.isDummy())
649+
return false;
645650
if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
646651
return false;
647652

@@ -650,7 +655,8 @@ inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
650655

651656
inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
652657
const Pointer &Ptr = S.Stk.pop<Pointer>();
653-
658+
if (Ptr.isDummy())
659+
return false;
654660
if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
655661
return false;
656662

@@ -660,6 +666,9 @@ inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
660666
inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
661667
const Pointer &Ptr = S.Stk.pop<Pointer>();
662668

669+
if (Ptr.isDummy())
670+
return false;
671+
663672
if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
664673
return false;
665674

@@ -669,6 +678,8 @@ inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
669678
inline bool DecfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
670679
const Pointer &Ptr = S.Stk.pop<Pointer>();
671680

681+
if (Ptr.isDummy())
682+
return false;
672683
if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
673684
return false;
674685

@@ -774,9 +785,9 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
774785
// element in the same array are NOT equal. They have the same Base value,
775786
// but a different Offset. This is a pretty rare case, so we fix this here
776787
// by comparing pointers to the first elements.
777-
if (LHS.isArrayRoot())
788+
if (!LHS.isDummy() && LHS.isArrayRoot())
778789
VL = LHS.atIndex(0).getByteOffset();
779-
if (RHS.isArrayRoot())
790+
if (!RHS.isDummy() && RHS.isArrayRoot())
780791
VR = RHS.atIndex(0).getByteOffset();
781792

782793
S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
@@ -1895,7 +1906,7 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
18951906
const T &Offset = S.Stk.pop<T>();
18961907
const Pointer &Ptr = S.Stk.peek<Pointer>();
18971908

1898-
if (!CheckDummy(S, OpPC, Ptr))
1909+
if (Ptr.isDummy())
18991910
return true;
19001911

19011912
if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
@@ -1909,7 +1920,7 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
19091920
const T &Offset = S.Stk.pop<T>();
19101921
const Pointer &Ptr = S.Stk.pop<Pointer>();
19111922

1912-
if (!CheckDummy(S, OpPC, Ptr)) {
1923+
if (Ptr.isDummy()) {
19131924
S.Stk.push<Pointer>(Ptr);
19141925
return true;
19151926
}

clang/test/AST/Interp/arrays.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,3 +564,8 @@ namespace LocalVLA {
564564
#endif
565565
}
566566
}
567+
568+
char melchizedek[2200000000];
569+
typedef decltype(melchizedek[1] - melchizedek[0]) ptrdiff_t;
570+
constexpr ptrdiff_t d1 = &melchizedek[0x7fffffff] - &melchizedek[0]; // ok
571+
constexpr ptrdiff_t d3 = &melchizedek[0] - &melchizedek[0x80000000u]; // ok

clang/test/AST/Interp/c.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ const int b = 3;
3333
_Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \
3434
// pedantic-expected-warning {{not an integer constant expression}}
3535

36-
/// FIXME: The new interpreter is missing the "initializer of 'c' unknown" diagnostics.
37-
const int c; // ref-note {{declared here}} \
38-
// pedantic-ref-note {{declared here}}
36+
const int c; // all-note {{declared here}}
3937
_Static_assert(c == 0, ""); // ref-error {{not an integral constant expression}} \
4038
// ref-note {{initializer of 'c' is unknown}} \
4139
// pedantic-ref-error {{not an integral constant expression}} \
4240
// pedantic-ref-note {{initializer of 'c' is unknown}} \
4341
// expected-error {{not an integral constant expression}} \
44-
// pedantic-expected-error {{not an integral constant expression}}
42+
// expected-note {{initializer of 'c' is unknown}} \
43+
// pedantic-expected-error {{not an integral constant expression}} \
44+
// pedantic-expected-note {{initializer of 'c' is unknown}}
4545

4646
_Static_assert(&c != 0, ""); // ref-warning {{always true}} \
4747
// pedantic-ref-warning {{always true}} \

clang/test/AST/Interp/cxx98.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@ template struct C<cval>;
1818

1919
/// FIXME: This example does not get properly diagnosed in the new interpreter.
2020
extern const int recurse1;
21-
const int recurse2 = recurse1; // ref-note {{here}}
21+
const int recurse2 = recurse1; // both-note {{declared here}}
2222
const int recurse1 = 1;
2323
int array1[recurse1];
2424
int array2[recurse2]; // ref-warning 2{{variable length array}} \
2525
// ref-note {{initializer of 'recurse2' is not a constant expression}} \
2626
// expected-warning {{variable length array}} \
27+
// expected-note {{read of non-const variable 'recurse2'}} \
2728
// expected-error {{variable length array}}
2829

2930
int NCI; // both-note {{declared here}}

0 commit comments

Comments
 (0)