clang 18.0.0git
ByteCodeStmtGen.cpp
Go to the documentation of this file.
1//===--- ByteCodeStmtGen.cpp - 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#include "ByteCodeStmtGen.h"
10#include "ByteCodeEmitter.h"
11#include "ByteCodeGenError.h"
12#include "Context.h"
13#include "Function.h"
14#include "PrimType.h"
15
16using namespace clang;
17using namespace clang::interp;
18
19namespace clang {
20namespace interp {
21
22/// Scope managing label targets.
23template <class Emitter> class LabelScope {
24public:
25 virtual ~LabelScope() { }
26
27protected:
29 /// ByteCodeStmtGen instance.
31};
32
33/// Sets the context for break/continue statements.
34template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
35public:
36 using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
37 using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy;
38
40 LabelTy ContinueLabel)
41 : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
42 OldContinueLabel(Ctx->ContinueLabel) {
43 this->Ctx->BreakLabel = BreakLabel;
44 this->Ctx->ContinueLabel = ContinueLabel;
45 }
46
48 this->Ctx->BreakLabel = OldBreakLabel;
49 this->Ctx->ContinueLabel = OldContinueLabel;
50 }
51
52private:
53 OptLabelTy OldBreakLabel;
54 OptLabelTy OldContinueLabel;
55};
56
57// Sets the context for a switch scope, mapping labels.
58template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
59public:
60 using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
61 using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy;
62 using CaseMap = typename ByteCodeStmtGen<Emitter>::CaseMap;
63
65 LabelTy BreakLabel, OptLabelTy DefaultLabel)
66 : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
67 OldDefaultLabel(this->Ctx->DefaultLabel),
68 OldCaseLabels(std::move(this->Ctx->CaseLabels)) {
69 this->Ctx->BreakLabel = BreakLabel;
70 this->Ctx->DefaultLabel = DefaultLabel;
71 this->Ctx->CaseLabels = std::move(CaseLabels);
72 }
73
75 this->Ctx->BreakLabel = OldBreakLabel;
76 this->Ctx->DefaultLabel = OldDefaultLabel;
77 this->Ctx->CaseLabels = std::move(OldCaseLabels);
78 }
79
80private:
81 OptLabelTy OldBreakLabel;
82 OptLabelTy OldDefaultLabel;
83 CaseMap OldCaseLabels;
84};
85
86} // namespace interp
87} // namespace clang
88
89template <class Emitter>
91 const CXXMethodDecl *MD) {
92 assert(MD->isLambdaStaticInvoker());
93 assert(MD->hasBody());
94 assert(cast<CompoundStmt>(MD->getBody())->body_empty());
95
96 const CXXRecordDecl *ClosureClass = MD->getParent();
97 const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator();
98 assert(ClosureClass->captures_begin() == ClosureClass->captures_end());
99 const Function *Func = this->getFunction(LambdaCallOp);
100 if (!Func)
101 return false;
102 assert(Func->hasThisPointer());
103 assert(Func->getNumParams() == (MD->getNumParams() + 1 + Func->hasRVO()));
104
105 if (Func->hasRVO()) {
106 if (!this->emitRVOPtr(MD))
107 return false;
108 }
109
110 // The lambda call operator needs an instance pointer, but we don't have
111 // one here, and we don't need one either because the lambda cannot have
112 // any captures, as verified above. Emit a null pointer. This is then
113 // special-cased when interpreting to not emit any misleading diagnostics.
114 if (!this->emitNullPtr(MD))
115 return false;
116
117 // Forward all arguments from the static invoker to the lambda call operator.
118 for (const ParmVarDecl *PVD : MD->parameters()) {
119 auto It = this->Params.find(PVD);
120 assert(It != this->Params.end());
121
122 // We do the lvalue-to-rvalue conversion manually here, so no need
123 // to care about references.
124 PrimType ParamType = this->classify(PVD->getType()).value_or(PT_Ptr);
125 if (!this->emitGetParam(ParamType, It->second.Offset, MD))
126 return false;
127 }
128
129 if (!this->emitCall(Func, LambdaCallOp))
130 return false;
131
132 this->emitCleanup();
133 if (ReturnType)
134 return this->emitRet(*ReturnType, MD);
135
136 // Nothing to do, since we emitted the RVO pointer above.
137 return this->emitRetVoid(MD);
138}
139
140template <class Emitter>
142 // Classify the return type.
143 ReturnType = this->classify(F->getReturnType());
144
145 // Emit custom code if this is a lambda static invoker.
146 if (const auto *MD = dyn_cast<CXXMethodDecl>(F);
147 MD && MD->isLambdaStaticInvoker())
148 return this->emitLambdaStaticInvokerBody(MD);
149
150 // Constructor. Set up field initializers.
151 if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(F)) {
152 const RecordDecl *RD = Ctor->getParent();
153 const Record *R = this->getRecord(RD);
154 if (!R)
155 return false;
156
157 for (const auto *Init : Ctor->inits()) {
158 // Scope needed for the initializers.
160
161 const Expr *InitExpr = Init->getInit();
162 if (const FieldDecl *Member = Init->getMember()) {
163 const Record::Field *F = R->getField(Member);
164
165 if (std::optional<PrimType> T = this->classify(InitExpr)) {
166 if (!this->visit(InitExpr))
167 return false;
168
169 if (F->isBitField()) {
170 if (!this->emitInitThisBitField(*T, F, InitExpr))
171 return false;
172 } else {
173 if (!this->emitInitThisField(*T, F->Offset, InitExpr))
174 return false;
175 }
176 } else {
177 // Non-primitive case. Get a pointer to the field-to-initialize
178 // on the stack and call visitInitialzer() for it.
179 if (!this->emitGetPtrThisField(F->Offset, InitExpr))
180 return false;
181
182 if (!this->visitInitializer(InitExpr))
183 return false;
184
185 if (!this->emitPopPtr(InitExpr))
186 return false;
187 }
188 } else if (const Type *Base = Init->getBaseClass()) {
189 // Base class initializer.
190 // Get This Base and call initializer on it.
191 const auto *BaseDecl = Base->getAsCXXRecordDecl();
192 assert(BaseDecl);
193 const Record::Base *B = R->getBase(BaseDecl);
194 assert(B);
195 if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
196 return false;
197 if (!this->visitInitializer(InitExpr))
198 return false;
199 if (!this->emitInitPtrPop(InitExpr))
200 return false;
201 } else {
202 assert(Init->isDelegatingInitializer());
203 if (!this->emitThis(InitExpr))
204 return false;
205 if (!this->visitInitializer(Init->getInit()))
206 return false;
207 if (!this->emitPopPtr(InitExpr))
208 return false;
209 }
210 }
211 }
212
213 if (const auto *Body = F->getBody())
214 if (!visitStmt(Body))
215 return false;
216
217 // Emit a guard return to protect against a code path missing one.
218 if (F->getReturnType()->isVoidType())
219 return this->emitRetVoid(SourceInfo{});
220 else
221 return this->emitNoRet(SourceInfo{});
222}
223
224template <class Emitter>
226 switch (S->getStmtClass()) {
227 case Stmt::CompoundStmtClass:
228 return visitCompoundStmt(cast<CompoundStmt>(S));
229 case Stmt::DeclStmtClass:
230 return visitDeclStmt(cast<DeclStmt>(S));
231 case Stmt::ReturnStmtClass:
232 return visitReturnStmt(cast<ReturnStmt>(S));
233 case Stmt::IfStmtClass:
234 return visitIfStmt(cast<IfStmt>(S));
235 case Stmt::WhileStmtClass:
236 return visitWhileStmt(cast<WhileStmt>(S));
237 case Stmt::DoStmtClass:
238 return visitDoStmt(cast<DoStmt>(S));
239 case Stmt::ForStmtClass:
240 return visitForStmt(cast<ForStmt>(S));
241 case Stmt::CXXForRangeStmtClass:
242 return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
243 case Stmt::BreakStmtClass:
244 return visitBreakStmt(cast<BreakStmt>(S));
245 case Stmt::ContinueStmtClass:
246 return visitContinueStmt(cast<ContinueStmt>(S));
247 case Stmt::SwitchStmtClass:
248 return visitSwitchStmt(cast<SwitchStmt>(S));
249 case Stmt::CaseStmtClass:
250 return visitCaseStmt(cast<CaseStmt>(S));
251 case Stmt::DefaultStmtClass:
252 return visitDefaultStmt(cast<DefaultStmt>(S));
253 case Stmt::GCCAsmStmtClass:
254 case Stmt::MSAsmStmtClass:
255 return visitAsmStmt(cast<AsmStmt>(S));
256 case Stmt::AttributedStmtClass:
257 return visitAttributedStmt(cast<AttributedStmt>(S));
258 case Stmt::CXXTryStmtClass:
259 return visitCXXTryStmt(cast<CXXTryStmt>(S));
260 case Stmt::NullStmtClass:
261 return true;
262 default: {
263 if (auto *Exp = dyn_cast<Expr>(S))
264 return this->discard(Exp);
265 return this->bail(S);
266 }
267 }
268}
269
270/// Visits the given statment without creating a variable
271/// scope for it in case it is a compound statement.
272template <class Emitter>
274 if (isa<NullStmt>(S))
275 return true;
276
277 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
278 for (auto *InnerStmt : CS->body())
279 if (!visitStmt(InnerStmt))
280 return false;
281 return true;
282 }
283
284 return this->visitStmt(S);
285}
286
287template <class Emitter>
289 const CompoundStmt *CompoundStmt) {
291 for (auto *InnerStmt : CompoundStmt->body())
292 if (!visitStmt(InnerStmt))
293 return false;
294 return true;
295}
296
297template <class Emitter>
299 for (auto *D : DS->decls()) {
300 if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl>(D))
301 continue;
302
303 const auto *VD = dyn_cast<VarDecl>(D);
304 if (!VD)
305 return false;
306 if (!this->visitVarDecl(VD))
307 return false;
308 }
309
310 return true;
311}
312
313template <class Emitter>
315 if (const Expr *RE = RS->getRetValue()) {
316 ExprScope<Emitter> RetScope(this);
317 if (ReturnType) {
318 // Primitive types are simply returned.
319 if (!this->visit(RE))
320 return false;
321 this->emitCleanup();
322 return this->emitRet(*ReturnType, RS);
323 } else if (RE->getType()->isVoidType()) {
324 if (!this->visit(RE))
325 return false;
326 } else {
327 // RVO - construct the value in the return location.
328 if (!this->emitRVOPtr(RE))
329 return false;
330 if (!this->visitInitializer(RE))
331 return false;
332 if (!this->emitPopPtr(RE))
333 return false;
334
335 this->emitCleanup();
336 return this->emitRetVoid(RS);
337 }
338 }
339
340 // Void return.
341 this->emitCleanup();
342 return this->emitRetVoid(RS);
343}
344
345template <class Emitter>
347 BlockScope<Emitter> IfScope(this);
348
349 if (IS->isNonNegatedConsteval())
350 return visitStmt(IS->getThen());
351 if (IS->isNegatedConsteval())
352 return IS->getElse() ? visitStmt(IS->getElse()) : true;
353
354 if (auto *CondInit = IS->getInit())
355 if (!visitStmt(CondInit))
356 return false;
357
358 if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())
359 if (!visitDeclStmt(CondDecl))
360 return false;
361
362 if (!this->visitBool(IS->getCond()))
363 return false;
364
365 if (const Stmt *Else = IS->getElse()) {
366 LabelTy LabelElse = this->getLabel();
367 LabelTy LabelEnd = this->getLabel();
368 if (!this->jumpFalse(LabelElse))
369 return false;
370 if (!visitStmt(IS->getThen()))
371 return false;
372 if (!this->jump(LabelEnd))
373 return false;
374 this->emitLabel(LabelElse);
375 if (!visitStmt(Else))
376 return false;
377 this->emitLabel(LabelEnd);
378 } else {
379 LabelTy LabelEnd = this->getLabel();
380 if (!this->jumpFalse(LabelEnd))
381 return false;
382 if (!visitStmt(IS->getThen()))
383 return false;
384 this->emitLabel(LabelEnd);
385 }
386
387 return true;
388}
389
390template <class Emitter>
392 const Expr *Cond = S->getCond();
393 const Stmt *Body = S->getBody();
394
395 LabelTy CondLabel = this->getLabel(); // Label before the condition.
396 LabelTy EndLabel = this->getLabel(); // Label after the loop.
397 LoopScope<Emitter> LS(this, EndLabel, CondLabel);
398
399 this->emitLabel(CondLabel);
400 if (!this->visitBool(Cond))
401 return false;
402 if (!this->jumpFalse(EndLabel))
403 return false;
404
406 {
408 if (!this->visitLoopBody(Body))
409 return false;
410 }
411
412 if (!this->jump(CondLabel))
413 return false;
414 this->emitLabel(EndLabel);
415
416 return true;
417}
418
419template <class Emitter>
421 const Expr *Cond = S->getCond();
422 const Stmt *Body = S->getBody();
423
424 LabelTy StartLabel = this->getLabel();
425 LabelTy EndLabel = this->getLabel();
426 LabelTy CondLabel = this->getLabel();
427 LoopScope<Emitter> LS(this, EndLabel, CondLabel);
429
430 this->emitLabel(StartLabel);
431 {
433
434 if (!this->visitLoopBody(Body))
435 return false;
436 this->emitLabel(CondLabel);
437 if (!this->visitBool(Cond))
438 return false;
439 }
440 if (!this->jumpTrue(StartLabel))
441 return false;
442
443 this->emitLabel(EndLabel);
444 return true;
445}
446
447template <class Emitter>
449 // for (Init; Cond; Inc) { Body }
450 const Stmt *Init = S->getInit();
451 const Expr *Cond = S->getCond();
452 const Expr *Inc = S->getInc();
453 const Stmt *Body = S->getBody();
454
455 LabelTy EndLabel = this->getLabel();
456 LabelTy CondLabel = this->getLabel();
457 LabelTy IncLabel = this->getLabel();
458 LoopScope<Emitter> LS(this, EndLabel, IncLabel);
460
461 if (Init && !this->visitStmt(Init))
462 return false;
463 this->emitLabel(CondLabel);
464 if (Cond) {
465 if (!this->visitBool(Cond))
466 return false;
467 if (!this->jumpFalse(EndLabel))
468 return false;
469 }
470
471 {
473
474 if (Body && !this->visitLoopBody(Body))
475 return false;
476 this->emitLabel(IncLabel);
477 if (Inc && !this->discard(Inc))
478 return false;
479 }
480
481 if (!this->jump(CondLabel))
482 return false;
483 this->emitLabel(EndLabel);
484 return true;
485}
486
487template <class Emitter>
489 const Stmt *Init = S->getInit();
490 const Expr *Cond = S->getCond();
491 const Expr *Inc = S->getInc();
492 const Stmt *Body = S->getBody();
493 const Stmt *BeginStmt = S->getBeginStmt();
494 const Stmt *RangeStmt = S->getRangeStmt();
495 const Stmt *EndStmt = S->getEndStmt();
496 const VarDecl *LoopVar = S->getLoopVariable();
497
498 LabelTy EndLabel = this->getLabel();
499 LabelTy CondLabel = this->getLabel();
500 LabelTy IncLabel = this->getLabel();
501 LoopScope<Emitter> LS(this, EndLabel, IncLabel);
502
503 // Emit declarations needed in the loop.
504 if (Init && !this->visitStmt(Init))
505 return false;
506 if (!this->visitStmt(RangeStmt))
507 return false;
508 if (!this->visitStmt(BeginStmt))
509 return false;
510 if (!this->visitStmt(EndStmt))
511 return false;
512
513 // Now the condition as well as the loop variable assignment.
514 this->emitLabel(CondLabel);
515 if (!this->visitBool(Cond))
516 return false;
517 if (!this->jumpFalse(EndLabel))
518 return false;
519
520 if (!this->visitVarDecl(LoopVar))
521 return false;
522
523 // Body.
525 {
527
528 if (!this->visitLoopBody(Body))
529 return false;
530 this->emitLabel(IncLabel);
531 if (!this->discard(Inc))
532 return false;
533 }
534 if (!this->jump(CondLabel))
535 return false;
536
537 this->emitLabel(EndLabel);
538 return true;
539}
540
541template <class Emitter>
543 if (!BreakLabel)
544 return false;
545
546 this->VarScope->emitDestructors();
547 return this->jump(*BreakLabel);
548}
549
550template <class Emitter>
552 if (!ContinueLabel)
553 return false;
554
555 this->VarScope->emitDestructors();
556 return this->jump(*ContinueLabel);
557}
558
559template <class Emitter>
561 const Expr *Cond = S->getCond();
562 PrimType CondT = this->classifyPrim(Cond->getType());
563
564 LabelTy EndLabel = this->getLabel();
565 OptLabelTy DefaultLabel = std::nullopt;
566 unsigned CondVar = this->allocateLocalPrimitive(Cond, CondT, true, false);
567
568 if (const auto *CondInit = S->getInit())
569 if (!visitStmt(CondInit))
570 return false;
571
572 // Initialize condition variable.
573 if (!this->visit(Cond))
574 return false;
575 if (!this->emitSetLocal(CondT, CondVar, S))
576 return false;
577
578 CaseMap CaseLabels;
579 // Create labels and comparison ops for all case statements.
580 for (const SwitchCase *SC = S->getSwitchCaseList(); SC;
581 SC = SC->getNextSwitchCase()) {
582 if (const auto *CS = dyn_cast<CaseStmt>(SC)) {
583 // FIXME: Implement ranges.
584 if (CS->caseStmtIsGNURange())
585 return false;
586 CaseLabels[SC] = this->getLabel();
587
588 const Expr *Value = CS->getLHS();
589 PrimType ValueT = this->classifyPrim(Value->getType());
590
591 // Compare the case statement's value to the switch condition.
592 if (!this->emitGetLocal(CondT, CondVar, CS))
593 return false;
594 if (!this->visit(Value))
595 return false;
596
597 // Compare and jump to the case label.
598 if (!this->emitEQ(ValueT, S))
599 return false;
600 if (!this->jumpTrue(CaseLabels[CS]))
601 return false;
602 } else {
603 assert(!DefaultLabel);
604 DefaultLabel = this->getLabel();
605 }
606 }
607
608 // If none of the conditions above were true, fall through to the default
609 // statement or jump after the switch statement.
610 if (DefaultLabel) {
611 if (!this->jump(*DefaultLabel))
612 return false;
613 } else {
614 if (!this->jump(EndLabel))
615 return false;
616 }
617
618 SwitchScope<Emitter> SS(this, std::move(CaseLabels), EndLabel, DefaultLabel);
619 if (!this->visitStmt(S->getBody()))
620 return false;
621 this->emitLabel(EndLabel);
622 return true;
623}
624
625template <class Emitter>
627 this->emitLabel(CaseLabels[S]);
628 return this->visitStmt(S->getSubStmt());
629}
630
631template <class Emitter>
633 this->emitLabel(*DefaultLabel);
634 return this->visitStmt(S->getSubStmt());
635}
636
637template <class Emitter>
639 return this->emitInvalid(S);
640}
641
642template <class Emitter>
644 // Ignore all attributes.
645 return this->visitStmt(S->getSubStmt());
646}
647
648template <class Emitter>
650 // Ignore all handlers.
651 return this->visitStmt(S->getTryBlock());
652}
653
654namespace clang {
655namespace interp {
656
658
659} // namespace interp
660} // namespace clang
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
Definition: Stmt.h:3094
Represents an attribute applied to a statement.
Definition: Stmt.h:2074
BreakStmt - This represents a break.
Definition: Stmt.h:2974
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition: StmtCXX.h:135
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2053
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition: DeclCXX.h:2179
bool isLambdaStaticInvoker() const
Determine whether this is a lambda closure type's static member function that is used for the result ...
Definition: DeclCXX.cpp:2548
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
capture_const_iterator captures_end() const
Definition: DeclCXX.h:1110
capture_const_iterator captures_begin() const
Definition: DeclCXX.h:1104
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
Definition: DeclCXX.cpp:1553
CXXTryStmt - A C++ try block, including all handlers.
Definition: StmtCXX.h:69
CaseStmt - Represent a case statement.
Definition: Stmt.h:1795
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1602
body_range body()
Definition: Stmt.h:1658
ContinueStmt - This represents a continue.
Definition: Stmt.h:2944
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2065
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1493
decl_range decls()
Definition: Stmt.h:1541
DoStmt - This represents a 'do/while' stmt.
Definition: Stmt.h:2719
This represents one expression.
Definition: Expr.h:110
QualType getType() const
Definition: Expr.h:142
Represents a member of a struct/union/class.
Definition: Decl.h:3015
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2775
Represents a function declaration or definition.
Definition: Decl.h:1957
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition: Decl.cpp:3187
QualType getReturnType() const
Definition: Decl.h:2712
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2641
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3629
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition: Decl.cpp:3107
IfStmt - This represents an if/then/else.
Definition: Stmt.h:2132
Stmt * getThen()
Definition: Stmt.h:2221
Stmt * getInit()
Definition: Stmt.h:2282
bool isNonNegatedConsteval() const
Definition: Stmt.h:2317
Expr * getCond()
Definition: Stmt.h:2209
bool isNegatedConsteval() const
Definition: Stmt.h:2321
Stmt * getElse()
Definition: Stmt.h:2230
DeclStmt * getConditionVariableDeclStmt()
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
Definition: Stmt.h:2265
Represents a parameter to a function.
Definition: Decl.h:1747
Represents a struct/union/class.
Definition: Decl.h:4117
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition: Stmt.h:3013
Expr * getRetValue()
Definition: Stmt.h:3044
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
Stmt - This represents one statement.
Definition: Stmt.h:84
SwitchStmt - This represents a 'switch' stmt.
Definition: Stmt.h:2382
The base class of the type hierarchy.
Definition: Type.h:1602
bool isVoidType() const
Definition: Type.h:7352
QualType getType() const
Definition: Value.cpp:234
Represents a variable declaration or definition.
Definition: Decl.h:916
WhileStmt - This represents a 'while' stmt.
Definition: Stmt.h:2578
Scope for storage declared in a compound statement.
Compilation context for statements.
bool visitFunc(const FunctionDecl *F) override
Emits the destructors of the variables of.
Expression scope which tracks potentially lifetime extended temporaries which are hoisted to the pare...
Bytecode function.
Definition: Function.h:76
Scope managing label targets.
LabelScope(ByteCodeStmtGen< Emitter > *Ctx)
ByteCodeStmtGen< Emitter > * Ctx
ByteCodeStmtGen instance.
Generic scope for local variables.
Sets the context for break/continue statements.
LoopScope(ByteCodeStmtGen< Emitter > *Ctx, LabelTy BreakLabel, LabelTy ContinueLabel)
typename ByteCodeStmtGen< Emitter >::LabelTy LabelTy
typename ByteCodeStmtGen< Emitter >::OptLabelTy OptLabelTy
Structure/Class descriptor.
Definition: Record.h:25
const Field * getField(const FieldDecl *FD) const
Returns a field.
Definition: Record.cpp:30
const Base * getBase(const RecordDecl *FD) const
Returns a base descriptor.
Definition: Record.cpp:36
Describes a scope block.
Definition: Function.h:34
Describes the statement/declaration an opcode was generated from.
Definition: Source.h:72
typename ByteCodeStmtGen< Emitter >::LabelTy LabelTy
SwitchScope(ByteCodeStmtGen< Emitter > *Ctx, CaseMap &&CaseLabels, LabelTy BreakLabel, OptLabelTy DefaultLabel)
typename ByteCodeStmtGen< Emitter >::OptLabelTy OptLabelTy
typename ByteCodeStmtGen< Emitter >::CaseMap CaseMap
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:32
Definition: Format.h:5202
#define true
Definition: stdbool.h:21
Describes a base class.
Definition: Record.h:36
Describes a record field.
Definition: Record.h:28
bool isBitField() const
Definition: Record.h:32