/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/Interp/ByteCodeExprGen.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- ByteCodeExprGen.h - Code generator for expressions -----*- 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 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // Defines the constexpr bytecode compiler. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #ifndef LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H |
14 | | #define LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H |
15 | | |
16 | | #include "ByteCodeEmitter.h" |
17 | | #include "EvalEmitter.h" |
18 | | #include "Pointer.h" |
19 | | #include "PrimType.h" |
20 | | #include "Record.h" |
21 | | #include "clang/AST/Decl.h" |
22 | | #include "clang/AST/Expr.h" |
23 | | #include "clang/AST/StmtVisitor.h" |
24 | | #include "clang/Basic/TargetInfo.h" |
25 | | #include "llvm/ADT/Optional.h" |
26 | | |
27 | | namespace clang { |
28 | | class QualType; |
29 | | |
30 | | namespace interp { |
31 | | class Function; |
32 | | class State; |
33 | | |
34 | | template <class Emitter> class LocalScope; |
35 | | template <class Emitter> class RecordScope; |
36 | | template <class Emitter> class VariableScope; |
37 | | template <class Emitter> class DeclScope; |
38 | | template <class Emitter> class OptionScope; |
39 | | |
40 | | /// Compilation context for expressions. |
41 | | template <class Emitter> |
42 | | class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, |
43 | | public Emitter { |
44 | | protected: |
45 | | // Emitters for opcodes of various arities. |
46 | | using NullaryFn = bool (ByteCodeExprGen::*)(const SourceInfo &); |
47 | | using UnaryFn = bool (ByteCodeExprGen::*)(PrimType, const SourceInfo &); |
48 | | using BinaryFn = bool (ByteCodeExprGen::*)(PrimType, PrimType, |
49 | | const SourceInfo &); |
50 | | |
51 | | // Aliases for types defined in the emitter. |
52 | | using LabelTy = typename Emitter::LabelTy; |
53 | | using AddrTy = typename Emitter::AddrTy; |
54 | | |
55 | | // Reference to a function generating the pointer of an initialized object.s |
56 | | using InitFnRef = std::function<bool()>; |
57 | | |
58 | | /// Current compilation context. |
59 | | Context &Ctx; |
60 | | /// Program to link to. |
61 | | Program &P; |
62 | | |
63 | | public: |
64 | | /// Initializes the compiler and the backend emitter. |
65 | | template <typename... Tys> |
66 | | ByteCodeExprGen(Context &Ctx, Program &P, Tys &&... Args) |
67 | 8 | : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {} clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::ByteCodeExprGen<>(clang::interp::Context&, clang::interp::Program&) Line | Count | Source | 67 | 1 | : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {} |
clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::ByteCodeExprGen<clang::interp::State&, clang::interp::InterpStack&, clang::APValue&>(clang::interp::Context&, clang::interp::Program&, clang::interp::State&, clang::interp::InterpStack&, clang::APValue&) Line | Count | Source | 67 | 7 | : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {} |
|
68 | | |
69 | | // Expression visitors - result returned on stack. |
70 | | bool VisitCastExpr(const CastExpr *E); |
71 | | bool VisitIntegerLiteral(const IntegerLiteral *E); |
72 | | bool VisitParenExpr(const ParenExpr *E); |
73 | | bool VisitBinaryOperator(const BinaryOperator *E); |
74 | | |
75 | | protected: |
76 | | bool visitExpr(const Expr *E) override; |
77 | | bool visitDecl(const VarDecl *VD) override; |
78 | | |
79 | | protected: |
80 | | /// Emits scope cleanup instructions. |
81 | | void emitCleanup(); |
82 | | |
83 | | /// Returns a record type from a record or pointer type. |
84 | | const RecordType *getRecordTy(QualType Ty); |
85 | | |
86 | | /// Returns a record from a record or pointer type. |
87 | | Record *getRecord(QualType Ty); |
88 | | Record *getRecord(const RecordDecl *RD); |
89 | | |
90 | | /// Returns the size int bits of an integer. |
91 | 0 | unsigned getIntWidth(QualType Ty) { |
92 | 0 | auto &ASTContext = Ctx.getASTContext(); |
93 | 0 | return ASTContext.getIntWidth(Ty); |
94 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::getIntWidth(clang::QualType) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::getIntWidth(clang::QualType) |
95 | | |
96 | | /// Returns the value of CHAR_BIT. |
97 | 0 | unsigned getCharBit() const { |
98 | 0 | auto &ASTContext = Ctx.getASTContext(); |
99 | 0 | return ASTContext.getTargetInfo().getCharWidth(); |
100 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::getCharBit() const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::getCharBit() const |
101 | | |
102 | | /// Classifies a type. |
103 | 0 | llvm::Optional<PrimType> classify(const Expr *E) const { |
104 | 0 | return E->isGLValue() ? PT_Ptr : classify(E->getType()); |
105 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::classify(clang::Expr const*) const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::classify(clang::Expr const*) const |
106 | 39 | llvm::Optional<PrimType> classify(QualType Ty) const { |
107 | 39 | return Ctx.classify(Ty); |
108 | 39 | } clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::classify(clang::QualType) const Line | Count | Source | 106 | 17 | llvm::Optional<PrimType> classify(QualType Ty) const { | 107 | 17 | return Ctx.classify(Ty); | 108 | 17 | } |
clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::classify(clang::QualType) const Line | Count | Source | 106 | 22 | llvm::Optional<PrimType> classify(QualType Ty) const { | 107 | 22 | return Ctx.classify(Ty); | 108 | 22 | } |
|
109 | | |
110 | | /// Checks if a pointer needs adjustment. |
111 | 0 | bool needsAdjust(QualType Ty) const { |
112 | 0 | return true; |
113 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::needsAdjust(clang::QualType) const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::needsAdjust(clang::QualType) const |
114 | | |
115 | | /// Classifies a known primitive type |
116 | 0 | PrimType classifyPrim(QualType Ty) const { |
117 | 0 | if (auto T = classify(Ty)) { |
118 | 0 | return *T; |
119 | 0 | } |
120 | 0 | llvm_unreachable("not a primitive type"); |
121 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::classifyPrim(clang::QualType) const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::classifyPrim(clang::QualType) const |
122 | | |
123 | | /// Evaluates an expression for side effects and discards the result. |
124 | | bool discard(const Expr *E); |
125 | | /// Evaluates an expression and places result on stack. |
126 | | bool visit(const Expr *E); |
127 | | /// Compiles an initializer for a local. |
128 | | bool visitInitializer(const Expr *E, InitFnRef GenPtr); |
129 | | |
130 | | /// Visits an expression and converts it to a boolean. |
131 | | bool visitBool(const Expr *E); |
132 | | |
133 | | /// Visits an initializer for a local. |
134 | 0 | bool visitLocalInitializer(const Expr *Init, unsigned I) { |
135 | 0 | return visitInitializer(Init, [this, I, Init] { |
136 | 0 | return this->emitGetPtrLocal(I, Init); |
137 | 0 | }); Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitLocalInitializer(clang::Expr const*, unsigned int)::'lambda'()::operator()() const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitLocalInitializer(clang::Expr const*, unsigned int)::'lambda'()::operator()() const |
138 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitLocalInitializer(clang::Expr const*, unsigned int) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitLocalInitializer(clang::Expr const*, unsigned int) |
139 | | |
140 | | /// Visits an initializer for a global. |
141 | 0 | bool visitGlobalInitializer(const Expr *Init, unsigned I) { |
142 | 0 | return visitInitializer(Init, [this, I, Init] { |
143 | 0 | return this->emitGetPtrGlobal(I, Init); |
144 | 0 | }); Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitGlobalInitializer(clang::Expr const*, unsigned int)::'lambda'()::operator()() const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitGlobalInitializer(clang::Expr const*, unsigned int)::'lambda'()::operator()() const |
145 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitGlobalInitializer(clang::Expr const*, unsigned int) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitGlobalInitializer(clang::Expr const*, unsigned int) |
146 | | |
147 | | /// Visits a delegated initializer. |
148 | 0 | bool visitThisInitializer(const Expr *I) { |
149 | 0 | return visitInitializer(I, [this, I] { return this->emitThis(I); }); Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitThisInitializer(clang::Expr const*)::'lambda'()::operator()() const Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitThisInitializer(clang::Expr const*)::'lambda'()::operator()() const |
150 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::visitThisInitializer(clang::Expr const*) Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitThisInitializer(clang::Expr const*) |
151 | | |
152 | | /// Creates a local primitive value. |
153 | | unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsMutable, |
154 | | bool IsExtended = false); |
155 | | |
156 | | /// Allocates a space storing a local given its type. |
157 | | llvm::Optional<unsigned> allocateLocal(DeclTy &&Decl, |
158 | | bool IsExtended = false); |
159 | | |
160 | | private: |
161 | | friend class VariableScope<Emitter>; |
162 | | friend class LocalScope<Emitter>; |
163 | | friend class RecordScope<Emitter>; |
164 | | friend class DeclScope<Emitter>; |
165 | | friend class OptionScope<Emitter>; |
166 | | |
167 | | /// Emits a zero initializer. |
168 | | bool visitZeroInitializer(PrimType T, const Expr *E); |
169 | | |
170 | | enum class DerefKind { |
171 | | /// Value is read and pushed to stack. |
172 | | Read, |
173 | | /// Direct method generates a value which is written. Returns pointer. |
174 | | Write, |
175 | | /// Direct method receives the value, pushes mutated value. Returns pointer. |
176 | | ReadWrite, |
177 | | }; |
178 | | |
179 | | /// Method to directly load a value. If the value can be fetched directly, |
180 | | /// the direct handler is called. Otherwise, a pointer is left on the stack |
181 | | /// and the indirect handler is expected to operate on that. |
182 | | bool dereference(const Expr *LV, DerefKind AK, |
183 | | llvm::function_ref<bool(PrimType)> Direct, |
184 | | llvm::function_ref<bool(PrimType)> Indirect); |
185 | | bool dereferenceParam(const Expr *LV, PrimType T, const ParmVarDecl *PD, |
186 | | DerefKind AK, |
187 | | llvm::function_ref<bool(PrimType)> Direct, |
188 | | llvm::function_ref<bool(PrimType)> Indirect); |
189 | | bool dereferenceVar(const Expr *LV, PrimType T, const VarDecl *PD, |
190 | | DerefKind AK, llvm::function_ref<bool(PrimType)> Direct, |
191 | | llvm::function_ref<bool(PrimType)> Indirect); |
192 | | |
193 | | /// Emits an APInt constant. |
194 | | bool emitConst(PrimType T, unsigned NumBits, const llvm::APInt &Value, |
195 | | const Expr *E); |
196 | | |
197 | | /// Emits an integer constant. |
198 | | template <typename T> bool emitConst(const Expr *E, T Value) { |
199 | | QualType Ty = E->getType(); |
200 | | unsigned NumBits = getIntWidth(Ty); |
201 | | APInt WrappedValue(NumBits, Value, std::is_signed<T>::value); |
202 | | return emitConst(*Ctx.classify(Ty), NumBits, WrappedValue, E); |
203 | | } |
204 | | |
205 | | /// Returns a pointer to a variable declaration. |
206 | | bool getPtrVarDecl(const VarDecl *VD, const Expr *E); |
207 | | |
208 | | /// Returns the index of a global. |
209 | | llvm::Optional<unsigned> getGlobalIdx(const VarDecl *VD); |
210 | | |
211 | | /// Emits the initialized pointer. |
212 | 0 | bool emitInitFn() { |
213 | 0 | assert(InitFn && "missing initializer"); |
214 | 0 | return (*InitFn)(); |
215 | 0 | } Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>::emitInitFn() Unexecuted instantiation: clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::emitInitFn() |
216 | | |
217 | | protected: |
218 | | /// Variable to storage mapping. |
219 | | llvm::DenseMap<const ValueDecl *, Scope::Local> Locals; |
220 | | |
221 | | /// OpaqueValueExpr to location mapping. |
222 | | llvm::DenseMap<const OpaqueValueExpr *, unsigned> OpaqueExprs; |
223 | | |
224 | | /// Current scope. |
225 | | VariableScope<Emitter> *VarScope = nullptr; |
226 | | |
227 | | /// Current argument index. |
228 | | llvm::Optional<uint64_t> ArrayIndex; |
229 | | |
230 | | /// Flag indicating if return value is to be discarded. |
231 | | bool DiscardResult = false; |
232 | | |
233 | | /// Expression being initialized. |
234 | | llvm::Optional<InitFnRef> InitFn = {}; |
235 | | }; |
236 | | |
237 | | extern template class ByteCodeExprGen<ByteCodeEmitter>; |
238 | | extern template class ByteCodeExprGen<EvalEmitter>; |
239 | | |
240 | | /// Scope chain managing the variable lifetimes. |
241 | | template <class Emitter> class VariableScope { |
242 | | public: |
243 | 13 | virtual ~VariableScope() { Ctx->VarScope = this->Parent; } clang::interp::VariableScope<clang::interp::ByteCodeEmitter>::~VariableScope() Line | Count | Source | 243 | 6 | virtual ~VariableScope() { Ctx->VarScope = this->Parent; } |
clang::interp::VariableScope<clang::interp::EvalEmitter>::~VariableScope() Line | Count | Source | 243 | 7 | virtual ~VariableScope() { Ctx->VarScope = this->Parent; } |
|
244 | | |
245 | 0 | void add(const Scope::Local &Local, bool IsExtended) { |
246 | 0 | if (IsExtended) |
247 | 0 | this->addExtended(Local); |
248 | 0 | else |
249 | 0 | this->addLocal(Local); |
250 | 0 | } Unexecuted instantiation: clang::interp::VariableScope<clang::interp::ByteCodeEmitter>::add(clang::interp::Scope::Local const&, bool) Unexecuted instantiation: clang::interp::VariableScope<clang::interp::EvalEmitter>::add(clang::interp::Scope::Local const&, bool) |
251 | | |
252 | 0 | virtual void addLocal(const Scope::Local &Local) { |
253 | 0 | if (this->Parent) |
254 | 0 | this->Parent->addLocal(Local); |
255 | 0 | } Unexecuted instantiation: clang::interp::VariableScope<clang::interp::ByteCodeEmitter>::addLocal(clang::interp::Scope::Local const&) Unexecuted instantiation: clang::interp::VariableScope<clang::interp::EvalEmitter>::addLocal(clang::interp::Scope::Local const&) |
256 | | |
257 | 0 | virtual void addExtended(const Scope::Local &Local) { |
258 | 0 | if (this->Parent) |
259 | 0 | this->Parent->addExtended(Local); |
260 | 0 | } Unexecuted instantiation: clang::interp::VariableScope<clang::interp::ByteCodeEmitter>::addExtended(clang::interp::Scope::Local const&) Unexecuted instantiation: clang::interp::VariableScope<clang::interp::EvalEmitter>::addExtended(clang::interp::Scope::Local const&) |
261 | | |
262 | 0 | virtual void emitDestruction() {} Unexecuted instantiation: clang::interp::VariableScope<clang::interp::ByteCodeEmitter>::emitDestruction() Unexecuted instantiation: clang::interp::VariableScope<clang::interp::EvalEmitter>::emitDestruction() |
263 | | |
264 | 8 | VariableScope *getParent() { return Parent; } clang::interp::VariableScope<clang::interp::ByteCodeEmitter>::getParent() Line | Count | Source | 264 | 8 | VariableScope *getParent() { return Parent; } |
Unexecuted instantiation: clang::interp::VariableScope<clang::interp::EvalEmitter>::getParent() |
265 | | |
266 | | protected: |
267 | | VariableScope(ByteCodeExprGen<Emitter> *Ctx) |
268 | 13 | : Ctx(Ctx), Parent(Ctx->VarScope) { |
269 | 13 | Ctx->VarScope = this; |
270 | 13 | } clang::interp::VariableScope<clang::interp::ByteCodeEmitter>::VariableScope(clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>*) Line | Count | Source | 268 | 6 | : Ctx(Ctx), Parent(Ctx->VarScope) { | 269 | 6 | Ctx->VarScope = this; | 270 | 6 | } |
clang::interp::VariableScope<clang::interp::EvalEmitter>::VariableScope(clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>*) Line | Count | Source | 268 | 7 | : Ctx(Ctx), Parent(Ctx->VarScope) { | 269 | 7 | Ctx->VarScope = this; | 270 | 7 | } |
|
271 | | |
272 | | /// ByteCodeExprGen instance. |
273 | | ByteCodeExprGen<Emitter> *Ctx; |
274 | | /// Link to the parent scope. |
275 | | VariableScope *Parent; |
276 | | }; |
277 | | |
278 | | /// Scope for local variables. |
279 | | /// |
280 | | /// When the scope is destroyed, instructions are emitted to tear down |
281 | | /// all variables declared in this scope. |
282 | | template <class Emitter> class LocalScope : public VariableScope<Emitter> { |
283 | | public: |
284 | 13 | LocalScope(ByteCodeExprGen<Emitter> *Ctx) : VariableScope<Emitter>(Ctx) {} clang::interp::LocalScope<clang::interp::ByteCodeEmitter>::LocalScope(clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>*) Line | Count | Source | 284 | 6 | LocalScope(ByteCodeExprGen<Emitter> *Ctx) : VariableScope<Emitter>(Ctx) {} |
clang::interp::LocalScope<clang::interp::EvalEmitter>::LocalScope(clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>*) Line | Count | Source | 284 | 7 | LocalScope(ByteCodeExprGen<Emitter> *Ctx) : VariableScope<Emitter>(Ctx) {} |
|
285 | | |
286 | 13 | ~LocalScope() override { this->emitDestruction(); } clang::interp::LocalScope<clang::interp::ByteCodeEmitter>::~LocalScope() Line | Count | Source | 286 | 6 | ~LocalScope() override { this->emitDestruction(); } |
clang::interp::LocalScope<clang::interp::EvalEmitter>::~LocalScope() Line | Count | Source | 286 | 7 | ~LocalScope() override { this->emitDestruction(); } |
|
287 | | |
288 | 0 | void addLocal(const Scope::Local &Local) override { |
289 | 0 | if (!Idx.hasValue()) { |
290 | 0 | Idx = this->Ctx->Descriptors.size(); |
291 | 0 | this->Ctx->Descriptors.emplace_back(); |
292 | 0 | } |
293 | |
|
294 | 0 | this->Ctx->Descriptors[*Idx].emplace_back(Local); |
295 | 0 | } Unexecuted instantiation: clang::interp::LocalScope<clang::interp::ByteCodeEmitter>::addLocal(clang::interp::Scope::Local const&) Unexecuted instantiation: clang::interp::LocalScope<clang::interp::EvalEmitter>::addLocal(clang::interp::Scope::Local const&) |
296 | | |
297 | 21 | void emitDestruction() override { |
298 | 21 | if (!Idx.hasValue()) |
299 | 21 | return; |
300 | 0 | this->Ctx->emitDestroy(*Idx, SourceInfo{}); |
301 | 0 | } clang::interp::LocalScope<clang::interp::ByteCodeEmitter>::emitDestruction() Line | Count | Source | 297 | 14 | void emitDestruction() override { | 298 | 14 | if (!Idx.hasValue()) | 299 | 14 | return; | 300 | 0 | this->Ctx->emitDestroy(*Idx, SourceInfo{}); | 301 | 0 | } |
clang::interp::LocalScope<clang::interp::EvalEmitter>::emitDestruction() Line | Count | Source | 297 | 7 | void emitDestruction() override { | 298 | 7 | if (!Idx.hasValue()) | 299 | 7 | return; | 300 | 0 | this->Ctx->emitDestroy(*Idx, SourceInfo{}); | 301 | 0 | } |
|
302 | | |
303 | | protected: |
304 | | /// Index of the scope in the chain. |
305 | | Optional<unsigned> Idx; |
306 | | }; |
307 | | |
308 | | /// Scope for storage declared in a compound statement. |
309 | | template <class Emitter> class BlockScope final : public LocalScope<Emitter> { |
310 | | public: |
311 | 4 | BlockScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {} |
312 | | |
313 | 0 | void addExtended(const Scope::Local &Local) override { |
314 | 0 | llvm_unreachable("Cannot create temporaries in full scopes"); |
315 | 0 | } |
316 | | }; |
317 | | |
318 | | /// Expression scope which tracks potentially lifetime extended |
319 | | /// temporaries which are hoisted to the parent scope on exit. |
320 | | template <class Emitter> class ExprScope final : public LocalScope<Emitter> { |
321 | | public: |
322 | 9 | ExprScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {} clang::interp::ExprScope<clang::interp::ByteCodeEmitter>::ExprScope(clang::interp::ByteCodeExprGen<clang::interp::ByteCodeEmitter>*) Line | Count | Source | 322 | 2 | ExprScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {} |
clang::interp::ExprScope<clang::interp::EvalEmitter>::ExprScope(clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>*) Line | Count | Source | 322 | 7 | ExprScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {} |
|
323 | | |
324 | 0 | void addExtended(const Scope::Local &Local) override { |
325 | 0 | this->Parent->addLocal(Local); |
326 | 0 | } Unexecuted instantiation: clang::interp::ExprScope<clang::interp::ByteCodeEmitter>::addExtended(clang::interp::Scope::Local const&) Unexecuted instantiation: clang::interp::ExprScope<clang::interp::EvalEmitter>::addExtended(clang::interp::Scope::Local const&) |
327 | | }; |
328 | | |
329 | | } // namespace interp |
330 | | } // namespace clang |
331 | | |
332 | | #endif |