clang  16.0.0git
ByteCodeExprGen.cpp
Go to the documentation of this file.
1 //===--- ByteCodeExprGen.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 "ByteCodeExprGen.h"
10 #include "ByteCodeEmitter.h"
11 #include "ByteCodeGenError.h"
12 #include "ByteCodeStmtGen.h"
13 #include "Context.h"
14 #include "Function.h"
15 #include "PrimType.h"
16 #include "Program.h"
17 #include "State.h"
18 
19 using namespace clang;
20 using namespace clang::interp;
21 
23 template <typename T> using Expected = llvm::Expected<T>;
24 template <typename T> using Optional = llvm::Optional<T>;
25 
26 namespace clang {
27 namespace interp {
28 
29 /// Scope used to handle temporaries in toplevel variable declarations.
30 template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
31 public:
33  : LocalScope<Emitter>(Ctx), Scope(Ctx->P, VD) {}
34 
35  void addExtended(const Scope::Local &Local) override {
36  return this->addLocal(Local);
37  }
38 
39 private:
41 };
42 
43 /// Scope used to handle initialization methods.
44 template <class Emitter> class OptionScope {
45 public:
47  using ChainedInitFnRef = std::function<bool(InitFnRef)>;
48 
49  /// Root constructor, compiling or discarding primitives.
50  OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult)
51  : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
52  OldInitFn(std::move(Ctx->InitFn)) {
53  Ctx->DiscardResult = NewDiscardResult;
55  }
56 
57  /// Root constructor, setting up compilation state.
59  : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
60  OldInitFn(std::move(Ctx->InitFn)) {
61  Ctx->DiscardResult = true;
62  Ctx->InitFn = NewInitFn;
63  }
64 
65  /// Extends the chain of initialisation pointers.
67  : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
68  OldInitFn(std::move(Ctx->InitFn)) {
69  assert(OldInitFn && "missing initializer");
70  Ctx->InitFn = [this, NewInitFn] { return NewInitFn(*OldInitFn); };
71  }
72 
74  Ctx->DiscardResult = OldDiscardResult;
75  Ctx->InitFn = std::move(OldInitFn);
76  }
77 
78 private:
79  /// Parent context.
81  /// Old discard flag to restore.
82  bool OldDiscardResult;
83  /// Old pointer emitter to restore.
84  llvm::Optional<InitFnRef> OldInitFn;
85 };
86 
87 } // namespace interp
88 } // namespace clang
89 
90 template <class Emitter>
92  auto *SubExpr = CE->getSubExpr();
93  switch (CE->getCastKind()) {
94 
95  case CK_LValueToRValue: {
96  return dereference(
97  CE->getSubExpr(), DerefKind::Read,
98  [](PrimType) {
99  // Value loaded - nothing to do here.
100  return true;
101  },
102  [this, CE](PrimType T) {
103  // Pointer on stack - dereference it.
104  if (!this->emitLoadPop(T, CE))
105  return false;
106  return DiscardResult ? this->emitPop(T, CE) : true;
107  });
108  }
109 
110  case CK_UncheckedDerivedToBase:
111  case CK_DerivedToBase: {
112  if (!this->visit(SubExpr))
113  return false;
114 
115  const CXXRecordDecl *FromDecl = getRecordDecl(SubExpr);
116  assert(FromDecl);
117  const CXXRecordDecl *ToDecl = getRecordDecl(CE);
118  assert(ToDecl);
119  const Record *R = getRecord(FromDecl);
120  const Record::Base *ToBase = R->getBase(ToDecl);
121  assert(ToBase);
122 
123  return this->emitGetPtrBase(ToBase->Offset, CE);
124  }
125 
126  case CK_ArrayToPointerDecay:
127  case CK_AtomicToNonAtomic:
128  case CK_ConstructorConversion:
129  case CK_FunctionToPointerDecay:
130  case CK_NonAtomicToAtomic:
131  case CK_NoOp:
132  case CK_UserDefinedConversion:
133  case CK_NullToPointer:
134  return this->visit(SubExpr);
135 
136  case CK_IntegralToBoolean:
137  case CK_IntegralCast: {
138  Optional<PrimType> FromT = classify(SubExpr->getType());
139  Optional<PrimType> ToT = classify(CE->getType());
140  if (!FromT || !ToT)
141  return false;
142 
143  if (!this->visit(SubExpr))
144  return false;
145 
146  // TODO: Emit this only if FromT != ToT.
147  return this->emitCast(*FromT, *ToT, CE);
148  }
149 
150  case CK_ToVoid:
151  return discard(SubExpr);
152 
153  default:
154  assert(false && "Cast not implemented");
155  }
156  llvm_unreachable("Unhandled clang::CastKind enum");
157 }
158 
159 template <class Emitter>
161  if (DiscardResult)
162  return true;
163 
164  return this->emitConst(LE->getValue(), LE);
165 }
166 
167 template <class Emitter>
169  return this->visit(PE->getSubExpr());
170 }
171 
172 template <class Emitter>
174  const Expr *LHS = BO->getLHS();
175  const Expr *RHS = BO->getRHS();
176 
177  // Deal with operations which have composite or void types.
178  switch (BO->getOpcode()) {
179  case BO_Comma:
180  if (!discard(LHS))
181  return false;
182  if (!this->visit(RHS))
183  return false;
184  return true;
185  default:
186  break;
187  }
188 
189  // Typecheck the args.
190  Optional<PrimType> LT = classify(LHS->getType());
191  Optional<PrimType> RT = classify(RHS->getType());
192  Optional<PrimType> T = classify(BO->getType());
193  if (!LT || !RT || !T) {
194  return this->bail(BO);
195  }
196 
197  auto Discard = [this, T, BO](bool Result) {
198  if (!Result)
199  return false;
200  return DiscardResult ? this->emitPop(*T, BO) : true;
201  };
202 
203  // Pointer arithmetic special case.
204  if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {
205  if (*T == PT_Ptr || (*LT == PT_Ptr && *RT == PT_Ptr))
206  return this->VisitPointerArithBinOp(BO);
207  }
208 
209  if (!visit(LHS) || !visit(RHS))
210  return false;
211 
212  switch (BO->getOpcode()) {
213  case BO_EQ:
214  return Discard(this->emitEQ(*LT, BO));
215  case BO_NE:
216  return Discard(this->emitNE(*LT, BO));
217  case BO_LT:
218  return Discard(this->emitLT(*LT, BO));
219  case BO_LE:
220  return Discard(this->emitLE(*LT, BO));
221  case BO_GT:
222  return Discard(this->emitGT(*LT, BO));
223  case BO_GE:
224  return Discard(this->emitGE(*LT, BO));
225  case BO_Sub:
226  return Discard(this->emitSub(*T, BO));
227  case BO_Add:
228  return Discard(this->emitAdd(*T, BO));
229  case BO_Mul:
230  return Discard(this->emitMul(*T, BO));
231  case BO_Rem:
232  return Discard(this->emitRem(*T, BO));
233  case BO_Div:
234  return Discard(this->emitDiv(*T, BO));
235  case BO_Assign:
236  if (DiscardResult)
237  return this->emitStorePop(*T, BO);
238  return this->emitStore(*T, BO);
239  case BO_And:
240  return Discard(this->emitBitAnd(*T, BO));
241  case BO_Or:
242  return Discard(this->emitBitOr(*T, BO));
243  case BO_Shl:
244  return Discard(this->emitShl(*LT, *RT, BO));
245  case BO_Shr:
246  return Discard(this->emitShr(*LT, *RT, BO));
247  case BO_Xor:
248  return Discard(this->emitBitXor(*T, BO));
249  case BO_LAnd:
250  case BO_LOr:
251  default:
252  return this->bail(BO);
253  }
254 
255  llvm_unreachable("Unhandled binary op");
256 }
257 
258 /// Perform addition/subtraction of a pointer and an integer or
259 /// subtraction of two pointers.
260 template <class Emitter>
262  BinaryOperatorKind Op = E->getOpcode();
263  const Expr *LHS = E->getLHS();
264  const Expr *RHS = E->getRHS();
265 
266  if ((Op != BO_Add && Op != BO_Sub) ||
267  (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType()))
268  return false;
269 
270  Optional<PrimType> LT = classify(LHS);
271  Optional<PrimType> RT = classify(RHS);
272 
273  if (!LT || !RT)
274  return false;
275 
276  if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) {
277  if (Op != BO_Sub)
278  return false;
279 
280  assert(E->getType()->isIntegerType());
281  if (!visit(RHS) || !visit(LHS))
282  return false;
283 
284  return this->emitSubPtr(classifyPrim(E->getType()), E);
285  }
286 
287  PrimType OffsetType;
288  if (LHS->getType()->isIntegerType()) {
289  if (!visit(RHS) || !visit(LHS))
290  return false;
291  OffsetType = *LT;
292  } else if (RHS->getType()->isIntegerType()) {
293  if (!visit(LHS) || !visit(RHS))
294  return false;
295  OffsetType = *RT;
296  } else {
297  return false;
298  }
299 
300  if (Op == BO_Add)
301  return this->emitAddOffset(OffsetType, E);
302  else if (Op == BO_Sub)
303  return this->emitSubOffset(OffsetType, E);
304 
305  return this->bail(E);
306 }
307 
308 template <class Emitter>
310  if (Optional<PrimType> T = classify(E))
311  return this->emitZero(*T, E);
312 
313  return false;
314 }
315 
316 template <class Emitter>
318  const ArraySubscriptExpr *E) {
319  const Expr *Base = E->getBase();
320  const Expr *Index = E->getIdx();
321  PrimType IndexT = classifyPrim(Index->getType());
322 
323  // Take pointer of LHS, add offset from RHS, narrow result.
324  // What's left on the stack after this is a pointer.
325  if (!this->visit(Base))
326  return false;
327 
328  if (!this->visit(Index))
329  return false;
330 
331  if (!this->emitAddOffset(IndexT, E))
332  return false;
333 
334  if (!this->emitNarrowPtr(E))
335  return false;
336 
337  if (DiscardResult)
338  return this->emitPopPtr(E);
339 
340  return true;
341 }
342 
343 template <class Emitter>
345  for (const Expr *Init : E->inits()) {
346  if (!this->visit(Init))
347  return false;
348  }
349  return true;
350 }
351 
352 template <class Emitter>
354  const SubstNonTypeTemplateParmExpr *E) {
355  return this->visit(E->getReplacement());
356 }
357 
358 template <class Emitter>
360  // TODO: Check if the ConstantExpr already has a value set and if so,
361  // use that instead of evaluating it again.
362  return this->visit(E->getSubExpr());
363 }
364 
365 static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,
367  bool AlignOfReturnsPreferred =
368  ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
369 
370  // C++ [expr.alignof]p3:
371  // When alignof is applied to a reference type, the result is the
372  // alignment of the referenced type.
373  if (const auto *Ref = T->getAs<ReferenceType>())
374  T = Ref->getPointeeType();
375 
376  // __alignof is defined to return the preferred alignment.
377  // Before 8, clang returned the preferred alignment for alignof and
378  // _Alignof as well.
379  if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
380  return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T));
381 
382  return ASTCtx.getTypeAlignInChars(T);
383 }
384 
385 template <class Emitter>
387  const UnaryExprOrTypeTraitExpr *E) {
389  ASTContext &ASTCtx = Ctx.getASTContext();
390 
391  if (Kind == UETT_SizeOf) {
392  QualType ArgType = E->getTypeOfArgument();
393  CharUnits Size;
394  if (ArgType->isVoidType() || ArgType->isFunctionType())
395  Size = CharUnits::One();
396  else {
397  if (ArgType->isDependentType() || !ArgType->isConstantSizeType())
398  return false;
399 
400  Size = ASTCtx.getTypeSizeInChars(ArgType);
401  }
402 
403  return this->emitConst(Size.getQuantity(), E);
404  }
405 
406  if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) {
407  CharUnits Size;
408 
409  if (E->isArgumentType()) {
410  QualType ArgType = E->getTypeOfArgument();
411 
412  Size = AlignOfType(ArgType, ASTCtx, Kind);
413  } else {
414  // Argument is an expression, not a type.
415  const Expr *Arg = E->getArgumentExpr()->IgnoreParens();
416 
417  // The kinds of expressions that we have special-case logic here for
418  // should be kept up to date with the special checks for those
419  // expressions in Sema.
420 
421  // alignof decl is always accepted, even if it doesn't make sense: we
422  // default to 1 in those cases.
423  if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg))
424  Size = ASTCtx.getDeclAlign(DRE->getDecl(),
425  /*RefAsPointee*/ true);
426  else if (const auto *ME = dyn_cast<MemberExpr>(Arg))
427  Size = ASTCtx.getDeclAlign(ME->getMemberDecl(),
428  /*RefAsPointee*/ true);
429  else
430  Size = AlignOfType(Arg->getType(), ASTCtx, Kind);
431  }
432 
433  return this->emitConst(Size.getQuantity(), E);
434  }
435 
436  return false;
437 }
438 
439 template <class Emitter>
441  if (DiscardResult)
442  return true;
443 
444  // 'Base.Member'
445  const Expr *Base = E->getBase();
446  const ValueDecl *Member = E->getMemberDecl();
447 
448  if (!this->visit(Base))
449  return false;
450 
451  // Base above gives us a pointer on the stack.
452  // TODO: Implement non-FieldDecl members.
453  if (const auto *FD = dyn_cast<FieldDecl>(Member)) {
454  const RecordDecl *RD = FD->getParent();
455  const Record *R = getRecord(RD);
456  const Record::Field *F = R->getField(FD);
457  // Leave a pointer to the field on the stack.
458  if (F->Decl->getType()->isReferenceType())
459  return this->emitGetFieldPop(PT_Ptr, F->Offset, E);
460  return this->emitGetPtrField(F->Offset, E);
461  }
462 
463  return false;
464 }
465 
466 template <class Emitter>
468  const ArrayInitIndexExpr *E) {
469  // ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated
470  // stand-alone, e.g. via EvaluateAsInt().
471  if (!ArrayIndex)
472  return false;
473  return this->emitConst(*ArrayIndex, E);
474 }
475 
476 template <class Emitter>
478  return this->visit(E->getSourceExpr());
479 }
480 
481 template <class Emitter>
483  const AbstractConditionalOperator *E) {
484  const Expr *Condition = E->getCond();
485  const Expr *TrueExpr = E->getTrueExpr();
486  const Expr *FalseExpr = E->getFalseExpr();
487 
488  LabelTy LabelEnd = this->getLabel(); // Label after the operator.
489  LabelTy LabelFalse = this->getLabel(); // Label for the false expr.
490 
491  if (!this->visit(Condition))
492  return false;
493  if (!this->jumpFalse(LabelFalse))
494  return false;
495 
496  if (!this->visit(TrueExpr))
497  return false;
498  if (!this->jump(LabelEnd))
499  return false;
500 
501  this->emitLabel(LabelFalse);
502 
503  if (!this->visit(FalseExpr))
504  return false;
505 
506  this->fallthrough(LabelEnd);
507  this->emitLabel(LabelEnd);
508 
509  return true;
510 }
511 
512 template <class Emitter>
514  unsigned StringIndex = P.createGlobalString(E);
515  return this->emitGetPtrGlobal(StringIndex, E);
516 }
517 
518 template <class Emitter>
520  const CharacterLiteral *E) {
521  return this->emitConst(E->getValue(), E);
522 }
523 
524 template <class Emitter>
526  const CompoundAssignOperator *E) {
527  const Expr *LHS = E->getLHS();
528  const Expr *RHS = E->getRHS();
529  Optional<PrimType> LT = classify(E->getLHS()->getType());
530  Optional<PrimType> RT = classify(E->getRHS()->getType());
531 
532  if (!LT || !RT)
533  return false;
534 
535  assert(!E->getType()->isPointerType() &&
536  "Support pointer arithmethic in compound assignment operators");
537 
538  // Get LHS pointer, load its value and get RHS value.
539  if (!visit(LHS))
540  return false;
541  if (!this->emitLoad(*LT, E))
542  return false;
543  if (!visit(RHS))
544  return false;
545 
546  // Perform operation.
547  switch (E->getOpcode()) {
548  case BO_AddAssign:
549  if (!this->emitAdd(*LT, E))
550  return false;
551  break;
552  case BO_SubAssign:
553  if (!this->emitSub(*LT, E))
554  return false;
555  break;
556 
557  case BO_MulAssign:
558  case BO_DivAssign:
559  case BO_RemAssign:
560  case BO_ShlAssign:
561  if (!this->emitShl(*LT, *RT, E))
562  return false;
563  break;
564  case BO_ShrAssign:
565  if (!this->emitShr(*LT, *RT, E))
566  return false;
567  break;
568  case BO_AndAssign:
569  case BO_XorAssign:
570  case BO_OrAssign:
571  default:
572  llvm_unreachable("Unimplemented compound assign operator");
573  }
574 
575  // And store the result in LHS.
576  if (DiscardResult)
577  return this->emitStorePop(*LT, E);
578  return this->emitStore(*LT, E);
579 }
580 
581 template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
582  OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true);
583  return this->Visit(E);
584 }
585 
586 template <class Emitter>
588  OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false);
589  return this->Visit(E);
590 }
591 
592 template <class Emitter>
594  if (Optional<PrimType> T = classify(E->getType())) {
595  return visit(E);
596  } else {
597  return this->bail(E);
598  }
599 }
600 
601 template <class Emitter>
603  switch (T) {
604  case PT_Bool:
605  return this->emitZeroBool(E);
606  case PT_Sint8:
607  return this->emitZeroSint8(E);
608  case PT_Uint8:
609  return this->emitZeroUint8(E);
610  case PT_Sint16:
611  return this->emitZeroSint16(E);
612  case PT_Uint16:
613  return this->emitZeroUint16(E);
614  case PT_Sint32:
615  return this->emitZeroSint32(E);
616  case PT_Uint32:
617  return this->emitZeroUint32(E);
618  case PT_Sint64:
619  return this->emitZeroSint64(E);
620  case PT_Uint64:
621  return this->emitZeroUint64(E);
622  case PT_Ptr:
623  return this->emitNullPtr(E);
624  }
625  llvm_unreachable("unknown primitive type");
626 }
627 
628 template <class Emitter>
630  const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
631  llvm::function_ref<bool(PrimType)> Indirect) {
632  if (Optional<PrimType> T = classify(LV->getType())) {
633  if (!LV->refersToBitField()) {
634  // Only primitive, non bit-field types can be dereferenced directly.
635  if (auto *DE = dyn_cast<DeclRefExpr>(LV)) {
636  if (!DE->getDecl()->getType()->isReferenceType()) {
637  if (auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl()))
638  return dereferenceParam(LV, *T, PD, AK, Direct, Indirect);
639  if (auto *VD = dyn_cast<VarDecl>(DE->getDecl()))
640  return dereferenceVar(LV, *T, VD, AK, Direct, Indirect);
641  }
642  }
643  }
644 
645  if (!visit(LV))
646  return false;
647  return Indirect(*T);
648  }
649 
650  return false;
651 }
652 
653 template <class Emitter>
655  const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK,
656  llvm::function_ref<bool(PrimType)> Direct,
657  llvm::function_ref<bool(PrimType)> Indirect) {
658  auto It = this->Params.find(PD);
659  if (It != this->Params.end()) {
660  unsigned Idx = It->second;
661  switch (AK) {
662  case DerefKind::Read:
663  return DiscardResult ? true : this->emitGetParam(T, Idx, LV);
664 
665  case DerefKind::Write:
666  if (!Direct(T))
667  return false;
668  if (!this->emitSetParam(T, Idx, LV))
669  return false;
670  return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
671 
672  case DerefKind::ReadWrite:
673  if (!this->emitGetParam(T, Idx, LV))
674  return false;
675  if (!Direct(T))
676  return false;
677  if (!this->emitSetParam(T, Idx, LV))
678  return false;
679  return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
680  }
681  return true;
682  }
683 
684  // If the param is a pointer, we can dereference a dummy value.
685  if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) {
686  if (auto Idx = P.getOrCreateDummy(PD))
687  return this->emitGetPtrGlobal(*Idx, PD);
688  return false;
689  }
690 
691  // Value cannot be produced - try to emit pointer and do stuff with it.
692  return visit(LV) && Indirect(T);
693 }
694 
695 template <class Emitter>
697  const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK,
698  llvm::function_ref<bool(PrimType)> Direct,
699  llvm::function_ref<bool(PrimType)> Indirect) {
700  auto It = Locals.find(VD);
701  if (It != Locals.end()) {
702  const auto &L = It->second;
703  switch (AK) {
704  case DerefKind::Read:
705  if (!this->emitGetLocal(T, L.Offset, LV))
706  return false;
707  return DiscardResult ? this->emitPop(T, LV) : true;
708 
709  case DerefKind::Write:
710  if (!Direct(T))
711  return false;
712  if (!this->emitSetLocal(T, L.Offset, LV))
713  return false;
714  return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
715 
716  case DerefKind::ReadWrite:
717  if (!this->emitGetLocal(T, L.Offset, LV))
718  return false;
719  if (!Direct(T))
720  return false;
721  if (!this->emitSetLocal(T, L.Offset, LV))
722  return false;
723  return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
724  }
725  } else if (auto Idx = P.getGlobal(VD)) {
726  switch (AK) {
727  case DerefKind::Read:
728  if (!this->emitGetGlobal(T, *Idx, LV))
729  return false;
730  return DiscardResult ? this->emitPop(T, LV) : true;
731 
732  case DerefKind::Write:
733  if (!Direct(T))
734  return false;
735  if (!this->emitSetGlobal(T, *Idx, LV))
736  return false;
737  return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
738 
739  case DerefKind::ReadWrite:
740  if (!this->emitGetGlobal(T, *Idx, LV))
741  return false;
742  if (!Direct(T))
743  return false;
744  if (!this->emitSetGlobal(T, *Idx, LV))
745  return false;
746  return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
747  }
748  }
749 
750  // If the declaration is a constant value, emit it here even
751  // though the declaration was not evaluated in the current scope.
752  // The access mode can only be read in this case.
753  if (!DiscardResult && AK == DerefKind::Read) {
754  if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) {
755  QualType VT = VD->getType();
756  if (VT.isConstQualified() && VT->isFundamentalType())
757  return this->visit(VD->getInit());
758  }
759  }
760 
761  // Value cannot be produced - try to emit pointer.
762  return visit(LV) && Indirect(T);
763 }
764 
765 template <class Emitter>
766 template <typename T>
768  switch (classifyPrim(E->getType())) {
769  case PT_Sint8:
770  return this->emitConstSint8(Value, E);
771  case PT_Uint8:
772  return this->emitConstUint8(Value, E);
773  case PT_Sint16:
774  return this->emitConstSint16(Value, E);
775  case PT_Uint16:
776  return this->emitConstUint16(Value, E);
777  case PT_Sint32:
778  return this->emitConstSint32(Value, E);
779  case PT_Uint32:
780  return this->emitConstUint32(Value, E);
781  case PT_Sint64:
782  return this->emitConstSint64(Value, E);
783  case PT_Uint64:
784  return this->emitConstUint64(Value, E);
785  case PT_Bool:
786  return this->emitConstBool(Value, E);
787  case PT_Ptr:
788  llvm_unreachable("Invalid integral type");
789  break;
790  }
791  llvm_unreachable("unknown primitive type");
792 }
793 
794 template <class Emitter>
795 bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, const Expr *E) {
796  if (Value.isSigned())
797  return this->emitConst(Value.getSExtValue(), E);
798  return this->emitConst(Value.getZExtValue(), E);
799 }
800 
801 template <class Emitter>
803  PrimType Ty,
804  bool IsConst,
805  bool IsExtended) {
806  Descriptor *D = P.createDescriptor(Src, Ty, IsConst, Src.is<const Expr *>());
807  Scope::Local Local = this->createLocal(D);
808  if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>()))
809  Locals.insert({VD, Local});
810  VarScope->add(Local, IsExtended);
811  return Local.Offset;
812 }
813 
814 template <class Emitter>
817  QualType Ty;
818 
819  const ValueDecl *Key = nullptr;
820  const Expr *Init = nullptr;
821  bool IsTemporary = false;
822  if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
823  Key = VD;
824  Ty = VD->getType();
825 
826  if (const auto *VarD = dyn_cast<VarDecl>(VD))
827  Init = VarD->getInit();
828  }
829  if (auto *E = Src.dyn_cast<const Expr *>()) {
830  IsTemporary = true;
831  Ty = E->getType();
832  }
833 
834  Descriptor *D = P.createDescriptor(
835  Src, Ty.getTypePtr(), Ty.isConstQualified(), IsTemporary, false, Init);
836  if (!D)
837  return {};
838 
839  Scope::Local Local = this->createLocal(D);
840  if (Key)
841  Locals.insert({Key, Local});
842  VarScope->add(Local, IsExtended);
843  return Local.Offset;
844 }
845 
846 // NB: When calling this function, we have a pointer to the
847 // array-to-initialize on the stack.
848 template <class Emitter>
850  assert(Initializer->getType()->isArrayType());
851 
852  // TODO: Fillers?
853  if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) {
854  unsigned ElementIndex = 0;
855  for (const Expr *Init : InitList->inits()) {
856  if (Optional<PrimType> T = classify(Init->getType())) {
857  // Visit the primitive element like normal.
858  if (!this->emitDupPtr(Init))
859  return false;
860  if (!this->visit(Init))
861  return false;
862  if (!this->emitInitElem(*T, ElementIndex, Init))
863  return false;
864  } else {
865  // Advance the pointer currently on the stack to the given
866  // dimension and narrow().
867  if (!this->emitDupPtr(Init))
868  return false;
869  if (!this->emitConstUint32(ElementIndex, Init))
870  return false;
871  if (!this->emitAddOffsetUint32(Init))
872  return false;
873  if (!this->emitNarrowPtr(Init))
874  return false;
875 
876  if (!visitInitializer(Init))
877  return false;
878  }
879  if (!this->emitPopPtr(Init))
880  return false;
881 
882  ++ElementIndex;
883  }
884  return true;
885  } else if (const auto *DIE = dyn_cast<CXXDefaultInitExpr>(Initializer)) {
886  return this->visitInitializer(DIE->getExpr());
887  } else if (const auto *AILE = dyn_cast<ArrayInitLoopExpr>(Initializer)) {
888  // TODO: This compiles to quite a lot of bytecode if the array is larger.
889  // Investigate compiling this to a loop, or at least try to use
890  // the AILE's Common expr.
891  const Expr *SubExpr = AILE->getSubExpr();
892  size_t Size = AILE->getArraySize().getZExtValue();
893  Optional<PrimType> ElemT = classify(SubExpr->getType());
894 
895  // So, every iteration, we execute an assignment here
896  // where the LHS is on the stack (the target array)
897  // and the RHS is our SubExpr.
898  for (size_t I = 0; I != Size; ++I) {
899  ArrayIndexScope<Emitter> IndexScope(this, I);
900 
901  if (!this->emitDupPtr(SubExpr)) // LHS
902  return false;
903 
904  if (ElemT) {
905  if (!this->visit(SubExpr))
906  return false;
907  if (!this->emitInitElem(*ElemT, I, Initializer))
908  return false;
909  } else {
910  // Narrow to our array element and recurse into visitInitializer()
911  if (!this->emitConstUint64(I, SubExpr))
912  return false;
913 
914  if (!this->emitAddOffsetUint64(SubExpr))
915  return false;
916 
917  if (!this->emitNarrowPtr(SubExpr))
918  return false;
919 
920  if (!visitInitializer(SubExpr))
921  return false;
922  }
923 
924  if (!this->emitPopPtr(Initializer))
925  return false;
926  }
927  return true;
928  } else if (const auto *IVIE = dyn_cast<ImplicitValueInitExpr>(Initializer)) {
929  const ArrayType *AT = IVIE->getType()->getAsArrayTypeUnsafe();
930  assert(AT);
931  const auto *CAT = cast<ConstantArrayType>(AT);
932  size_t NumElems = CAT->getSize().getZExtValue();
933 
934  if (Optional<PrimType> ElemT = classify(CAT->getElementType())) {
935  // TODO(perf): For int and bool types, we can probably just skip this
936  // since we memset our Block*s to 0 and so we have the desired value
937  // without this.
938  for (size_t I = 0; I != NumElems; ++I) {
939  if (!this->emitZero(*ElemT, Initializer))
940  return false;
941  if (!this->emitInitElem(*ElemT, I, Initializer))
942  return false;
943  }
944  } else {
945  assert(false && "default initializer for non-primitive type");
946  }
947 
948  return true;
949  } else if (const auto *Ctor = dyn_cast<CXXConstructExpr>(Initializer)) {
950  const ConstantArrayType *CAT =
951  Ctx.getASTContext().getAsConstantArrayType(Ctor->getType());
952  assert(CAT);
953  size_t NumElems = CAT->getSize().getZExtValue();
954  const Function *Func = getFunction(Ctor->getConstructor());
955  if (!Func || !Func->isConstexpr())
956  return false;
957 
958  // FIXME(perf): We're calling the constructor once per array element here,
959  // in the old intepreter we had a special-case for trivial constructors.
960  for (size_t I = 0; I != NumElems; ++I) {
961  if (!this->emitDupPtr(Initializer))
962  return false;
963  if (!this->emitConstUint64(I, Initializer))
964  return false;
965  if (!this->emitAddOffsetUint64(Initializer))
966  return false;
967  if (!this->emitNarrowPtr(Initializer))
968  return false;
969 
970  // Constructor arguments.
971  for (const auto *Arg : Ctor->arguments()) {
972  if (!this->visit(Arg))
973  return false;
974  }
975 
976  if (!this->emitCall(Func, Initializer))
977  return false;
978  }
979  return true;
980  }
981 
982  assert(false && "Unknown expression for array initialization");
983  return false;
984 }
985 
986 template <class Emitter>
988  Initializer = Initializer->IgnoreParenImpCasts();
989  assert(Initializer->getType()->isRecordType());
990 
991  if (const auto CtorExpr = dyn_cast<CXXConstructExpr>(Initializer)) {
992  const Function *Func = getFunction(CtorExpr->getConstructor());
993 
994  if (!Func || !Func->isConstexpr())
995  return false;
996 
997  // The This pointer is already on the stack because this is an initializer,
998  // but we need to dup() so the call() below has its own copy.
999  if (!this->emitDupPtr(Initializer))
1000  return false;
1001 
1002  // Constructor arguments.
1003  for (const auto *Arg : CtorExpr->arguments()) {
1004  if (!this->visit(Arg))
1005  return false;
1006  }
1007 
1008  return this->emitCall(Func, Initializer);
1009  } else if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) {
1010  const Record *R = getRecord(InitList->getType());
1011 
1012  unsigned InitIndex = 0;
1013  for (const Expr *Init : InitList->inits()) {
1014  const Record::Field *FieldToInit = R->getField(InitIndex);
1015 
1016  if (!this->emitDupPtr(Initializer))
1017  return false;
1018 
1019  if (Optional<PrimType> T = classify(Init)) {
1020  if (!this->visit(Init))
1021  return false;
1022 
1023  if (!this->emitInitField(*T, FieldToInit->Offset, Initializer))
1024  return false;
1025 
1026  if (!this->emitPopPtr(Initializer))
1027  return false;
1028  } else {
1029  // Non-primitive case. Get a pointer to the field-to-initialize
1030  // on the stack and recurse into visitInitializer().
1031  if (!this->emitGetPtrField(FieldToInit->Offset, Init))
1032  return false;
1033 
1034  if (!this->visitInitializer(Init))
1035  return false;
1036 
1037  if (!this->emitPopPtr(Initializer))
1038  return false;
1039  }
1040  ++InitIndex;
1041  }
1042 
1043  return true;
1044  } else if (const CallExpr *CE = dyn_cast<CallExpr>(Initializer)) {
1045  const Decl *Callee = CE->getCalleeDecl();
1046  const Function *Func = getFunction(dyn_cast<FunctionDecl>(Callee));
1047 
1048  if (!Func)
1049  return false;
1050 
1051  if (Func->hasRVO()) {
1052  // RVO functions expect a pointer to initialize on the stack.
1053  // Dup our existing pointer so it has its own copy to use.
1054  if (!this->emitDupPtr(Initializer))
1055  return false;
1056 
1057  return this->visit(CE);
1058  }
1059  } else if (const auto *DIE = dyn_cast<CXXDefaultInitExpr>(Initializer)) {
1060  return this->visitInitializer(DIE->getExpr());
1061  }
1062 
1063  return false;
1064 }
1065 
1066 template <class Emitter>
1068  QualType InitializerType = Initializer->getType();
1069 
1070  if (InitializerType->isArrayType())
1071  return visitArrayInitializer(Initializer);
1072 
1073  if (InitializerType->isRecordType())
1074  return visitRecordInitializer(Initializer);
1075 
1076  // Otherwise, visit the expression like normal.
1077  return this->visit(Initializer);
1078 }
1079 
1080 template <class Emitter>
1082  if (const PointerType *PT = dyn_cast<PointerType>(Ty))
1083  return PT->getPointeeType()->getAs<RecordType>();
1084  else
1085  return Ty->getAs<RecordType>();
1086 }
1087 
1088 template <class Emitter>
1090  if (auto *RecordTy = getRecordTy(Ty)) {
1091  return getRecord(RecordTy->getDecl());
1092  }
1093  return nullptr;
1094 }
1095 
1096 template <class Emitter>
1098  return P.getOrCreateRecord(RD);
1099 }
1100 
1101 template <class Emitter>
1103  assert(FD);
1104  const Function *Func = P.getFunction(FD);
1105  bool IsBeingCompiled = Func && !Func->isFullyCompiled();
1106  bool WasNotDefined = Func && !Func->hasBody();
1107 
1108  if (IsBeingCompiled)
1109  return Func;
1110 
1111  if (!Func || WasNotDefined) {
1112  if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(Ctx, P).compileFunc(FD))
1113  Func = *R;
1114  else {
1115  llvm::consumeError(R.takeError());
1116  return nullptr;
1117  }
1118  }
1119 
1120  return Func;
1121 }
1122 
1123 template <class Emitter>
1125  ExprScope<Emitter> RootScope(this);
1126  if (!visit(Exp))
1127  return false;
1128 
1129  if (Optional<PrimType> T = classify(Exp))
1130  return this->emitRet(*T, Exp);
1131  else
1132  return this->emitRetValue(Exp);
1133 }
1134 
1135 template <class Emitter>
1137  const Expr *Init = VD->getInit();
1138 
1139  if (Optional<unsigned> I = P.createGlobal(VD, Init)) {
1140  if (Optional<PrimType> T = classify(VD->getType())) {
1141  {
1142  // Primitive declarations - compute the value and set it.
1143  DeclScope<Emitter> LocalScope(this, VD);
1144  if (!visit(Init))
1145  return false;
1146  }
1147 
1148  // If the declaration is global, save the value for later use.
1149  if (!this->emitDup(*T, VD))
1150  return false;
1151  if (!this->emitInitGlobal(*T, *I, VD))
1152  return false;
1153  return this->emitRet(*T, VD);
1154  } else {
1155  {
1156  // Composite declarations - allocate storage and initialize it.
1157  DeclScope<Emitter> LocalScope(this, VD);
1158  if (!visitGlobalInitializer(Init, *I))
1159  return false;
1160  }
1161 
1162  // Return a pointer to the global.
1163  if (!this->emitGetPtrGlobal(*I, VD))
1164  return false;
1165  return this->emitRetValue(VD);
1166  }
1167  }
1168 
1169  return this->bail(VD);
1170 }
1171 
1172 template <class Emitter>
1174  assert(!E->getBuiltinCallee() && "Builtin functions aren't supported yet");
1175 
1176  const Decl *Callee = E->getCalleeDecl();
1177  if (const auto *FuncDecl = dyn_cast_or_null<FunctionDecl>(Callee)) {
1178  const Function *Func = getFunction(FuncDecl);
1179  if (!Func)
1180  return false;
1181  // If the function is being compiled right now, this is a recursive call.
1182  // In that case, the function can't be valid yet, even though it will be
1183  // later.
1184  // If the function is already fully compiled but not constexpr, it was
1185  // found to be faulty earlier on, so bail out.
1186  if (Func->isFullyCompiled() && !Func->isConstexpr())
1187  return false;
1188 
1189  QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
1190  Optional<PrimType> T = classify(ReturnType);
1191 
1192  if (Func->hasRVO() && DiscardResult) {
1193  // If we need to discard the return value but the function returns its
1194  // value via an RVO pointer, we need to create one such pointer just
1195  // for this call.
1196  if (Optional<unsigned> LocalIndex = allocateLocal(E)) {
1197  if (!this->emitGetPtrLocal(*LocalIndex, E))
1198  return false;
1199  }
1200  }
1201 
1202  // Put arguments on the stack.
1203  for (const auto *Arg : E->arguments()) {
1204  if (!this->visit(Arg))
1205  return false;
1206  }
1207 
1208  // In any case call the function. The return value will end up on the stack and
1209  // if the function has RVO, we already have the pointer on the stack to write
1210  // the result into.
1211  if (!this->emitCall(Func, E))
1212  return false;
1213 
1214  if (DiscardResult && !ReturnType->isVoidType() && T)
1215  return this->emitPop(*T, E);
1216 
1217  return true;
1218  } else {
1219  assert(false && "We don't support non-FunctionDecl callees right now.");
1220  }
1221 
1222  return false;
1223 }
1224 
1225 template <class Emitter>
1227  const CXXMemberCallExpr *E) {
1228  // Get a This pointer on the stack.
1229  if (!this->visit(E->getImplicitObjectArgument()))
1230  return false;
1231 
1232  return VisitCallExpr(E);
1233 }
1234 
1235 template <class Emitter>
1237  const CXXDefaultInitExpr *E) {
1238  return this->visit(E->getExpr());
1239 }
1240 
1241 template <class Emitter>
1243  const CXXDefaultArgExpr *E) {
1244  return this->visit(E->getExpr());
1245 }
1246 
1247 template <class Emitter>
1249  const CXXBoolLiteralExpr *E) {
1250  if (DiscardResult)
1251  return true;
1252 
1253  return this->emitConstBool(E->getValue(), E);
1254 }
1255 
1256 template <class Emitter>
1258  const CXXNullPtrLiteralExpr *E) {
1259  if (DiscardResult)
1260  return true;
1261 
1262  return this->emitNullPtr(E);
1263 }
1264 
1265 template <class Emitter>
1267  if (DiscardResult)
1268  return true;
1269  return this->emitThis(E);
1270 }
1271 
1272 template <class Emitter>
1274  const Expr *SubExpr = E->getSubExpr();
1275  Optional<PrimType> T = classify(SubExpr->getType());
1276 
1277  // TODO: Support pointers for inc/dec operators.
1278  switch (E->getOpcode()) {
1279  case UO_PostInc: { // x++
1280  if (!this->visit(SubExpr))
1281  return false;
1282 
1283  return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E);
1284  }
1285  case UO_PostDec: { // x--
1286  if (!this->visit(SubExpr))
1287  return false;
1288 
1289  return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E);
1290  }
1291  case UO_PreInc: { // ++x
1292  if (!this->visit(SubExpr))
1293  return false;
1294 
1295  // Post-inc and pre-inc are the same if the value is to be discarded.
1296  if (DiscardResult)
1297  return this->emitIncPop(*T, E);
1298 
1299  this->emitLoad(*T, E);
1300  this->emitConst(1, E);
1301  this->emitAdd(*T, E);
1302  return this->emitStore(*T, E);
1303  }
1304  case UO_PreDec: { // --x
1305  if (!this->visit(SubExpr))
1306  return false;
1307 
1308  // Post-dec and pre-dec are the same if the value is to be discarded.
1309  if (DiscardResult)
1310  return this->emitDecPop(*T, E);
1311 
1312  this->emitLoad(*T, E);
1313  this->emitConst(1, E);
1314  this->emitSub(*T, E);
1315  return this->emitStore(*T, E);
1316  }
1317  case UO_LNot: // !x
1318  if (!this->visit(SubExpr))
1319  return false;
1320  // The Inv doesn't change anything, so skip it if we don't need the result.
1321  return DiscardResult ? this->emitPop(*T, E) : this->emitInvBool(E);
1322  case UO_Minus: // -x
1323  if (!this->visit(SubExpr))
1324  return false;
1325  return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
1326  case UO_Plus: // +x
1327  if (!this->visit(SubExpr)) // noop
1328  return false;
1329  return DiscardResult ? this->emitPop(*T, E) : true;
1330  case UO_AddrOf: // &x
1331  // We should already have a pointer when we get here.
1332  if (!this->visit(SubExpr))
1333  return false;
1334  return DiscardResult ? this->emitPop(*T, E) : true;
1335  case UO_Deref: // *x
1336  return dereference(
1337  SubExpr, DerefKind::Read,
1338  [](PrimType) {
1339  llvm_unreachable("Dereferencing requires a pointer");
1340  return false;
1341  },
1342  [this, E](PrimType T) {
1343  return DiscardResult ? this->emitPop(T, E) : true;
1344  });
1345  case UO_Not: // ~x
1346  if (!this->visit(SubExpr))
1347  return false;
1348  return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
1349  case UO_Real: // __real x
1350  case UO_Imag: // __imag x
1351  case UO_Extension:
1352  case UO_Coawait:
1353  assert(false && "Unhandled opcode");
1354  }
1355 
1356  return false;
1357 }
1358 
1359 template <class Emitter>
1361  const auto *Decl = E->getDecl();
1362  // References are implemented via pointers, so when we see a DeclRefExpr
1363  // pointing to a reference, we need to get its value directly (i.e. the
1364  // pointer to the actual value) instead of a pointer to the pointer to the
1365  // value.
1366  bool IsReference = Decl->getType()->isReferenceType();
1367 
1368  if (auto It = Locals.find(Decl); It != Locals.end()) {
1369  const unsigned Offset = It->second.Offset;
1370 
1371  if (IsReference)
1372  return this->emitGetLocal(PT_Ptr, Offset, E);
1373  return this->emitGetPtrLocal(Offset, E);
1374  } else if (auto GlobalIndex = P.getGlobal(Decl)) {
1375  if (IsReference)
1376  return this->emitGetGlobal(PT_Ptr, *GlobalIndex, E);
1377 
1378  return this->emitGetPtrGlobal(*GlobalIndex, E);
1379  } else if (const auto *PVD = dyn_cast<ParmVarDecl>(Decl)) {
1380  if (auto It = this->Params.find(PVD); It != this->Params.end()) {
1381  if (IsReference)
1382  return this->emitGetParam(PT_Ptr, It->second, E);
1383  return this->emitGetPtrParam(It->second, E);
1384  }
1385  } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(Decl)) {
1386  return this->emitConst(ECD->getInitVal(), E);
1387  }
1388 
1389  return false;
1390 }
1391 
1392 template <class Emitter>
1394  for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())
1395  C->emitDestruction();
1396 }
1397 
1398 namespace clang {
1399 namespace interp {
1400 
1401 template class ByteCodeExprGen<ByteCodeEmitter>;
1402 template class ByteCodeExprGen<EvalEmitter>;
1403 
1404 } // namespace interp
1405 } // namespace clang
clang::ArrayInitIndexExpr
Represents the index of the current element of an array being initialized by an ArrayInitLoopExpr.
Definition: Expr.h:5479
clang::ASTContext::getTypeSizeInChars
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
Definition: ASTContext.cpp:2515
clang::SubstNonTypeTemplateParmExpr
Represents a reference to a non-type template parameter that has been substituted with a template arg...
Definition: ExprCXX.h:4269
clang::interp::Record::Base::Offset
unsigned Offset
Definition: Record.h:36
clang::Type::isRecordType
bool isRecordType() const
Definition: Type.h:6973
APSInt
llvm::APSInt APSInt
Definition: ByteCodeExprGen.cpp:22
clang::Type::getAsArrayTypeUnsafe
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:7439
clang::interp::ByteCodeExprGen::visitBool
bool visitBool(const Expr *E)
Visits an expression and converts it to a boolean.
Definition: ByteCodeExprGen.cpp:593
clang::CXXBoolLiteralExpr
A boolean literal, per ([C++ lex.bool] Boolean literals).
Definition: ExprCXX.h:721
clang::interp::ByteCodeExprGen::discard
bool discard(const Expr *E)
Evaluates an expression for side effects and discards the result.
Definition: ByteCodeExprGen.cpp:581
clang::interp::OptionScope
Scope used to handle initialization methods.
Definition: ByteCodeExprGen.cpp:44
clang::interp::ByteCodeExprGen::VisitPointerArithBinOp
bool VisitPointerArithBinOp(const BinaryOperator *E)
Perform addition/subtraction of a pointer and an integer or subtraction of two pointers.
Definition: ByteCodeExprGen.cpp:261
clang::CXXDefaultArgExpr::getExpr
const Expr * getExpr() const
Definition: ExprCXX.h:1287
clang::Type::isFundamentalType
bool isFundamentalType() const
Tests whether the type is categorized as a fundamental type.
Definition: Type.h:6846
clang::interp::OptionScope::InitFnRef
typename ByteCodeExprGen< Emitter >::InitFnRef InitFnRef
Definition: ByteCodeExprGen.cpp:46
clang::QualType::isConstQualified
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:6694
clang::ConstantArrayType
Represents the canonical version of C arrays with a specified constant size.
Definition: Type.h:3058
clang::ConstantArrayType::getSize
const llvm::APInt & getSize() const
Definition: Type.h:3081
clang::interp::ByteCodeExprGen::VisitImplicitValueInitExpr
bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E)
Definition: ByteCodeExprGen.cpp:309
clang::AbstractConditionalOperator
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Definition: Expr.h:4112
clang::interp::ExprScope
Expression scope which tracks potentially lifetime extended temporaries which are hoisted to the pare...
Definition: ByteCodeExprGen.h:359
clang::CharacterLiteral::getValue
unsigned getValue() const
Definition: Expr.h:1627
clang::interp::ByteCodeExprGen::VisitBinaryOperator
bool VisitBinaryOperator(const BinaryOperator *E)
Definition: ByteCodeExprGen.cpp:173
clang::interp::Record::Base
Describes a base class.
Definition: Record.h:34
clang::interp::ByteCodeExprGen::VisitStringLiteral
bool VisitStringLiteral(const StringLiteral *E)
Definition: ByteCodeExprGen.cpp:513
clang::CastExpr::getSubExpr
Expr * getSubExpr()
Definition: Expr.h:3530
clang::interp::ByteCodeExprGen::VisitCXXBoolLiteralExpr
bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E)
Definition: ByteCodeExprGen.cpp:1248
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:737
clang::interp::ByteCodeExprGen::VisitDeclRefExpr
bool VisitDeclRefExpr(const DeclRefExpr *E)
Definition: ByteCodeExprGen.cpp:1360
clang::DynamicInitKind::Initializer
@ Initializer
clang::interp::ByteCodeExprGen::VisitCXXThisExpr
bool VisitCXXThisExpr(const CXXThisExpr *E)
Definition: ByteCodeExprGen.cpp:1266
clang::interp::ByteCodeStmtGen
Compilation context for statements.
Definition: ByteCodeStmtGen.h:36
clang::AbstractConditionalOperator::getTrueExpr
Expr * getTrueExpr() const
Definition: Expr.h:4296
clang::ArraySubscriptExpr::getIdx
Expr * getIdx()
Definition: Expr.h:2694
clang::interp::Program::DeclScope
Context to manage declaration lifetimes.
Definition: Program.h:130
clang::interp::ByteCodeExprGen::emitCleanup
void emitCleanup()
Emits scope cleanup instructions.
Definition: ByteCodeExprGen.cpp:1393
Write
@ Write
Definition: CGBuiltin.cpp:7596
clang::ParmVarDecl
Represents a parameter to a function.
Definition: Decl.h:1712
clang::interp::ByteCodeExprGen
Compilation context for expressions.
Definition: ByteCodeExprGen.h:41
clang::interp::DeclScope::addExtended
void addExtended(const Scope::Local &Local) override
Definition: ByteCodeExprGen.cpp:35
clang::interp::Record::getField
const Field * getField(const FieldDecl *FD) const
Returns a field.
Definition: Record.cpp:30
clang::interp::OptionScope::~OptionScope
~OptionScope()
Definition: ByteCodeExprGen.cpp:73
clang::interp::Record::Field
Describes a record field.
Definition: Record.h:27
clang::interp::PT_Uint16
@ PT_Uint16
Definition: PrimType.h:32
clang::interp::ByteCodeExprGen::VisitCXXMemberCallExpr
bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *E)
Definition: ByteCodeExprGen.cpp:1226
clang::InitListExpr
Describes an C or C++ initializer list.
Definition: Expr.h:4796
clang::interp::Scope
Describes a scope block.
Definition: Function.h:32
llvm::Optional
Definition: LLVM.h:40
clang::UnaryOperator
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2172
clang::Type::isVoidType
bool isVoidType() const
Definition: Type.h:7180
clang::interp::Record::Field::Offset
unsigned Offset
Definition: Record.h:29
clang::interp::Function::isConstexpr
bool isConstexpr() const
Checks if the function is valid to call in constexpr.
Definition: Function.h:125
llvm::Expected
Definition: LLVM.h:41
clang::CallExpr::getCalleeDecl
Decl * getCalleeDecl()
Definition: Expr.h:2974
clang::interp::ByteCodeExprGen::InitFnRef
std::function< bool()> InitFnRef
Definition: ByteCodeExprGen.h:49
clang::BinaryOperator::getOpcode
Opcode getOpcode() const
Definition: Expr.h:3856
clang::UnaryExprOrTypeTraitExpr::getArgumentExpr
Expr * getArgumentExpr()
Definition: Expr.h:2608
clang::interp::VariableScope
Scope chain managing the variable lifetimes.
Definition: ByteCodeExprGen.h:34
clang::interp::ByteCodeExprGen::VisitOpaqueValueExpr
bool VisitOpaqueValueExpr(const OpaqueValueExpr *E)
Definition: ByteCodeExprGen.cpp:477
clang::interp::OptionScope::OptionScope
OptionScope(ByteCodeExprGen< Emitter > *Ctx, bool NewDiscardResult)
Root constructor, compiling or discarding primitives.
Definition: ByteCodeExprGen.cpp:50
clang::interp::ByteCodeExprGen::VisitMemberExpr
bool VisitMemberExpr(const MemberExpr *E)
Definition: ByteCodeExprGen.cpp:440
clang::OpaqueValueExpr
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition: Expr.h:1144
clang::interp::Function::hasRVO
bool hasRVO() const
Checks if the first argument is a RVO pointer.
Definition: Function.h:102
clang::interp::PT_Sint16
@ PT_Sint16
Definition: PrimType.h:31
Offset
unsigned Offset
Definition: Format.cpp:2717
ByteCodeStmtGen.h
clang::interp::LT
bool LT(InterpState &S, CodePtr OpPC)
Definition: Interp.h:497
clang::interp::Scope::Local
Information about a local's storage.
Definition: Function.h:35
clang::ASTContext::getTypeAlignInChars
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
Definition: ASTContext.cpp:2524
APSInt
llvm::APSInt APSInt
Definition: ByteCodeEmitter.cpp:19
clang::interp::ByteCodeExprGen::VisitSubstNonTypeTemplateParmExpr
bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E)
Definition: ByteCodeExprGen.cpp:353
clang::CXXMemberCallExpr::getImplicitObjectArgument
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Definition: ExprCXX.cpp:650
clang::interp::DeclScope::DeclScope
DeclScope(ByteCodeExprGen< Emitter > *Ctx, const VarDecl *VD)
Definition: ByteCodeExprGen.cpp:32
clang::Type::isReferenceType
bool isReferenceType() const
Definition: Type.h:6895
clang::VarDecl::hasInit
bool hasInit() const
Definition: Decl.cpp:2324
clang::IntegerLiteral
Definition: Expr.h:1503
clang::CallExpr::getCallReturnType
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition: Expr.cpp:1575
clang::UnaryExprOrTypeTraitExpr
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Definition: Expr.h:2558
clang::interp::ByteCodeExprGen::allocateLocal
llvm::Optional< unsigned > allocateLocal(DeclTy &&Decl, bool IsExtended=false)
Allocates a space storing a local given its type.
Definition: ByteCodeExprGen.cpp:816
clang::interp::ByteCodeExprGen::allocateLocalPrimitive
unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsMutable, bool IsExtended=false)
Creates a local primitive value.
Definition: ByteCodeExprGen.cpp:802
clang::interp
Definition: ASTContext.h:155
clang::RecordType
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:4816
clang::interp::LocalScope
Scope for local variables.
Definition: ByteCodeExprGen.h:32
clang::interp::OptionScope::ChainedInitFnRef
std::function< bool(InitFnRef)> ChainedInitFnRef
Definition: ByteCodeExprGen.cpp:47
clang::CXXBoolLiteralExpr::getValue
bool getValue() const
Definition: ExprCXX.h:738
clang::ParenExpr::getSubExpr
const Expr * getSubExpr() const
Definition: Expr.h:2136
clang::BinaryOperator
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3812
clang::interp::ByteCodeExprGen::VisitCXXDefaultInitExpr
bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E)
Definition: ByteCodeExprGen.cpp:1236
clang::interp::LE
bool LE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:504
clang::SubstNonTypeTemplateParmExpr::getReplacement
Expr * getReplacement() const
Definition: ExprCXX.h:4307
clang::ASTContext
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:209
clang::interp::ByteCodeExprGen::getRecord
Record * getRecord(QualType Ty)
Returns a record from a record or pointer type.
Definition: ByteCodeExprGen.cpp:1089
clang::ArrayType
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3012
clang::DeclaratorContext::Member
@ Member
clang::Type::getAs
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:7386
clang::interp::PT_Bool
@ PT_Bool
Definition: PrimType.h:37
clang::interp::DeclScope
Scope used to handle temporaries in toplevel variable declarations.
Definition: ByteCodeExprGen.cpp:30
clang::interp::ByteCodeExprGen::VisitCallExpr
bool VisitCallExpr(const CallExpr *E)
Definition: ByteCodeExprGen.cpp:1173
clang::interp::ByteCodeExprGen::VisitConstantExpr
bool VisitConstantExpr(const ConstantExpr *E)
Definition: ByteCodeExprGen.cpp:359
clang::interp::PT_Uint32
@ PT_Uint32
Definition: PrimType.h:34
clang::interp::PrimType
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:28
clang::interp::ByteCodeExprGen::visitExpr
bool visitExpr(const Expr *E) override
Definition: ByteCodeExprGen.cpp:1124
clang::CharUnits::One
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition: CharUnits.h:58
clang::DeclRefExpr::getDecl
ValueDecl * getDecl()
Definition: Expr.h:1304
clang::Type::isFunctionType
bool isFunctionType() const
Definition: Type.h:6879
clang::AbstractConditionalOperator::getFalseExpr
Expr * getFalseExpr() const
Definition: Expr.h:4302
clang::ImplicitValueInitExpr
Represents an implicitly-generated value initialization of an object of a given type.
Definition: Expr.h:5515
bool
#define bool
Definition: stdbool.h:20
clang::interp::ByteCodeExprGen::DiscardResult
bool DiscardResult
Flag indicating if return value is to be discarded.
Definition: ByteCodeExprGen.h:270
clang::OpaqueValueExpr::getSourceExpr
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition: Expr.h:1194
clang::VarDecl
Represents a variable declaration or definition.
Definition: Decl.h:906
clang::Type::getPointeeType
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:625
clang::StringLiteral
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1776
clang::interp::Function::hasBody
bool hasBody() const
Definition: Function.h:139
PrimType.h
clang::interp::ByteCodeExprGen::visitRecordInitializer
bool visitRecordInitializer(const Expr *Initializer)
Compiles a record initializer.
Definition: ByteCodeExprGen.cpp:987
clang::interp::ByteCodeExprGen::VisitCXXNullPtrLiteralExpr
bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E)
Definition: ByteCodeExprGen.cpp:1257
clang::interp::ByteCodeExprGen::VisitParenExpr
bool VisitParenExpr(const ParenExpr *E)
Definition: ByteCodeExprGen.cpp:168
Base
clang::CXXDefaultArgExpr
A default argument (C++ [dcl.fct.default]).
Definition: ExprCXX.h:1248
clang::InitListExpr::inits
ArrayRef< Expr * > inits()
Definition: Expr.h:4836
clang::interp::ByteCodeExprGen::VisitUnaryExprOrTypeTraitExpr
bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E)
Definition: ByteCodeExprGen.cpp:386
clang::interp::ByteCodeExprGen::getRecordTy
const RecordType * getRecordTy(QualType Ty)
Returns a record type from a record or pointer type.
Definition: ByteCodeExprGen.cpp:1081
clang::ConstantExpr
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
Definition: Expr.h:1041
clang::CastExpr::getCastKind
CastKind getCastKind() const
Definition: Expr.h:3524
clang::interp::ByteCodeExprGen::VisitCXXDefaultArgExpr
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E)
Definition: ByteCodeExprGen.cpp:1242
clang::MemberExpr::getMemberDecl
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3252
clang::interp::ByteCodeExprGen::VisitIntegerLiteral
bool VisitIntegerLiteral(const IntegerLiteral *E)
Definition: ByteCodeExprGen.cpp:160
clang::FullExpr::getSubExpr
const Expr * getSubExpr() const
Definition: Expr.h:1026
clang::CharacterLiteral
Definition: Expr.h:1593
Emitter
clang::UnaryExprOrTypeTraitExpr::isArgumentType
bool isArgumentType() const
Definition: Expr.h:2600
clang::interp::ByteCodeExprGen::VisitCompoundAssignOperator
bool VisitCompoundAssignOperator(const CompoundAssignOperator *E)
Definition: ByteCodeExprGen.cpp:525
clang::MemberExpr::getBase
Expr * getBase() const
Definition: Expr.h:3246
clang::CXXRecordDecl
Represents a C++ struct/union/class.
Definition: DeclCXX.h:254
clang::ASTContext::getPreferredTypeAlign
unsigned getPreferredTypeAlign(QualType T) const
Return the "preferred" alignment of the specified type T for the current target, in bits.
Definition: ASTContext.h:2393
clang::interp::ByteCodeExprGen::VisitUnaryOperator
bool VisitUnaryOperator(const UnaryOperator *E)
Definition: ByteCodeExprGen.cpp:1273
P
StringRef P
Definition: ASTMatchersInternal.cpp:563
clang::Type::isDependentType
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2304
clang::interp::ByteCodeExprGen::VisitInitListExpr
bool VisitInitListExpr(const InitListExpr *E)
Definition: ByteCodeExprGen.cpp:344
dereference
static llvm::Optional< DereferenceInfo > dereference(ProgramStateRef State, const FieldRegion *FR)
Dereferences FR and returns with the pointee's region, and whether it needs to be casted back to it's...
Definition: UninitializedPointee.cpp:220
clang::Type::isPointerType
bool isPointerType() const
Definition: Type.h:6883
clang::interp::ByteCodeExprGen::InitFn
llvm::Optional< InitFnRef > InitFn
Expression being initialized.
Definition: ByteCodeExprGen.h:273
clang::ASTContext::getDeclAlign
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
Definition: ASTContext.cpp:1742
clang::ValueDecl
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:701
clang::interp::OptionScope::OptionScope
OptionScope(ByteCodeExprGen< Emitter > *Ctx, InitFnRef NewInitFn)
Root constructor, setting up compilation state.
Definition: ByteCodeExprGen.cpp:58
clang::interp::ByteCodeExprGen::LabelTy
typename Emitter::LabelTy LabelTy
Definition: ByteCodeExprGen.h:45
clang::CXXDefaultInitExpr::getExpr
const Expr * getExpr() const
Get the initialization expression that will be used.
Definition: ExprCXX.h:1353
clang::BinaryOperator::getLHS
Expr * getLHS() const
Definition: Expr.h:3861
clang::ParenExpr
ParenExpr - This represents a parethesized expression, e.g.
Definition: Expr.h:2121
clang::DeclContext::getParent
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:1923
Value
Value
Definition: UninitializedValues.cpp:103
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:83
clang::ArraySubscriptExpr
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2654
clang::UnaryExprOrTypeTraitExpr::getTypeOfArgument
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
Definition: Expr.h:2627
clang::interp::Record::getBase
const Base * getBase(const RecordDecl *FD) const
Returns a base descriptor.
Definition: Record.cpp:36
clang::interp::Record::Field::Decl
const FieldDecl * Decl
Definition: Record.h:28
clang::CXXNullPtrLiteralExpr
The null pointer literal (C++11 [lex.nullptr])
Definition: ExprCXX.h:766
clang::Type::isConstantSizeType
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
Definition: Type.cpp:2225
clang::interp::PT_Uint8
@ PT_Uint8
Definition: PrimType.h:30
clang::CompoundAssignOperator
CompoundAssignOperator - For compound assignments (e.g.
Definition: Expr.h:4059
clang::BinaryOperatorKind
BinaryOperatorKind
Definition: OperationKinds.h:25
clang::VarDecl::getInit
const Expr * getInit() const
Definition: Decl.h:1315
FromDecl
const NamedDecl * FromDecl
Definition: USRLocFinder.cpp:169
clang::interp::ByteCodeExprGen::visitInitializer
bool visitInitializer(const Expr *E)
Compiles an initializer.
Definition: ByteCodeExprGen.cpp:1067
clang::ObjCPropertyAttribute::Kind
Kind
Definition: DeclObjCCommon.h:22
clang::CXXThisExpr
Represents the this expression in C++.
Definition: ExprCXX.h:1149
clang::interp::PT_Sint32
@ PT_Sint32
Definition: PrimType.h:33
std
Definition: Format.h:4477
clang::interp::PT_Sint8
@ PT_Sint8
Definition: PrimType.h:29
clang::interp::Descriptor
Describes a memory block created by an allocation site.
Definition: Descriptor.h:51
clang::PointerType
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:2769
clang::UnaryExprOrTypeTraitExpr::getKind
UnaryExprOrTypeTrait getKind() const
Definition: Expr.h:2590
clang::AbstractConditionalOperator::getCond
Expr * getCond() const
Definition: Expr.h:4290
clang::UnaryOperator::getSubExpr
Expr * getSubExpr() const
Definition: Expr.h:2219
clang::Expr::IgnoreParens
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3031
clang
Definition: CalledOnceCheck.h:17
Function.h
clang::Type::isArrayType
bool isArrayType() const
Definition: Type.h:6949
clang::ASTContext::toCharUnitsFromBits
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
Definition: ASTContext.cpp:2504
clang::interp::Function
Bytecode function.
Definition: Function.h:74
clang::interp::Function::isFullyCompiled
bool isFullyCompiled() const
Checks if the function is fully done compiling.
Definition: Function.h:134
clang::VarDecl::isConstexpr
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition: Decl.h:1509
clang::UnaryOperator::getOpcode
Opcode getOpcode() const
Definition: Expr.h:2214
clang::BinaryOperator::getRHS
Expr * getRHS() const
Definition: Expr.h:3863
clang::DeclaratorContext::Condition
@ Condition
clang::interp::ByteCodeExprGen::VisitAbstractConditionalOperator
bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E)
Definition: ByteCodeExprGen.cpp:482
clang::Expr::getType
QualType getType() const
Definition: Expr.h:141
AlignOfType
static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx, UnaryExprOrTypeTrait Kind)
Definition: ByteCodeExprGen.cpp:365
clang::interp::PT_Uint64
@ PT_Uint64
Definition: PrimType.h:36
ByteCodeEmitter.h
clang::interp::OptionScope::OptionScope
OptionScope(ByteCodeExprGen< Emitter > *Ctx, ChainedInitFnRef NewInitFn)
Extends the chain of initialisation pointers.
Definition: ByteCodeExprGen.cpp:66
clang::interp::ByteCodeExprGen::VisitCastExpr
bool VisitCastExpr(const CastExpr *E)
Definition: ByteCodeExprGen.cpp:91
clang::interp::PT_Sint64
@ PT_Sint64
Definition: PrimType.h:35
clang::ArraySubscriptExpr::getBase
Expr * getBase()
Definition: Expr.h:2691
clang::MemberExpr
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3169
clang::interp::ByteCodeExprGen::visitDecl
bool visitDecl(const VarDecl *VD) override
Definition: ByteCodeExprGen.cpp:1136
State.h
clang::QualType::getTypePtr
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:6622
Program.h
clang::interp::DeclTy
unsigned llvm::PointerUnion< const Decl *, const Expr * > DeclTy
Definition: Descriptor.h:26
clang::ReferenceType
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:2880
clang::CharUnits
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
clang::interp::ByteCodeExprGen::VisitCharacterLiteral
bool VisitCharacterLiteral(const CharacterLiteral *E)
Definition: ByteCodeExprGen.cpp:519
clang::CallExpr::getBuiltinCallee
unsigned getBuiltinCallee() const
getBuiltinCallee - If this is a call to a builtin, return the builtin ID of the callee.
Definition: Expr.cpp:1564
clang::interp::PT_Ptr
@ PT_Ptr
Definition: PrimType.h:38
clang::Expr::refersToBitField
bool refersToBitField() const
Returns true if this expression is a gl-value that potentially refers to a bit-field.
Definition: Expr.h:462
clang::interp::ByteCodeExprGen::visit
bool visit(const Expr *E)
Evaluates an expression and places result on stack.
Definition: ByteCodeExprGen.cpp:587
clang::CallExpr::arguments
arg_range arguments()
Definition: Expr.h:3049
clang::ValueDecl::getType
QualType getType() const
Definition: Decl.h:712
true
#define true
Definition: stdbool.h:21
clang::Type::isIntegerType
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:7212
clang::LangOptions::ClangABI::Ver7
@ Ver7
Attempt to be ABI-compatible with code generated by Clang 7.0.x (SVN r338536).
clang::Expr
This represents one expression.
Definition: Expr.h:109
clang::interp::ByteCodeExprGen::getFunction
const Function * getFunction(const FunctionDecl *FD)
Definition: ByteCodeExprGen.cpp:1102
clang::CXXDefaultInitExpr
A use of a default initializer in a constructor or in aggregate initialization.
Definition: ExprCXX.h:1325
clang::VarDecl::hasLocalStorage
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition: Decl.h:1131
clang::interp::ByteCodeExprGen::VisitArraySubscriptExpr
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E)
Definition: ByteCodeExprGen.cpp:317
ByteCodeGenError.h
clang::CastExpr
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3480
clang::interp::Record
Structure/Class descriptor.
Definition: Record.h:24
clang::DeclRefExpr
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1232
clang::interp::ByteCodeExprGen::VisitArrayInitIndexExpr
bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E)
Definition: ByteCodeExprGen.cpp:467
clang::FunctionDecl
Represents a function declaration or definition.
Definition: Decl.h:1904
clang::RecordDecl
Represents a struct/union/class.
Definition: Decl.h:3983
clang::CallExpr
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2810
clang::interp::ArrayIndexScope
Definition: ByteCodeExprGen.h:37
clang::ASTContext::getLangOpts
const LangOptions & getLangOpts() const
Definition: ASTContext.h:791
clang::CXXMemberCallExpr
Represents a call to a member function that may be written either with member call syntax (e....
Definition: ExprCXX.h:177
Context.h
ByteCodeExprGen.h
clang::interp::ByteCodeExprGen::visitArrayInitializer
bool visitArrayInitializer(const Expr *Initializer)
Compiles an array initializer.
Definition: ByteCodeExprGen.cpp:849
clang::UnaryExprOrTypeTrait
UnaryExprOrTypeTrait
Names for the "expression or type" traits.
Definition: TypeTraits.h:51