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