aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/AST/Interp/Context.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/Interp/Context.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/AST/Interp/Context.cpp169
1 files changed, 96 insertions, 73 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Context.cpp b/contrib/llvm-project/clang/lib/AST/Interp/Context.cpp
index 75a300bcbace..b5e992c5a9ac 100644
--- a/contrib/llvm-project/clang/lib/AST/Interp/Context.cpp
+++ b/contrib/llvm-project/clang/lib/AST/Interp/Context.cpp
@@ -8,9 +8,7 @@
#include "Context.h"
#include "ByteCodeEmitter.h"
-#include "ByteCodeExprGen.h"
-#include "ByteCodeGenError.h"
-#include "ByteCodeStmtGen.h"
+#include "Compiler.h"
#include "EvalEmitter.h"
#include "Interp.h"
#include "InterpFrame.h"
@@ -31,102 +29,96 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
assert(Stk.empty());
Function *Func = P->getFunction(FD);
if (!Func || !Func->hasBody())
- Func = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD);
+ Func = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD);
+
+ if (!Func)
+ return false;
APValue DummyResult;
- if (!Run(Parent, Func, DummyResult)) {
+ if (!Run(Parent, Func, DummyResult))
return false;
- }
return Func->isConstexpr();
}
bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
- assert(Stk.empty());
- ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
+ ++EvalID;
+ bool Recursing = !Stk.empty();
+ Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
- auto Res = C.interpretExpr(E);
+ auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue());
if (Res.isInvalid()) {
+ C.cleanup();
Stk.clear();
return false;
}
- assert(Stk.empty());
+ if (!Recursing) {
+ assert(Stk.empty());
#ifndef NDEBUG
- // Make sure we don't rely on some value being still alive in
- // InterpStack memory.
- Stk.clear();
+ // Make sure we don't rely on some value being still alive in
+ // InterpStack memory.
+ Stk.clear();
#endif
-
- // Implicit lvalue-to-rvalue conversion.
- if (E->isGLValue()) {
- std::optional<APValue> RValueResult = Res.toRValue();
- if (!RValueResult) {
- return false;
- }
- Result = *RValueResult;
- } else {
- Result = Res.toAPValue();
}
+ Result = Res.toAPValue();
+
return true;
}
bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {
- assert(Stk.empty());
- ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
+ ++EvalID;
+ bool Recursing = !Stk.empty();
+ Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
auto Res = C.interpretExpr(E);
if (Res.isInvalid()) {
+ C.cleanup();
Stk.clear();
return false;
}
- assert(Stk.empty());
+ if (!Recursing) {
+ assert(Stk.empty());
#ifndef NDEBUG
- // Make sure we don't rely on some value being still alive in
- // InterpStack memory.
- Stk.clear();
+ // Make sure we don't rely on some value being still alive in
+ // InterpStack memory.
+ Stk.clear();
#endif
+ }
+
Result = Res.toAPValue();
return true;
}
bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
APValue &Result) {
- assert(Stk.empty());
- ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
-
- auto Res = C.interpretDecl(VD);
+ ++EvalID;
+ bool Recursing = !Stk.empty();
+ Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
+
+ bool CheckGlobalInitialized =
+ shouldBeGloballyIndexed(VD) &&
+ (VD->getType()->isRecordType() || VD->getType()->isArrayType());
+ auto Res = C.interpretDecl(VD, CheckGlobalInitialized);
if (Res.isInvalid()) {
+ C.cleanup();
Stk.clear();
return false;
}
- assert(Stk.empty());
+ if (!Recursing) {
+ assert(Stk.empty());
#ifndef NDEBUG
- // Make sure we don't rely on some value being still alive in
- // InterpStack memory.
- Stk.clear();
+ // Make sure we don't rely on some value being still alive in
+ // InterpStack memory.
+ Stk.clear();
#endif
+ }
- // Ensure global variables are fully initialized.
- if (shouldBeGloballyIndexed(VD) && !Res.isInvalid() &&
- (VD->getType()->isRecordType() || VD->getType()->isArrayType())) {
- assert(Res.isLValue());
-
- if (!Res.checkFullyInitialized(C.getState()))
- return false;
-
- // lvalue-to-rvalue conversion.
- std::optional<APValue> RValueResult = Res.toRValue();
- if (!RValueResult)
- return false;
- Result = *RValueResult;
-
- } else
- Result = Res.toAPValue();
+ Result = Res.toAPValue();
return true;
}
@@ -136,7 +128,8 @@ std::optional<PrimType> Context::classify(QualType T) const {
if (T->isBooleanType())
return PT_Bool;
- if (T->isAnyComplexType())
+ // We map these to primitive arrays.
+ if (T->isAnyComplexType() || T->isVectorType())
return std::nullopt;
if (T->isSignedIntegerOrEnumerationType()) {
@@ -175,22 +168,24 @@ std::optional<PrimType> Context::classify(QualType T) const {
if (T->isFloatingType())
return PT_Float;
+ if (T->isSpecificBuiltinType(BuiltinType::BoundMember) ||
+ T->isMemberPointerType())
+ return PT_MemberPtr;
+
if (T->isFunctionPointerType() || T->isFunctionReferenceType() ||
- T->isFunctionType() || T->isSpecificBuiltinType(BuiltinType::BoundMember))
+ T->isFunctionType())
return PT_FnPtr;
- if (T->isReferenceType() || T->isPointerType())
+ if (T->isReferenceType() || T->isPointerType() ||
+ T->isObjCObjectPointerType())
return PT_Ptr;
- if (const auto *AT = dyn_cast<AtomicType>(T))
+ if (const auto *AT = T->getAs<AtomicType>())
return classify(AT->getValueType());
if (const auto *DT = dyn_cast<DecltypeType>(T))
return classify(DT->getUnderlyingType());
- if (const auto *DT = dyn_cast<MemberPointerType>(T))
- return classify(DT->getPointeeType());
-
return std::nullopt;
}
@@ -208,7 +203,8 @@ bool Context::Run(State &Parent, const Function *Func, APValue &Result) {
{
InterpState State(Parent, *P, Stk, *this);
- State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, {});
+ State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, CodePtr(),
+ Func->getArgSize());
if (Interpret(State, Result)) {
assert(Stk.empty());
return true;
@@ -222,22 +218,14 @@ bool Context::Run(State &Parent, const Function *Func, APValue &Result) {
return false;
}
-bool Context::Check(State &Parent, llvm::Expected<bool> &&Flag) {
- if (Flag)
- return *Flag;
- handleAllErrors(Flag.takeError(), [&Parent](ByteCodeGenError &Err) {
- Parent.FFDiag(Err.getRange().getBegin(),
- diag::err_experimental_clang_interp_failed)
- << Err.getRange();
- });
- return false;
-}
-
// TODO: Virtual bases?
const CXXMethodDecl *
Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl,
const CXXRecordDecl *StaticDecl,
const CXXMethodDecl *InitialFunction) const {
+ assert(DynamicDecl);
+ assert(StaticDecl);
+ assert(InitialFunction);
const CXXRecordDecl *CurRecord = DynamicDecl;
const CXXMethodDecl *FoundFunction = InitialFunction;
@@ -278,9 +266,44 @@ const Function *Context::getOrCreateFunction(const FunctionDecl *FD) {
return Func;
if (!Func || WasNotDefined) {
- if (auto F = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD))
+ if (auto F = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD))
Func = F;
}
return Func;
}
+
+unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl,
+ const RecordDecl *DerivedDecl) const {
+ assert(BaseDecl);
+ assert(DerivedDecl);
+ const auto *FinalDecl = cast<CXXRecordDecl>(BaseDecl);
+ const RecordDecl *CurDecl = DerivedDecl;
+ const Record *CurRecord = P->getOrCreateRecord(CurDecl);
+ assert(CurDecl && FinalDecl);
+
+ unsigned OffsetSum = 0;
+ for (;;) {
+ assert(CurRecord->getNumBases() > 0);
+ // One level up
+ for (const Record::Base &B : CurRecord->bases()) {
+ const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl);
+
+ if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
+ OffsetSum += B.Offset;
+ CurRecord = B.R;
+ CurDecl = BaseDecl;
+ break;
+ }
+ }
+ if (CurDecl == FinalDecl)
+ break;
+ }
+
+ assert(OffsetSum > 0);
+ return OffsetSum;
+}
+
+const Record *Context::getRecord(const RecordDecl *D) const {
+ return P->getOrCreateRecord(D);
+}