[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang / lib / AST / Interp / Context.cpp
blobcb96e56fb5e1ad87f521f853e805b4cef877b6c4
1 //===--- Context.cpp - Context for the constexpr VM -------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "Context.h"
10 #include "ByteCodeEmitter.h"
11 #include "ByteCodeExprGen.h"
12 #include "ByteCodeGenError.h"
13 #include "ByteCodeStmtGen.h"
14 #include "EvalEmitter.h"
15 #include "Interp.h"
16 #include "InterpFrame.h"
17 #include "InterpStack.h"
18 #include "PrimType.h"
19 #include "Program.h"
20 #include "clang/AST/Expr.h"
21 #include "clang/Basic/TargetInfo.h"
23 using namespace clang;
24 using namespace clang::interp;
26 Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {}
28 Context::~Context() {}
30 bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
31 assert(Stk.empty());
32 Function *Func = P->getFunction(FD);
33 if (!Func || !Func->hasBody()) {
34 if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD)) {
35 Func = *R;
36 } else {
37 handleAllErrors(R.takeError(), [&Parent](ByteCodeGenError &Err) {
38 Parent.FFDiag(Err.getRange().getBegin(),
39 diag::err_experimental_clang_interp_failed)
40 << Err.getRange();
41 });
42 return false;
46 APValue DummyResult;
47 if (!Run(Parent, Func, DummyResult)) {
48 return false;
51 return Func->isConstexpr();
54 bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
55 assert(Stk.empty());
56 ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
57 if (Check(Parent, C.interpretExpr(E))) {
58 assert(Stk.empty());
59 #ifndef NDEBUG
60 // Make sure we don't rely on some value being still alive in
61 // InterpStack memory.
62 Stk.clear();
63 #endif
64 return true;
67 Stk.clear();
68 return false;
71 bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
72 APValue &Result) {
73 assert(Stk.empty());
74 ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
75 if (Check(Parent, C.interpretDecl(VD))) {
76 assert(Stk.empty());
77 #ifndef NDEBUG
78 // Make sure we don't rely on some value being still alive in
79 // InterpStack memory.
80 Stk.clear();
81 #endif
82 return true;
85 Stk.clear();
86 return false;
89 const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
91 std::optional<PrimType> Context::classify(QualType T) const {
92 if (T->isBooleanType())
93 return PT_Bool;
95 if (T->isSignedIntegerOrEnumerationType()) {
96 switch (Ctx.getIntWidth(T)) {
97 case 64:
98 return PT_Sint64;
99 case 32:
100 return PT_Sint32;
101 case 16:
102 return PT_Sint16;
103 case 8:
104 return PT_Sint8;
105 default:
106 return PT_IntAPS;
110 if (T->isUnsignedIntegerOrEnumerationType()) {
111 switch (Ctx.getIntWidth(T)) {
112 case 64:
113 return PT_Uint64;
114 case 32:
115 return PT_Uint32;
116 case 16:
117 return PT_Uint16;
118 case 8:
119 return PT_Uint8;
120 default:
121 return PT_IntAP;
125 if (T->isNullPtrType())
126 return PT_Ptr;
128 if (T->isFloatingType())
129 return PT_Float;
131 if (T->isFunctionPointerType() || T->isFunctionReferenceType() ||
132 T->isFunctionType() || T->isSpecificBuiltinType(BuiltinType::BoundMember))
133 return PT_FnPtr;
135 if (T->isReferenceType() || T->isPointerType())
136 return PT_Ptr;
138 if (const auto *AT = dyn_cast<AtomicType>(T))
139 return classify(AT->getValueType());
141 if (const auto *DT = dyn_cast<DecltypeType>(T))
142 return classify(DT->getUnderlyingType());
144 if (const auto *DT = dyn_cast<MemberPointerType>(T))
145 return classify(DT->getPointeeType());
147 return std::nullopt;
150 unsigned Context::getCharBit() const {
151 return Ctx.getTargetInfo().getCharWidth();
154 /// Simple wrapper around getFloatTypeSemantics() to make code a
155 /// little shorter.
156 const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const {
157 return Ctx.getFloatTypeSemantics(T);
160 bool Context::Run(State &Parent, const Function *Func, APValue &Result) {
163 InterpState State(Parent, *P, Stk, *this);
164 State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, {});
165 if (Interpret(State, Result)) {
166 assert(Stk.empty());
167 return true;
170 // State gets destroyed here, so the Stk.clear() below doesn't accidentally
171 // remove values the State's destructor might accedd.
174 Stk.clear();
175 return false;
178 bool Context::Check(State &Parent, llvm::Expected<bool> &&Flag) {
179 if (Flag)
180 return *Flag;
181 handleAllErrors(Flag.takeError(), [&Parent](ByteCodeGenError &Err) {
182 Parent.FFDiag(Err.getRange().getBegin(),
183 diag::err_experimental_clang_interp_failed)
184 << Err.getRange();
186 return false;
189 // TODO: Virtual bases?
190 const CXXMethodDecl *
191 Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl,
192 const CXXRecordDecl *StaticDecl,
193 const CXXMethodDecl *InitialFunction) const {
195 const CXXRecordDecl *CurRecord = DynamicDecl;
196 const CXXMethodDecl *FoundFunction = InitialFunction;
197 for (;;) {
198 const CXXMethodDecl *Overrider =
199 FoundFunction->getCorrespondingMethodDeclaredInClass(CurRecord, false);
200 if (Overrider)
201 return Overrider;
203 // Common case of only one base class.
204 if (CurRecord->getNumBases() == 1) {
205 CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl();
206 continue;
209 // Otherwise, go to the base class that will lead to the StaticDecl.
210 for (const CXXBaseSpecifier &Spec : CurRecord->bases()) {
211 const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl();
212 if (Base == StaticDecl || Base->isDerivedFrom(StaticDecl)) {
213 CurRecord = Base;
214 break;
219 llvm_unreachable(
220 "Couldn't find an overriding function in the class hierarchy?");
221 return nullptr;
224 const Function *Context::getOrCreateFunction(const FunctionDecl *FD) {
225 assert(FD);
226 const Function *Func = P->getFunction(FD);
227 bool IsBeingCompiled = Func && Func->isDefined() && !Func->isFullyCompiled();
228 bool WasNotDefined = Func && !Func->isConstexpr() && !Func->isDefined();
230 if (IsBeingCompiled)
231 return Func;
233 if (!Func || WasNotDefined) {
234 if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD))
235 Func = *R;
236 else {
237 llvm::consumeError(R.takeError());
238 return nullptr;
242 return Func;