aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode')
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp5
-rw-r--r--clang/lib/AST/ByteCode/Context.cpp13
-rw-r--r--clang/lib/AST/ByteCode/Context.h4
-rw-r--r--clang/lib/AST/ByteCode/EvalEmitter.cpp13
-rw-r--r--clang/lib/AST/ByteCode/EvalEmitter.h3
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp9
-rw-r--r--clang/lib/AST/ByteCode/Interp.h2
7 files changed, 46 insertions, 3 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index ea473730..65ad7ca 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -6670,6 +6670,11 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
}
// Function parameters.
if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
+ if (Ctx.getLangOpts().CPlusPlus && !Ctx.getLangOpts().CPlusPlus11 &&
+ !D->getType()->isIntegralOrEnumerationType()) {
+ return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),
+ /*InitializerFailed=*/false, E);
+ }
if (auto It = this->Params.find(PVD); It != this->Params.end()) {
if (IsReference || !It->second.IsPtr)
return this->emitGetParam(classifyPrim(E), It->second.Offset, E);
diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp
index a629ff9..ead6e4a 100644
--- a/clang/lib/AST/ByteCode/Context.cpp
+++ b/clang/lib/AST/ByteCode/Context.cpp
@@ -52,6 +52,19 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
return Func->isValid();
}
+void Context::isPotentialConstantExprUnevaluated(State &Parent, const Expr *E,
+ const FunctionDecl *FD) {
+ assert(Stk.empty());
+ ++EvalID;
+ size_t StackSizeBefore = Stk.size();
+ Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
+
+ if (!C.interpretCall(FD, E)) {
+ C.cleanup();
+ Stk.clearTo(StackSizeBefore);
+ }
+}
+
bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
++EvalID;
bool Recursing = !Stk.empty();
diff --git a/clang/lib/AST/ByteCode/Context.h b/clang/lib/AST/ByteCode/Context.h
index 5898ab5..acf7504 100644
--- a/clang/lib/AST/ByteCode/Context.h
+++ b/clang/lib/AST/ByteCode/Context.h
@@ -47,7 +47,9 @@ public:
~Context();
/// Checks if a function is a potential constant expression.
- bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FnDecl);
+ bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FD);
+ void isPotentialConstantExprUnevaluated(State &Parent, const Expr *E,
+ const FunctionDecl *FD);
/// Evaluates a toplevel expression as an rvalue.
bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index 5498065..6e511bc 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -90,6 +90,19 @@ EvaluationResult EvalEmitter::interpretAsPointer(const Expr *E,
return std::move(this->EvalResult);
}
+bool EvalEmitter::interpretCall(const FunctionDecl *FD, const Expr *E) {
+ // Add parameters to the parameter map. The values in the ParamOffset don't
+ // matter in this case as reading from them can't ever work.
+ for (const ParmVarDecl *PD : FD->parameters()) {
+ this->Params.insert({PD, {0, false}});
+ }
+
+ if (!this->visit(E))
+ return false;
+ PrimType T = Ctx.classify(E).value_or(PT_Ptr);
+ return this->emitPop(T, E);
+}
+
void EvalEmitter::emitLabel(LabelTy Label) { CurrentLabel = Label; }
EvalEmitter::LabelTy EvalEmitter::getLabel() { return NextLabel++; }
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.h b/clang/lib/AST/ByteCode/EvalEmitter.h
index 7303adb..2fe7da6 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.h
+++ b/clang/lib/AST/ByteCode/EvalEmitter.h
@@ -40,6 +40,9 @@ public:
EvaluationResult interpretDecl(const VarDecl *VD, bool CheckFullyInitialized);
/// Interpret the given Expr to a Pointer.
EvaluationResult interpretAsPointer(const Expr *E, PtrCallback PtrCB);
+ /// Interpret the given expression as if it was in the body of the given
+ /// function, i.e. the parameters of the function are available for use.
+ bool interpretCall(const FunctionDecl *FD, const Expr *E);
/// Clean up all resources.
void cleanup();
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index df5e3be..5463aec 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -142,8 +142,12 @@ static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC,
return false;
if (isa<ParmVarDecl>(D)) {
- if (D->getType()->isReferenceType())
+ if (D->getType()->isReferenceType()) {
+ if (S.inConstantContext() && S.getLangOpts().CPlusPlus &&
+ !S.getLangOpts().CPlusPlus11)
+ diagnoseNonConstVariable(S, OpPC, D);
return false;
+ }
const SourceInfo &Loc = S.Current->getSource(OpPC);
if (S.getLangOpts().CPlusPlus11) {
@@ -661,6 +665,9 @@ bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
if (Ptr.isInitialized())
return true;
+ if (Ptr.isExtern() && S.checkingPotentialConstantExpression())
+ return false;
+
if (const auto *VD = Ptr.getDeclDesc()->asVarDecl();
VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index ce0ebdd..aac519d 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -1308,7 +1308,7 @@ bool Dup(InterpState &S, CodePtr OpPC) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Pop(InterpState &S, CodePtr OpPC) {
- S.Stk.pop<T>();
+ S.Stk.discard<T>();
return true;
}