aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Interp/ByteCodeExprGen.cpp2
-rw-r--r--clang/lib/AST/Interp/Interp.cpp48
-rw-r--r--clang/lib/AST/Interp/Interp.h14
-rw-r--r--clang/lib/AST/Interp/Opcodes.td1
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] -> []