diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index b151f8d0d7a79..122b9045a75f6 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -3213,12 +3213,6 @@ bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) { // we haven't seen yet. if (Ctx.getLangOpts().CPlusPlus) { if (const auto *VD = dyn_cast(D)) { - // Dummy for static locals - if (VD->isStaticLocal()) { - if (std::optional I = P.getOrCreateDummy(D)) - return this->emitGetPtrGlobal(*I, E); - return false; - } // Visit local const variables like normal. if (VD->isLocalVarDecl() && VD->getType().isConstQualified()) { if (!this->visitVarDecl(VD)) @@ -3226,6 +3220,9 @@ bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) { // Retry. return this->VisitDeclRefExpr(E); } + + if (VD->hasExternalStorage()) + return this->emitInvalidDeclRef(E, E); } } else { if (const auto *VD = dyn_cast(D); @@ -3235,11 +3232,11 @@ bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) { // Retry. return this->VisitDeclRefExpr(E); } - - if (std::optional I = P.getOrCreateDummy(D)) - return this->emitGetPtrGlobal(*I, E); } + if (std::optional I = P.getOrCreateDummy(D)) + return this->emitGetPtrGlobal(*I, E); + return this->emitInvalidDeclRef(E, E); } diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 5670888c245eb..4f3cd6cd21a15 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -285,10 +285,6 @@ static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { return CheckConstant(S, OpPC, Ptr.getDeclDesc()); } -bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { - return !Ptr.isDummy(); -} - bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK) { if (!Ptr.isZero()) @@ -595,10 +591,8 @@ bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result, return true; } -/// We aleady know the given DeclRefExpr is invalid for some reason, -/// now figure out why and print appropriate diagnostics. -bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) { - const ValueDecl *D = DR->getDecl(); +static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, + const ValueDecl *D) { const SourceInfo &E = S.Current->getSource(OpPC); if (isa(D)) { @@ -621,10 +615,28 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) { return false; } } - return false; } +/// We aleady know the given DeclRefExpr is invalid for some reason, +/// now figure out why and print appropriate diagnostics. +bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) { + const ValueDecl *D = DR->getDecl(); + return diagnoseUnknownDecl(S, OpPC, D); +} + +bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { + if (!Ptr.isDummy()) + return true; + + const Descriptor *Desc = Ptr.getDeclDesc(); + const ValueDecl *D = Desc->asValueDecl(); + if (!D) + return false; + + return diagnoseUnknownDecl(S, OpPC, D); +} + bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *CE, unsigned ArgSize) { auto Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs()); diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 13e004371f912..f379c9869d8d8 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -572,7 +572,8 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { template ::T> bool Inc(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.pop(); - + if (Ptr.isDummy()) + return false; if (!CheckInitialized(S, OpPC, Ptr, AK_Increment)) return false; @@ -585,7 +586,8 @@ bool Inc(InterpState &S, CodePtr OpPC) { template ::T> bool IncPop(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.pop(); - + if (Ptr.isDummy()) + return false; if (!CheckInitialized(S, OpPC, Ptr, AK_Increment)) return false; @@ -599,7 +601,8 @@ bool IncPop(InterpState &S, CodePtr OpPC) { template ::T> bool Dec(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.pop(); - + if (Ptr.isDummy()) + return false; if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement)) return false; @@ -612,7 +615,8 @@ bool Dec(InterpState &S, CodePtr OpPC) { template ::T> bool DecPop(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.pop(); - + if (Ptr.isDummy()) + return false; if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement)) return false; @@ -641,7 +645,8 @@ bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr, inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { const Pointer &Ptr = S.Stk.pop(); - + if (Ptr.isDummy()) + return false; if (!CheckInitialized(S, OpPC, Ptr, AK_Increment)) return false; @@ -650,7 +655,8 @@ inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { const Pointer &Ptr = S.Stk.pop(); - + if (Ptr.isDummy()) + return false; if (!CheckInitialized(S, OpPC, Ptr, AK_Increment)) return false; @@ -660,6 +666,9 @@ inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { const Pointer &Ptr = S.Stk.pop(); + if (Ptr.isDummy()) + return false; + if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement)) return false; @@ -669,6 +678,8 @@ inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { inline bool DecfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { const Pointer &Ptr = S.Stk.pop(); + if (Ptr.isDummy()) + return false; if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement)) return false; @@ -774,9 +785,9 @@ inline bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn) { // element in the same array are NOT equal. They have the same Base value, // but a different Offset. This is a pretty rare case, so we fix this here // by comparing pointers to the first elements. - if (LHS.isArrayRoot()) + if (!LHS.isDummy() && LHS.isArrayRoot()) VL = LHS.atIndex(0).getByteOffset(); - if (RHS.isArrayRoot()) + if (!RHS.isDummy() && RHS.isArrayRoot()) VR = RHS.atIndex(0).getByteOffset(); S.Stk.push(BoolT::from(Fn(Compare(VL, VR)))); @@ -1895,7 +1906,7 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) { const T &Offset = S.Stk.pop(); const Pointer &Ptr = S.Stk.peek(); - if (!CheckDummy(S, OpPC, Ptr)) + if (Ptr.isDummy()) return true; if (!OffsetHelper(S, OpPC, Offset, Ptr)) @@ -1909,7 +1920,7 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) { const T &Offset = S.Stk.pop(); const Pointer &Ptr = S.Stk.pop(); - if (!CheckDummy(S, OpPC, Ptr)) { + if (Ptr.isDummy()) { S.Stk.push(Ptr); return true; } diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp index e1af2e80e3ad7..2bf6e9ef35119 100644 --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -564,3 +564,8 @@ namespace LocalVLA { #endif } } + +char melchizedek[2200000000]; +typedef decltype(melchizedek[1] - melchizedek[0]) ptrdiff_t; +constexpr ptrdiff_t d1 = &melchizedek[0x7fffffff] - &melchizedek[0]; // ok +constexpr ptrdiff_t d3 = &melchizedek[0] - &melchizedek[0x80000000u]; // ok diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index 2a72c24b43d1c..260e5bdfeefb2 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -33,15 +33,15 @@ const int b = 3; _Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \ // pedantic-expected-warning {{not an integer constant expression}} -/// FIXME: The new interpreter is missing the "initializer of 'c' unknown" diagnostics. -const int c; // ref-note {{declared here}} \ - // pedantic-ref-note {{declared here}} +const int c; // all-note {{declared here}} _Static_assert(c == 0, ""); // ref-error {{not an integral constant expression}} \ // ref-note {{initializer of 'c' is unknown}} \ // pedantic-ref-error {{not an integral constant expression}} \ // pedantic-ref-note {{initializer of 'c' is unknown}} \ // expected-error {{not an integral constant expression}} \ - // pedantic-expected-error {{not an integral constant expression}} + // expected-note {{initializer of 'c' is unknown}} \ + // pedantic-expected-error {{not an integral constant expression}} \ + // pedantic-expected-note {{initializer of 'c' is unknown}} _Static_assert(&c != 0, ""); // ref-warning {{always true}} \ // pedantic-ref-warning {{always true}} \ diff --git a/clang/test/AST/Interp/cxx98.cpp b/clang/test/AST/Interp/cxx98.cpp index 1acc74a8290a0..73e4537206633 100644 --- a/clang/test/AST/Interp/cxx98.cpp +++ b/clang/test/AST/Interp/cxx98.cpp @@ -18,12 +18,13 @@ template struct C; /// FIXME: This example does not get properly diagnosed in the new interpreter. extern const int recurse1; -const int recurse2 = recurse1; // ref-note {{here}} +const int recurse2 = recurse1; // both-note {{declared here}} const int recurse1 = 1; int array1[recurse1]; int array2[recurse2]; // ref-warning 2{{variable length array}} \ // ref-note {{initializer of 'recurse2' is not a constant expression}} \ // expected-warning {{variable length array}} \ + // expected-note {{read of non-const variable 'recurse2'}} \ // expected-error {{variable length array}} int NCI; // both-note {{declared here}}