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 const auto *BaseDecl = Base->getAsCXXRecordDecl();
193 assert(BaseDecl);
194
195 if (Init->isBaseVirtual()) {
196 assert(R->getVirtualBase(BaseDecl));
197 if (!this->emitGetPtrThisVirtBase(BaseDecl, InitExpr))
198 return false;
199
200 } else {
201 // Base class initializer.
202 // Get This Base and call initializer on it.
203 const Record::Base *B = R->getBase(BaseDecl);
204 assert(B);
205 if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
206 return false;
207 }
208
209 if (!this->visitInitializer(InitExpr))
210 return false;
211 if (!this->emitFinishInitPop(InitExpr))
212 return false;
213 } else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {
214 assert(IFD->getChainingSize() >= 2);
215
216 unsigned NestedFieldOffset = 0;
217 const Record::Field *NestedField = nullptr;
218 for (const NamedDecl *ND : IFD->chain()) {
219 const auto *FD = cast<FieldDecl>(ND);
220 const Record *FieldRecord =
221 this->P.getOrCreateRecord(FD->getParent());
222 assert(FieldRecord);
223
224 NestedField = FieldRecord->getField(FD);
225 assert(NestedField);
226
227 NestedFieldOffset += NestedField->Offset;
228 }
229 assert(NestedField);
230
231 if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr))
232 return false;
233 } else {
234 assert(Init->isDelegatingInitializer());
235 if (!this->emitThis(InitExpr))
236 return false;
237 if (!this->visitInitializer(Init->getInit()))
238 return false;
239 if (!this->emitPopPtr(InitExpr))
240 return false;
241 }
242 }
243 }
244
245 if (const auto *Body = F->getBody())
246 if (!visitStmt(Body))
247 return false;
248
249 // Emit a guard return to protect against a code path missing one.
250 if (F->getReturnType()->isVoidType())
251 return this->emitRetVoid(SourceInfo{});
252 else
253 return this->emitNoRet(SourceInfo{});
254}
255
256template <class Emitter>
258 switch (S->getStmtClass()) {
259 case Stmt::CompoundStmtClass:
260 return visitCompoundStmt(cast<CompoundStmt>(S));
261 case Stmt::DeclStmtClass:
262 return visitDeclStmt(cast<DeclStmt>(S));
263 case Stmt::ReturnStmtClass:
264 return visitReturnStmt(cast<ReturnStmt>(S));
265 case Stmt::IfStmtClass:
266 return visitIfStmt(cast<IfStmt>(S));
267 case Stmt::WhileStmtClass:
268 return visitWhileStmt(cast<WhileStmt>(S));
269 case Stmt::DoStmtClass:
270 return visitDoStmt(cast<DoStmt>(S));
271 case Stmt::ForStmtClass:
272 return visitForStmt(cast<ForStmt>(S));
273 case Stmt::CXXForRangeStmtClass:
274 return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
275 case Stmt::BreakStmtClass:
276 return visitBreakStmt(cast<BreakStmt>(S));
277 case Stmt::ContinueStmtClass:
278 return visitContinueStmt(cast<ContinueStmt>(S));
279 case Stmt::SwitchStmtClass:
280 return visitSwitchStmt(cast<SwitchStmt>(S));
281 case Stmt::CaseStmtClass:
282 return visitCaseStmt(cast<CaseStmt>(S));
283 case Stmt::DefaultStmtClass:
284 return visitDefaultStmt(cast<DefaultStmt>(S));
285 case Stmt::AttributedStmtClass:
286 return visitAttributedStmt(cast<AttributedStmt>(S));
287 case Stmt::CXXTryStmtClass:
288 return visitCXXTryStmt(cast<CXXTryStmt>(S));
289 case Stmt::NullStmtClass:
290 return true;
291 // Always invalid statements.
292 case Stmt::GCCAsmStmtClass:
293 case Stmt::MSAsmStmtClass:
294 case Stmt::GotoStmtClass:
295 return this->emitInvalid(S);
296 case Stmt::LabelStmtClass:
297 return this->visitStmt(cast<LabelStmt>(S)->getSubStmt());
298 default: {
299 if (auto *Exp = dyn_cast<Expr>(S))
300 return this->discard(Exp);
301 return false;
302 }
303 }
304}
305
306/// Visits the given statment without creating a variable
307/// scope for it in case it is a compound statement.
308template <class Emitter>
310 if (isa<NullStmt>(S))
311 return true;
312
313 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
314 for (auto *InnerStmt : CS->body())
315 if (!visitStmt(InnerStmt))
316 return false;
317 return true;
318 }
319
320 return this->visitStmt(S);
321}
322
323template <class Emitter>
325 const CompoundStmt *CompoundStmt) {
327 for (auto *InnerStmt : CompoundStmt->body())
328 if (!visitStmt(InnerStmt))
329 return false;
330 return true;
331}
332
333template <class Emitter>
335 for (auto *D : DS->decls()) {
337 FunctionDecl>(D))
338 continue;
339
340 const auto *VD = dyn_cast<VarDecl>(D);
341 if (!VD)
342 return false;
343 if (!this->visitVarDecl(VD))
344 return false;
345 }
346
347 return true;
348}
349
350template <class Emitter>
352 if (const Expr *RE = RS->getRetValue()) {
353 ExprScope<Emitter> RetScope(this);
354 if (ReturnType) {
355 // Primitive types are simply returned.
356 if (!this->visit(RE))
357 return false;
358 this->emitCleanup();
359 return this->emitRet(*ReturnType, RS);
360 } else if (RE->getType()->isVoidType()) {
361 if (!this->visit(RE))
362 return false;
363 } else {
364 // RVO - construct the value in the return location.
365 if (!this->emitRVOPtr(RE))
366 return false;
367 if (!this->visitInitializer(RE))
368 return false;
369 if (!this->emitPopPtr(RE))
370 return false;
371
372 this->emitCleanup();
373 return this->emitRetVoid(RS);
374 }
375 }
376
377 // Void return.
378 this->emitCleanup();
379 return this->emitRetVoid(RS);
380}
381
382template <class Emitter>
384 BlockScope<Emitter> IfScope(this);
385
386 if (IS->isNonNegatedConsteval())
387 return visitStmt(IS->getThen());
388 if (IS->isNegatedConsteval())
389 return IS->getElse() ? visitStmt(IS->getElse()) : true;
390
391 if (auto *CondInit = IS->getInit())
392 if (!visitStmt(CondInit))
393 return false;
394
395 if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())
396 if (!visitDeclStmt(CondDecl))
397 return false;
398
399 if (!this->visitBool(IS->getCond()))
400 return false;
401
402 if (const Stmt *Else = IS->getElse()) {
403 LabelTy LabelElse = this->getLabel();
404 LabelTy LabelEnd = this->getLabel();
405 if (!this->jumpFalse(LabelElse))
406 return false;
407 if (!visitStmt(IS->getThen()))
408 return false;
409 if (!this->jump(LabelEnd))
410 return false;
411 this->emitLabel(LabelElse);
412 if (!visitStmt(Else))
413 return false;
414 this->emitLabel(LabelEnd);
415 } else {
416 LabelTy LabelEnd = this->getLabel();
417 if (!this->jumpFalse(LabelEnd))
418 return false;
419 if (!visitStmt(IS->getThen()))
420 return false;
421 this->emitLabel(LabelEnd);
422 }
423
424 return true;
425}
426
427template <class Emitter>
429 const Expr *Cond = S->getCond();
430 const Stmt *Body = S->getBody();
431
432 LabelTy CondLabel = this->getLabel(); // Label before the condition.
433 LabelTy EndLabel = this->getLabel(); // Label after the loop.
434 LoopScope<Emitter> LS(this, EndLabel, CondLabel);
435
436 this->emitLabel(CondLabel);
437
438 if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
439 if (!visitDeclStmt(CondDecl))
440 return false;
441
442 if (!this->visitBool(Cond))
443 return false;
444 if (!this->jumpFalse(EndLabel))
445 return false;
446
448 {
450 if (!this->visitLoopBody(Body))
451 return false;
452 }
453
454 if (!this->jump(CondLabel))
455 return false;
456 this->emitLabel(EndLabel);
457
458 return true;
459}
460
461template <class Emitter>
463 const Expr *Cond = S->getCond();
464 const Stmt *Body = S->getBody();
465
466 LabelTy StartLabel = this->getLabel();
467 LabelTy EndLabel = this->getLabel();
468 LabelTy CondLabel = this->getLabel();
469 LoopScope<Emitter> LS(this, EndLabel, CondLabel);
471
472 this->emitLabel(StartLabel);
473 {
475
476 if (!this->visitLoopBody(Body))
477 return false;
478 this->emitLabel(CondLabel);
479 if (!this->visitBool(Cond))
480 return false;
481 }
482 if (!this->jumpTrue(StartLabel))
483 return false;
484
485 this->emitLabel(EndLabel);
486 return true;
487}
488
489template <class Emitter>
491 // for (Init; Cond; Inc) { Body }
492 const Stmt *Init = S->getInit();
493 const Expr *Cond = S->getCond();
494 const Expr *Inc = S->getInc();
495 const Stmt *Body = S->getBody();
496
497 LabelTy EndLabel = this->getLabel();
498 LabelTy CondLabel = this->getLabel();
499 LabelTy IncLabel = this->getLabel();
500 LoopScope<Emitter> LS(this, EndLabel, IncLabel);
502
503 if (Init && !this->visitStmt(Init))
504 return false;
505 this->emitLabel(CondLabel);
506
507 if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
508 if (!visitDeclStmt(CondDecl))
509 return false;
510 if (Cond) {
511 if (!this->visitBool(Cond))
512 return false;
513 if (!this->jumpFalse(EndLabel))
514 return false;
515 }
516
517 {
519
520 if (Body && !this->visitLoopBody(Body))
521 return false;
522 this->emitLabel(IncLabel);
523 if (Inc && !this->discard(Inc))
524 return false;
525 }
526
527 if (!this->jump(CondLabel))
528 return false;
529 this->emitLabel(EndLabel);
530 return true;
531}
532
533template <class Emitter>
535 const Stmt *Init = S->getInit();
536 const Expr *Cond = S->getCond();
537 const Expr *Inc = S->getInc();
538 const Stmt *Body = S->getBody();
539 const Stmt *BeginStmt = S->getBeginStmt();
540 const Stmt *RangeStmt = S->getRangeStmt();
541 const Stmt *EndStmt = S->getEndStmt();
542 const VarDecl *LoopVar = S->getLoopVariable();
543
544 LabelTy EndLabel = this->getLabel();
545 LabelTy CondLabel = this->getLabel();
546 LabelTy IncLabel = this->getLabel();
547 LoopScope<Emitter> LS(this, EndLabel, IncLabel);
548
549 // Emit declarations needed in the loop.
550 if (Init && !this->visitStmt(Init))
551 return false;
552 if (!this->visitStmt(RangeStmt))
553 return false;
554 if (!this->visitStmt(BeginStmt))
555 return false;
556 if (!this->visitStmt(EndStmt))
557 return false;
558
559 // Now the condition as well as the loop variable assignment.
560 this->emitLabel(CondLabel);
561 if (!this->visitBool(Cond))
562 return false;
563 if (!this->jumpFalse(EndLabel))
564 return false;
565
566 if (!this->visitVarDecl(LoopVar))
567 return false;
568
569 // Body.
571 {
573
574 if (!this->visitLoopBody(Body))
575 return false;
576 this->emitLabel(IncLabel);
577 if (!this->discard(Inc))
578 return false;
579 }
580 if (!this->jump(CondLabel))
581 return false;
582
583 this->emitLabel(EndLabel);
584 return true;
585}
586
587template <class Emitter>
589 if (!BreakLabel)
590 return false;
591
592 this->VarScope->emitDestructors();
593 return this->jump(*BreakLabel);
594}
595
596template <class Emitter>
598 if (!ContinueLabel)
599 return false;
600
601 this->VarScope->emitDestructors();
602 return this->jump(*ContinueLabel);
603}
604
605template <class Emitter>
607 const Expr *Cond = S->getCond();
608
609 LabelTy EndLabel = this->getLabel();
610 OptLabelTy DefaultLabel = std::nullopt;
611
612 if (const auto *CondInit = S->getInit())
613 if (!visitStmt(CondInit))
614 return false;
615
616 if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
617 if (!visitDeclStmt(CondDecl))
618 return false;
619
620 // Initialize condition variable.
621 PrimType CondT = this->classifyPrim(Cond->getType());
622 unsigned CondVar = this->allocateLocalPrimitive(Cond, CondT, true, false);
623 if (!this->visit(Cond))
624 return false;
625 if (!this->emitSetLocal(CondT, CondVar, S))
626 return false;
627
628 CaseMap CaseLabels;
629 // Create labels and comparison ops for all case statements.
630 for (const SwitchCase *SC = S->getSwitchCaseList(); SC;
631 SC = SC->getNextSwitchCase()) {
632 if (const auto *CS = dyn_cast<CaseStmt>(SC)) {
633 // FIXME: Implement ranges.
634 if (CS->caseStmtIsGNURange())
635 return false;
636 CaseLabels[SC] = this->getLabel();
637
638 const Expr *Value = CS->getLHS();
639 PrimType ValueT = this->classifyPrim(Value->getType());
640
641 // Compare the case statement's value to the switch condition.
642 if (!this->emitGetLocal(CondT, CondVar, CS))
643 return false;
644 if (!this->visit(Value))
645 return false;
646
647 // Compare and jump to the case label.
648 if (!this->emitEQ(ValueT, S))
649 return false;
650 if (!this->jumpTrue(CaseLabels[CS]))
651 return false;
652 } else {
653 assert(!DefaultLabel);
654 DefaultLabel = this->getLabel();
655 }
656 }
657
658 // If none of the conditions above were true, fall through to the default
659 // statement or jump after the switch statement.
660 if (DefaultLabel) {
661 if (!this->jump(*DefaultLabel))
662 return false;
663 } else {
664 if (!this->jump(EndLabel))
665 return false;
666 }
667
668 SwitchScope<Emitter> SS(this, std::move(CaseLabels), EndLabel, DefaultLabel);
669 if (!this->visitStmt(S->getBody()))
670 return false;
671 this->emitLabel(EndLabel);
672 return true;
673}
674
675template <class Emitter>
677 this->emitLabel(CaseLabels[S]);
678 return this->visitStmt(S->getSubStmt());
679}
680
681template <class Emitter>
683 this->emitLabel(*DefaultLabel);
684 return this->visitStmt(S->getSubStmt());
685}
686
687template <class Emitter>
689
690 for (const Attr *A : S->getAttrs()) {
691 auto *AA = dyn_cast<CXXAssumeAttr>(A);
692 if (!AA)
693 continue;
694
695 assert(isa<NullStmt>(S->getSubStmt()));
696
697 const Expr *Assumption = AA->getAssumption();
698 if (Assumption->isValueDependent())
699 return false;
700
701 if (Assumption->HasSideEffects(this->Ctx.getASTContext()))
702 continue;
703
704 // Evaluate assumption.
705 if (!this->visitBool(Assumption))
706 return false;
707
708 if (!this->emitAssume(Assumption))
709 return false;
710 }
711
712 // Ignore other attributes.
713 return this->visitStmt(S->getSubStmt());
714}
715
716template <class Emitter>
718 // Ignore all handlers.
719 return this->visitStmt(S->getTryBlock());
720}
721
722namespace clang {
723namespace interp {
724
726
727} // namespace interp
728} // namespace clang
StringRef P
Attr - This represents one attribute.
Definition: Attr.h:42
Represents an attribute applied to a statement.
Definition: Stmt.h:2080
BreakStmt - This represents a break.
Definition: Stmt.h:2980
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:2060
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition: DeclCXX.h:2186
bool isLambdaStaticInvoker() const
Determine whether this is a lambda closure type's static member function that is used for the result ...
Definition: DeclCXX.cpp:2601
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
capture_const_iterator captures_end() const
Definition: DeclCXX.h:1111
capture_const_iterator captures_begin() const
Definition: DeclCXX.h:1105
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
Definition: DeclCXX.cpp:1594
CXXTryStmt - A C++ try block, including all handlers.
Definition: StmtCXX.h:69
CaseStmt - Represent a case statement.
Definition: Stmt.h:1801
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1606
body_range body()
Definition: Stmt.h:1664
ContinueStmt - This represents a continue.
Definition: Stmt.h:2950
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2066
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1497
decl_range decls()
Definition: Stmt.h:1545
DoStmt - This represents a 'do/while' stmt.
Definition: Stmt.h:2725
This represents one expression.
Definition: Expr.h:110
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:175
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Definition: Expr.cpp:3556
QualType getType() const
Definition: Expr.h:142
Represents a member of a struct/union/class.
Definition: Decl.h:3057
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2781
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:2754
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2683
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:2138
Stmt * getThen()
Definition: Stmt.h:2227
Stmt * getInit()
Definition: Stmt.h:2288
bool isNonNegatedConsteval() const
Definition: Stmt.h:2323
Expr * getCond()
Definition: Stmt.h:2215
bool isNegatedConsteval() const
Definition: Stmt.h:2327
Stmt * getElse()
Definition: Stmt.h:2236
DeclStmt * getConditionVariableDeclStmt()
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
Definition: Stmt.h:2271
Represents a field injected from an anonymous union/struct into the parent scope.
Definition: Decl.h:3341
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:4168
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition: Stmt.h:3019
Expr * getRetValue()
Definition: Stmt.h:3050
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
Represents a C++11 static_assert declaration.
Definition: DeclCXX.h:4058
Stmt - This represents one statement.
Definition: Stmt.h:84
SwitchStmt - This represents a 'switch' stmt.
Definition: Stmt.h:2388
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3584
The base class of the type hierarchy.
Definition: Type.h:1813
bool isVoidType() const
Definition: Type.h:7905
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3432
Represents a C++ using-enum-declaration.
Definition: DeclCXX.h:3713
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:2584
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.
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 * getVirtualBase(const RecordDecl *RD) const
Returns a virtual base descriptor.
Definition: Record.cpp:59
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:5428
#define true
Definition: stdbool.h:25