diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Interp/ByteCodeExprGen.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/Interp/Interp.cpp | 48 | ||||
-rw-r--r-- | clang/lib/AST/Interp/Interp.h | 14 | ||||
-rw-r--r-- | clang/lib/AST/Interp/Opcodes.td | 1 |
4 files changed, 54 insertions, 11 deletions
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 7f8bbe7..d6be9a3 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2337,7 +2337,7 @@ bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) { auto GlobalIndex = P.getGlobal(VD); assert(GlobalIndex); // visitVarDecl() didn't return false. if (VarT) { - if (!this->emitGetGlobal(*VarT, *GlobalIndex, VD)) + if (!this->emitGetGlobalUnchecked(*VarT, *GlobalIndex, VD)) return false; } else { if (!this->emitGetPtrGlobal(*GlobalIndex, VD)) diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 9de0926..b95a521 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -53,6 +53,21 @@ static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) { return true; } +static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC, + const ValueDecl *VD) { + if (!S.getLangOpts().CPlusPlus) + return; + + const SourceInfo &Loc = S.Current->getSource(OpPC); + S.FFDiag(Loc, + VD->getType()->isIntegralOrEnumerationType() + ? diag::note_constexpr_ltor_non_const_int + : diag::note_constexpr_ltor_non_constexpr, + 1) + << VD; + S.Note(VD->getLocation(), diag::note_declared_at); +} + static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK) { if (Ptr.isActive()) @@ -171,9 +186,7 @@ bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) { const auto *VD = Ptr.getDeclDesc()->asValueDecl(); - const SourceInfo &Loc = S.Current->getSource(OpPC); - S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD; - S.Note(VD->getLocation(), diag::note_declared_at); + diagnoseNonConstVariable(S, OpPC, VD); } return false; } @@ -216,6 +229,24 @@ bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, return true; } +bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { + assert(Desc); + if (const auto *D = Desc->asValueDecl()) { + if (const auto *VD = dyn_cast<VarDecl>(D); + VD && VD->hasGlobalStorage() && + !(VD->isConstexpr() || VD->getType().isConstQualified())) { + diagnoseNonConstVariable(S, OpPC, VD); + return false; + } + } + + return true; +} + +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.isZero() && !Ptr.isDummy(); } @@ -304,6 +335,9 @@ bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { if (!CheckLive(S, OpPC, Ptr, AK_Read)) return false; + if (!CheckConstant(S, OpPC, Ptr)) + return false; + if (!CheckDummy(S, OpPC, Ptr)) return false; if (!CheckExtern(S, OpPC, Ptr)) @@ -605,13 +639,7 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) { } } else if (const auto *VD = dyn_cast<VarDecl>(D)) { if (!VD->getType().isConstQualified()) { - S.FFDiag(E, - VD->getType()->isIntegralOrEnumerationType() - ? diag::note_constexpr_ltor_non_const_int - : diag::note_constexpr_ltor_non_constexpr, - 1) - << VD; - S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange(); + diagnoseNonConstVariable(S, OpPC, VD); return false; } diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index c05dea0..dbbc4c0 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -77,6 +77,9 @@ bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, /// Checks if a pointer points to const storage. bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr); +/// Checks if the Descriptor is of a constexpr or const global variable. +bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc); + /// Checks if a pointer points to a mutable field. bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr); @@ -1004,12 +1007,23 @@ bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I) { template <PrimType Name, class T = typename PrimConv<Name>::T> bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) { const Block *B = S.P.getGlobal(I); + + if (!CheckConstant(S, OpPC, B->getDescriptor())) + return false; if (B->isExtern()) return false; S.Stk.push<T>(B->deref<T>()); return true; } +/// Same as GetGlobal, but without the checks. +template <PrimType Name, class T = typename PrimConv<Name>::T> +bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I) { + auto *B = S.P.getGlobal(I); + S.Stk.push<T>(B->deref<T>()); + return true; +} + template <PrimType Name, class T = typename PrimConv<Name>::T> bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) { // TODO: emit warning. diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td index 69068e8..e01b6b9 100644 --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/Interp/Opcodes.td @@ -379,6 +379,7 @@ def CheckGlobalCtor : Opcode {} // [] -> [Value] def GetGlobal : AccessOpcode; +def GetGlobalUnchecked : AccessOpcode; // [Value] -> [] def InitGlobal : AccessOpcode; // [Value] -> [] |