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 
15 using namespace clang;
16 using namespace clang::interp;
17 
18 namespace clang {
19 namespace interp {
20 
21 /// Scope managing label targets.
22 template <class Emitter> class LabelScope {
23 public:
24  virtual ~LabelScope() { }
25 
26 protected:
28  /// ByteCodeStmtGen instance.
30 };
31 
32 /// Sets the context for break/continue statements.
33 template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
34 public:
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 
51 private:
52  OptLabelTy OldBreakLabel;
53  OptLabelTy OldContinueLabel;
54 };
55 
56 // Sets the context for a switch scope, mapping labels.
57 template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
58 public:
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 
79 private:
80  OptLabelTy OldBreakLabel;
81  OptLabelTy OldDefaultLabel;
82  CaseMap OldCaseLabels;
83 };
84 
85 } // namespace interp
86 } // namespace clang
87 
88 template <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 
139 template <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 
256 template <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.
308 template <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 
323 template <class Emitter>
325  const CompoundStmt *CompoundStmt) {
327  for (auto *InnerStmt : CompoundStmt->body())
328  if (!visitStmt(InnerStmt))
329  return false;
330  return true;
331 }
332 
333 template <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 
350 template <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 
382 template <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 
427 template <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 
461 template <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 
489 template <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 
533 template <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 
587 template <class Emitter>
589  if (!BreakLabel)
590  return false;
591 
592  this->VarScope->emitDestructors();
593  return this->jump(*BreakLabel);
594 }
595 
596 template <class Emitter>
598  if (!ContinueLabel)
599  return false;
600 
601  this->VarScope->emitDestructors();
602  return this->jump(*ContinueLabel);
603 }
604 
605 template <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 
675 template <class Emitter>
677  this->emitLabel(CaseLabels[S]);
678  return this->visitStmt(S->getSubStmt());
679 }
680 
681 template <class Emitter>
683  this->emitLabel(*DefaultLabel);
684  return this->visitStmt(S->getSubStmt());
685 }
686 
687 template <class Emitter>
689 
690  if (this->Ctx.getLangOpts().CXXAssumptions &&
691  !this->Ctx.getLangOpts().MSVCCompat) {
692  for (const Attr *A : S->getAttrs()) {
693  auto *AA = dyn_cast<CXXAssumeAttr>(A);
694  if (!AA)
695  continue;
696 
697  assert(isa<NullStmt>(S->getSubStmt()));
698 
699  const Expr *Assumption = AA->getAssumption();
700  if (Assumption->isValueDependent())
701  return false;
702 
703  if (Assumption->HasSideEffects(this->Ctx.getASTContext()))
704  continue;
705 
706  // Evaluate assumption.
707  if (!this->visitBool(Assumption))
708  return false;
709 
710  if (!this->emitAssume(Assumption))
711  return false;
712  }
713  }
714 
715  // Ignore other attributes.
716  return this->visitStmt(S->getSubStmt());
717 }
718 
719 template <class Emitter>
721  // Ignore all handlers.
722  return this->visitStmt(S->getTryBlock());
723 }
724 
725 namespace clang {
726 namespace interp {
727 
728 template class ByteCodeStmtGen<ByteCodeEmitter>;
729 
730 } // namespace interp
731 } // namespace clang
StringRef P
Attr - This represents one attribute.
Definition: Attr.h:46
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:3608
QualType getType() const
Definition: Expr.h:142
Represents a member of a struct/union/class.
Definition: Decl.h:3060
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2781
Represents a function declaration or definition.
Definition: Decl.h:1972
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition: Decl.cpp:3240
QualType getReturnType() const
Definition: Decl.h:2757
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2686
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3696
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition: Decl.cpp:3160
IfStmt - This represents an if/then/else.
Definition: Stmt.h:2138
Expr * getCond()
Definition: Stmt.h:2215
Stmt * getElse()
Definition: Stmt.h:2236
bool isNonNegatedConsteval() const
Definition: Stmt.h:2323
Stmt * getInit()
Definition: Stmt.h:2288
bool isNegatedConsteval() const
Definition: Stmt.h:2327
Stmt * getThen()
Definition: Stmt.h:2227
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:3344
This represents a decl that may have a name.
Definition: Decl.h:249
Represents a parameter to a function.
Definition: Decl.h:1762
Represents a struct/union/class.
Definition: Decl.h:4171
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:3587
The base class of the type hierarchy.
Definition: Type.h:1813
bool isVoidType() const
Definition: Type.h:7939
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3435
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:919
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
bool Inc(InterpState &S, CodePtr OpPC)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
Definition: Interp.h:590
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:32
bool Init(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1472
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition: Address.h:294
const FunctionProtoType * T
Definition: Format.h:5433
#define true
Definition: stdbool.h:25