clang 22.0.0git
Context.cpp
Go to the documentation of this file.
1//===--- Context.cpp - Context for the constexpr VM -------------*- 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 "Context.h"
10#include "ByteCodeEmitter.h"
11#include "Compiler.h"
12#include "EvalEmitter.h"
13#include "Interp.h"
14#include "InterpFrame.h"
15#include "InterpStack.h"
16#include "PrimType.h"
17#include "Program.h"
18#include "clang/AST/ASTLambda.h"
19#include "clang/AST/Expr.h"
21
22using namespace clang;
23using namespace clang::interp;
24
25Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {
26 this->ShortWidth = Ctx.getTargetInfo().getShortWidth();
27 this->IntWidth = Ctx.getTargetInfo().getIntWidth();
28 this->LongWidth = Ctx.getTargetInfo().getLongWidth();
29 this->LongLongWidth = Ctx.getTargetInfo().getLongLongWidth();
30 assert(Ctx.getTargetInfo().getCharWidth() == 8 &&
31 "We're assuming 8 bit chars");
32}
33
35
37 assert(Stk.empty());
38
39 // Get a function handle.
41 if (!Func)
42 return false;
43
44 // Compile the function.
45 Compiler<ByteCodeEmitter>(*this, *P).compileFunc(
46 FD, const_cast<Function *>(Func));
47
48 if (!Func->isValid())
49 return false;
50
51 ++EvalID;
52 // And run it.
53 return Run(Parent, Func);
54}
55
57 const FunctionDecl *FD) {
58 assert(Stk.empty());
59 ++EvalID;
60 size_t StackSizeBefore = Stk.size();
61 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
62
63 if (!C.interpretCall(FD, E)) {
64 C.cleanup();
65 Stk.clearTo(StackSizeBefore);
66 }
67}
68
70 ++EvalID;
71 bool Recursing = !Stk.empty();
72 size_t StackSizeBefore = Stk.size();
73 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
74
75 auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue());
76
77 if (Res.isInvalid()) {
78 C.cleanup();
79 Stk.clearTo(StackSizeBefore);
80 return false;
81 }
82
83 if (!Recursing) {
84 // We *can* actually get here with a non-empty stack, since
85 // things like InterpState::noteSideEffect() exist.
86 C.cleanup();
87#ifndef NDEBUG
88 // Make sure we don't rely on some value being still alive in
89 // InterpStack memory.
90 Stk.clearTo(StackSizeBefore);
91#endif
92 }
93
94 Result = Res.stealAPValue();
95
96 return true;
97}
98
100 ConstantExprKind Kind) {
101 ++EvalID;
102 bool Recursing = !Stk.empty();
103 size_t StackSizeBefore = Stk.size();
104 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
105
106 auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/false,
107 /*DestroyToplevelScope=*/true);
108 if (Res.isInvalid()) {
109 C.cleanup();
110 Stk.clearTo(StackSizeBefore);
111 return false;
112 }
113
114 if (!Recursing) {
115 assert(Stk.empty());
116 C.cleanup();
117#ifndef NDEBUG
118 // Make sure we don't rely on some value being still alive in
119 // InterpStack memory.
120 Stk.clearTo(StackSizeBefore);
121#endif
122 }
123
124 Result = Res.stealAPValue();
125 return true;
126}
127
129 APValue &Result) {
130 ++EvalID;
131 bool Recursing = !Stk.empty();
132 size_t StackSizeBefore = Stk.size();
133 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
134
135 bool CheckGlobalInitialized =
137 (VD->getType()->isRecordType() || VD->getType()->isArrayType());
138 auto Res = C.interpretDecl(VD, CheckGlobalInitialized);
139 if (Res.isInvalid()) {
140 C.cleanup();
141 Stk.clearTo(StackSizeBefore);
142
143 return false;
144 }
145
146 if (!Recursing) {
147 assert(Stk.empty());
148 C.cleanup();
149#ifndef NDEBUG
150 // Make sure we don't rely on some value being still alive in
151 // InterpStack memory.
152 Stk.clearTo(StackSizeBefore);
153#endif
154 }
155
156 Result = Res.stealAPValue();
157 return true;
158}
159
160template <typename ResultT>
161bool Context::evaluateStringRepr(State &Parent, const Expr *SizeExpr,
162 const Expr *PtrExpr, ResultT &Result) {
163 assert(Stk.empty());
164 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
165
166 // Evaluate size value.
167 APValue SizeValue;
168 if (!evaluateAsRValue(Parent, SizeExpr, SizeValue))
169 return false;
170
171 if (!SizeValue.isInt())
172 return false;
173 uint64_t Size = SizeValue.getInt().getZExtValue();
174
175 auto PtrRes = C.interpretAsPointer(PtrExpr, [&](const Pointer &Ptr) {
176 if (Size == 0) {
177 if constexpr (std::is_same_v<ResultT, APValue>)
179 return true;
180 }
181
182 if (!Ptr.isLive() || !Ptr.getFieldDesc()->isPrimitiveArray())
183 return false;
184
185 // Must be char.
186 if (Ptr.getFieldDesc()->getElemSize() != 1 /*bytes*/)
187 return false;
188
189 if (Size > Ptr.getNumElems()) {
190 Parent.FFDiag(SizeExpr, diag::note_constexpr_access_past_end) << AK_Read;
191 Size = Ptr.getNumElems();
192 }
193
194 if constexpr (std::is_same_v<ResultT, APValue>) {
195 QualType CharTy = PtrExpr->getType()->getPointeeType();
197 for (uint64_t I = 0; I != Size; ++I) {
198 if (std::optional<APValue> ElemVal =
199 Ptr.atIndex(I).toRValue(*this, CharTy))
200 Result.getArrayInitializedElt(I) = *ElemVal;
201 else
202 return false;
203 }
204 } else {
205 assert((std::is_same_v<ResultT, std::string>));
206 if (Size < Result.max_size())
207 Result.resize(Size);
208 Result.assign(reinterpret_cast<const char *>(Ptr.getRawAddress()), Size);
209 }
210
211 return true;
212 });
213
214 if (PtrRes.isInvalid()) {
215 C.cleanup();
216 Stk.clear();
217 return false;
218 }
219
220 return true;
221}
222
224 const Expr *PtrExpr, APValue &Result) {
225 assert(SizeExpr);
226 assert(PtrExpr);
227
228 return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
229}
230
232 const Expr *PtrExpr, std::string &Result) {
233 assert(SizeExpr);
234 assert(PtrExpr);
235
236 return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
237}
238
239bool Context::evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result) {
240 assert(Stk.empty());
241 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
242
243 auto PtrRes = C.interpretAsPointer(E, [&](const Pointer &Ptr) {
244 const Descriptor *FieldDesc = Ptr.getFieldDesc();
245 if (!FieldDesc->isPrimitiveArray())
246 return false;
247
248 unsigned N = Ptr.getNumElems();
249 if (Ptr.elemSize() == 1) {
250 Result = strnlen(reinterpret_cast<const char *>(Ptr.getRawAddress()), N);
251 return Result != N;
252 }
253
254 PrimType ElemT = FieldDesc->getPrimType();
255 Result = 0;
256 for (unsigned I = Ptr.getIndex(); I != N; ++I) {
257 INT_TYPE_SWITCH(ElemT, {
258 auto Elem = Ptr.elem<T>(I);
259 if (Elem.isZero())
260 return true;
261 ++Result;
262 });
263 }
264 // We didn't find a 0 byte.
265 return false;
266 });
267
268 if (PtrRes.isInvalid()) {
269 C.cleanup();
270 Stk.clear();
271 return false;
272 }
273 return true;
274}
275
276const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
277
278static PrimType integralTypeToPrimTypeS(unsigned BitWidth) {
279 switch (BitWidth) {
280 case 64:
281 return PT_Sint64;
282 case 32:
283 return PT_Sint32;
284 case 16:
285 return PT_Sint16;
286 case 8:
287 return PT_Sint8;
288 default:
289 return PT_IntAPS;
290 }
291 llvm_unreachable("Unhandled BitWidth");
292}
293
294static PrimType integralTypeToPrimTypeU(unsigned BitWidth) {
295 switch (BitWidth) {
296 case 64:
297 return PT_Uint64;
298 case 32:
299 return PT_Uint32;
300 case 16:
301 return PT_Uint16;
302 case 8:
303 return PT_Uint8;
304 default:
305 return PT_IntAP;
306 }
307 llvm_unreachable("Unhandled BitWidth");
308}
309
311
312 if (const auto *BT = dyn_cast<BuiltinType>(T.getCanonicalType())) {
313 auto Kind = BT->getKind();
314 if (Kind == BuiltinType::Bool)
315 return PT_Bool;
316 if (Kind == BuiltinType::NullPtr)
317 return PT_Ptr;
318 if (Kind == BuiltinType::BoundMember)
319 return PT_MemberPtr;
320
321 // Just trying to avoid the ASTContext::getIntWidth call below.
322 if (Kind == BuiltinType::Short)
323 return integralTypeToPrimTypeS(this->ShortWidth);
324 if (Kind == BuiltinType::UShort)
325 return integralTypeToPrimTypeU(this->ShortWidth);
326
327 if (Kind == BuiltinType::Int)
328 return integralTypeToPrimTypeS(this->IntWidth);
329 if (Kind == BuiltinType::UInt)
330 return integralTypeToPrimTypeU(this->IntWidth);
331 if (Kind == BuiltinType::Long)
332 return integralTypeToPrimTypeS(this->LongWidth);
333 if (Kind == BuiltinType::ULong)
334 return integralTypeToPrimTypeU(this->LongWidth);
335 if (Kind == BuiltinType::LongLong)
336 return integralTypeToPrimTypeS(this->LongLongWidth);
337 if (Kind == BuiltinType::ULongLong)
338 return integralTypeToPrimTypeU(this->LongLongWidth);
339
340 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
341 return integralTypeToPrimTypeS(8);
342 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
343 Kind == BuiltinType::Char8)
344 return integralTypeToPrimTypeU(8);
345
346 if (BT->isSignedInteger())
348 if (BT->isUnsignedInteger())
350
351 if (BT->isFloatingPoint())
352 return PT_Float;
353 }
354
356 return PT_Ptr;
357
358 if (T->isMemberPointerType())
359 return PT_MemberPtr;
360
361 if (const auto *BT = T->getAs<BitIntType>()) {
362 if (BT->isSigned())
363 return integralTypeToPrimTypeS(BT->getNumBits());
364 return integralTypeToPrimTypeU(BT->getNumBits());
365 }
366
367 if (const auto *D = T->getAsEnumDecl()) {
368 if (!D->isComplete())
369 return std::nullopt;
370 return classify(D->getIntegerType());
371 }
372
373 if (const auto *AT = T->getAs<AtomicType>())
374 return classify(AT->getValueType());
375
376 if (const auto *DT = dyn_cast<DecltypeType>(T))
377 return classify(DT->getUnderlyingType());
378
380 return PT_Ptr;
381
382 if (T->isFixedPointType())
383 return PT_FixedPoint;
384
385 // Vector and complex types get here.
386 return std::nullopt;
387}
388
389unsigned Context::getCharBit() const {
390 return Ctx.getTargetInfo().getCharWidth();
391}
392
393/// Simple wrapper around getFloatTypeSemantics() to make code a
394/// little shorter.
395const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const {
396 return Ctx.getFloatTypeSemantics(T);
397}
398
399bool Context::Run(State &Parent, const Function *Func) {
400 InterpState State(Parent, *P, Stk, *this, Func);
401 if (Interpret(State)) {
402 assert(Stk.empty());
403 return true;
404 }
405 Stk.clear();
406 return false;
407}
408
409// TODO: Virtual bases?
410const CXXMethodDecl *
412 const CXXRecordDecl *StaticDecl,
413 const CXXMethodDecl *InitialFunction) const {
414 assert(DynamicDecl);
415 assert(StaticDecl);
416 assert(InitialFunction);
417
418 const CXXRecordDecl *CurRecord = DynamicDecl;
419 const CXXMethodDecl *FoundFunction = InitialFunction;
420 for (;;) {
421 const CXXMethodDecl *Overrider =
422 FoundFunction->getCorrespondingMethodDeclaredInClass(CurRecord, false);
423 if (Overrider)
424 return Overrider;
425
426 // Common case of only one base class.
427 if (CurRecord->getNumBases() == 1) {
428 CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl();
429 continue;
430 }
431
432 // Otherwise, go to the base class that will lead to the StaticDecl.
433 for (const CXXBaseSpecifier &Spec : CurRecord->bases()) {
434 const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl();
435 if (Base == StaticDecl || Base->isDerivedFrom(StaticDecl)) {
436 CurRecord = Base;
437 break;
438 }
439 }
440 }
441
442 llvm_unreachable(
443 "Couldn't find an overriding function in the class hierarchy?");
444 return nullptr;
445}
446
448 assert(FuncDecl);
449 FuncDecl = FuncDecl->getMostRecentDecl();
450
451 if (const Function *Func = P->getFunction(FuncDecl))
452 return Func;
453
454 // Manually created functions that haven't been assigned proper
455 // parameters yet.
456 if (!FuncDecl->param_empty() && !FuncDecl->param_begin())
457 return nullptr;
458
459 bool IsLambdaStaticInvoker = false;
460 if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl);
461 MD && MD->isLambdaStaticInvoker()) {
462 // For a lambda static invoker, we might have to pick a specialized
463 // version if the lambda is generic. In that case, the picked function
464 // will *NOT* be a static invoker anymore. However, it will still
465 // be a non-static member function, this (usually) requiring an
466 // instance pointer. We suppress that later in this function.
467 IsLambdaStaticInvoker = true;
468
469 const CXXRecordDecl *ClosureClass = MD->getParent();
470 assert(ClosureClass->captures().empty());
471 if (ClosureClass->isGenericLambda()) {
472 const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator();
473 assert(MD->isFunctionTemplateSpecialization() &&
474 "A generic lambda's static-invoker function must be a "
475 "template specialization");
476 const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs();
477 FunctionTemplateDecl *CallOpTemplate =
478 LambdaCallOp->getDescribedFunctionTemplate();
479 void *InsertPos = nullptr;
480 const FunctionDecl *CorrespondingCallOpSpecialization =
481 CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos);
482 assert(CorrespondingCallOpSpecialization);
483 FuncDecl = CorrespondingCallOpSpecialization;
484 }
485 }
486 // Set up argument indices.
487 unsigned ParamOffset = 0;
488 SmallVector<PrimType, 8> ParamTypes;
489 SmallVector<unsigned, 8> ParamOffsets;
490 llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;
491
492 // If the return is not a primitive, a pointer to the storage where the
493 // value is initialized in is passed as the first argument. See 'RVO'
494 // elsewhere in the code.
495 QualType Ty = FuncDecl->getReturnType();
496 bool HasRVO = false;
497 if (!Ty->isVoidType() && !canClassify(Ty)) {
498 HasRVO = true;
499 ParamTypes.push_back(PT_Ptr);
500 ParamOffsets.push_back(ParamOffset);
502 }
503
504 // If the function decl is a member decl, the next parameter is
505 // the 'this' pointer. This parameter is pop()ed from the
506 // InterpStack when calling the function.
507 bool HasThisPointer = false;
508 if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) {
509 if (!IsLambdaStaticInvoker) {
510 HasThisPointer = MD->isInstance();
511 if (MD->isImplicitObjectMemberFunction()) {
512 ParamTypes.push_back(PT_Ptr);
513 ParamOffsets.push_back(ParamOffset);
515 }
516 }
517
518 if (isLambdaCallOperator(MD)) {
519 // The parent record needs to be complete, we need to know about all
520 // the lambda captures.
521 if (!MD->getParent()->isCompleteDefinition())
522 return nullptr;
523 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
524 FieldDecl *LTC;
525
526 MD->getParent()->getCaptureFields(LC, LTC);
527
528 if (MD->isStatic() && !LC.empty()) {
529 // Static lambdas cannot have any captures. If this one does,
530 // it has already been diagnosed and we can only ignore it.
531 return nullptr;
532 }
533 }
534 }
535
536 // Assign descriptors to all parameters.
537 // Composite objects are lowered to pointers.
538 for (const ParmVarDecl *PD : FuncDecl->parameters()) {
539 OptPrimType T = classify(PD->getType());
540 PrimType PT = T.value_or(PT_Ptr);
541 Descriptor *Desc = P->createDescriptor(PD, PT);
542 ParamDescriptors.insert({ParamOffset, {PT, Desc}});
543 ParamOffsets.push_back(ParamOffset);
544 ParamOffset += align(primSize(PT));
545 ParamTypes.push_back(PT);
546 }
547
548 // Create a handle over the emitted code.
549 assert(!P->getFunction(FuncDecl));
550 const Function *Func = P->createFunction(
551 FuncDecl, ParamOffset, std::move(ParamTypes), std::move(ParamDescriptors),
552 std::move(ParamOffsets), HasThisPointer, HasRVO, IsLambdaStaticInvoker);
553 return Func;
554}
555
557 const BlockDecl *BD = E->getBlockDecl();
558 // Set up argument indices.
559 unsigned ParamOffset = 0;
560 SmallVector<PrimType, 8> ParamTypes;
561 SmallVector<unsigned, 8> ParamOffsets;
562 llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;
563
564 // Assign descriptors to all parameters.
565 // Composite objects are lowered to pointers.
566 for (const ParmVarDecl *PD : BD->parameters()) {
567 OptPrimType T = classify(PD->getType());
568 PrimType PT = T.value_or(PT_Ptr);
569 Descriptor *Desc = P->createDescriptor(PD, PT);
570 ParamDescriptors.insert({ParamOffset, {PT, Desc}});
571 ParamOffsets.push_back(ParamOffset);
572 ParamOffset += align(primSize(PT));
573 ParamTypes.push_back(PT);
574 }
575
576 if (BD->hasCaptures())
577 return nullptr;
578
579 // Create a handle over the emitted code.
580 Function *Func =
581 P->createFunction(E, ParamOffset, std::move(ParamTypes),
582 std::move(ParamDescriptors), std::move(ParamOffsets),
583 /*HasThisPointer=*/false, /*HasRVO=*/false,
584 /*IsLambdaStaticInvoker=*/false);
585
586 assert(Func);
587 Func->setDefined(true);
588 // We don't compile the BlockDecl code at all right now.
589 Func->setIsFullyCompiled(true);
590 return Func;
591}
592
593unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl,
594 const RecordDecl *DerivedDecl) const {
595 assert(BaseDecl);
596 assert(DerivedDecl);
597 const auto *FinalDecl = cast<CXXRecordDecl>(BaseDecl);
598 const RecordDecl *CurDecl = DerivedDecl;
599 const Record *CurRecord = P->getOrCreateRecord(CurDecl);
600 assert(CurDecl && FinalDecl);
601
602 unsigned OffsetSum = 0;
603 for (;;) {
604 assert(CurRecord->getNumBases() > 0);
605 // One level up
606 for (const Record::Base &B : CurRecord->bases()) {
607 const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl);
608
609 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
610 OffsetSum += B.Offset;
611 CurRecord = B.R;
612 CurDecl = BaseDecl;
613 break;
614 }
615 }
616 if (CurDecl == FinalDecl)
617 break;
618 }
619
620 assert(OffsetSum > 0);
621 return OffsetSum;
622}
623
624const Record *Context::getRecord(const RecordDecl *D) const {
625 return P->getOrCreateRecord(D);
626}
627
629 return ID == Builtin::BI__builtin_classify_type ||
630 ID == Builtin::BI__builtin_os_log_format_buffer_size ||
631 ID == Builtin::BI__builtin_constant_p || ID == Builtin::BI__noop;
632}
NodeId Parent
Definition: ASTDiff.cpp:191
This file provides some common utility functions for processing Lambda related AST Constructs.
StringRef P
const Decl * D
Expr * E
static PrimType integralTypeToPrimTypeS(unsigned BitWidth)
Definition: Context.cpp:278
static PrimType integralTypeToPrimTypeU(unsigned BitWidth)
Definition: Context.cpp:294
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition: APValue.h:122
APSInt & getInt()
Definition: APValue.h:489
bool isInt() const
Definition: APValue.h:467
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
unsigned getIntWidth(QualType T) const
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
const LangOptions & getLangOpts() const
Definition: ASTContext.h:894
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:859
A fixed int type of a specified bitwidth.
Definition: TypeBase.h:8195
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition: Decl.h:4634
bool hasCaptures() const
True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...
Definition: Decl.h:4753
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:4720
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition: Expr.h:6560
Represents a base class of a C++ class.
Definition: DeclCXX.h:146
QualType getType() const
Retrieves the type of the base class.
Definition: DeclCXX.h:249
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2129
CXXMethodDecl * getCorrespondingMethodDeclaredInClass(const CXXRecordDecl *RD, bool MayBeBase=false)
Find if RD declares a function that overrides this function, and if so, return it.
Definition: DeclCXX.cpp:2423
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool isGenericLambda() const
Determine whether this class describes a generic lambda function object (i.e.
Definition: DeclCXX.cpp:1673
base_class_range bases()
Definition: DeclCXX.h:608
unsigned getNumBases() const
Retrieves the number of base classes of this class.
Definition: DeclCXX.h:602
base_class_iterator bases_begin()
Definition: DeclCXX.h:615
capture_const_range captures() const
Definition: DeclCXX.h:1097
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
Definition: DeclCXX.cpp:1736
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2109
This represents one expression.
Definition: Expr.h:112
bool isGLValue() const
Definition: Expr.h:287
ConstantExprKind
Definition: Expr.h:751
QualType getType() const
Definition: Expr.h:144
Represents a member of a struct/union/class.
Definition: Decl.h:3157
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition: Decl.h:3393
Represents a function declaration or definition.
Definition: Decl.h:1999
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition: Decl.cpp:4134
QualType getReturnType() const
Definition: Decl.h:2842
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2771
param_iterator param_begin()
Definition: Decl.h:2783
bool param_empty() const
Definition: Decl.h:2782
Declaration of a template function.
Definition: DeclTemplate.h:952
FunctionDecl * findSpecialization(ArrayRef< TemplateArgument > Args, void *&InsertPos)
Return the specialization with the provided arguments if it exists, otherwise return the insertion po...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:434
Represents a parameter to a function.
Definition: Decl.h:1789
A (possibly-)qualified type.
Definition: TypeBase.h:937
Represents a struct/union/class.
Definition: Decl.h:4309
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Definition: Redeclarable.h:223
unsigned getShortWidth() const
getShortWidth/Align - Return the size of 'signed short' and 'unsigned short' for this target,...
Definition: TargetInfo.h:522
unsigned getIntWidth() const
getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for this target,...
Definition: TargetInfo.h:527
unsigned getLongLongWidth() const
getLongLongWidth/Align - Return the size of 'signed long long' and 'unsigned long long' for this targ...
Definition: TargetInfo.h:537
unsigned getCharWidth() const
Definition: TargetInfo.h:517
unsigned getLongWidth() const
getLongWidth/Align - Return the size of 'signed long' and 'unsigned long' for this target,...
Definition: TargetInfo.h:532
A template argument list.
Definition: DeclTemplate.h:250
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
Definition: DeclTemplate.h:280
bool isBlockPointerType() const
Definition: TypeBase.h:8600
bool isVoidType() const
Definition: TypeBase.h:8936
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.h:26
bool isArrayType() const
Definition: TypeBase.h:8679
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
bool isFixedPointType() const
Return true if this is a fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
Definition: TypeBase.h:8992
bool isMemberPointerType() const
Definition: TypeBase.h:8661
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition: Type.h:53
bool isPointerOrReferenceType() const
Definition: TypeBase.h:8584
bool isObjCObjectPointerType() const
Definition: TypeBase.h:8749
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
bool isRecordType() const
Definition: TypeBase.h:8707
QualType getType() const
Definition: Decl.h:722
Represents a variable declaration or definition.
Definition: Decl.h:925
Compilation context for expressions.
Definition: Compiler.h:110
const LangOptions & getLangOpts() const
Returns the language options.
Definition: Context.cpp:276
const Function * getOrCreateObjCBlock(const BlockExpr *E)
Definition: Context.cpp:556
~Context()
Cleans up the constexpr VM.
Definition: Context.cpp:34
Context(ASTContext &Ctx)
Initialises the constexpr VM.
Definition: Context.cpp:25
bool evaluateCharRange(State &Parent, const Expr *SizeExpr, const Expr *PtrExpr, APValue &Result)
Definition: Context.cpp:223
bool canClassify(QualType T)
Definition: Context.h:96
static bool isUnevaluatedBuiltin(unsigned ID)
Unevaluated builtins don't get their arguments put on the stack automatically.
Definition: Context.cpp:628
unsigned getCharBit() const
Returns CHAR_BIT.
Definition: Context.cpp:389
bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result)
Evaluates a toplevel initializer.
Definition: Context.cpp:128
bool evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result)
Evalute.
Definition: Context.cpp:239
const llvm::fltSemantics & getFloatSemantics(QualType T) const
Return the floating-point semantics for T.
Definition: Context.cpp:395
static bool shouldBeGloballyIndexed(const ValueDecl *VD)
Returns whether we should create a global variable for the given ValueDecl.
Definition: Context.h:125
void isPotentialConstantExprUnevaluated(State &Parent, const Expr *E, const FunctionDecl *FD)
Definition: Context.cpp:56
unsigned collectBaseOffset(const RecordDecl *BaseDecl, const RecordDecl *DerivedDecl) const
Definition: Context.cpp:593
const Record * getRecord(const RecordDecl *D) const
Definition: Context.cpp:624
bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FD)
Checks if a function is a potential constant expression.
Definition: Context.cpp:36
const Function * getOrCreateFunction(const FunctionDecl *FuncDecl)
Definition: Context.cpp:447
OptPrimType classify(QualType T) const
Classifies a type.
Definition: Context.cpp:310
bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result)
Evaluates a toplevel expression as an rvalue.
Definition: Context.cpp:69
const CXXMethodDecl * getOverridingFunction(const CXXRecordDecl *DynamicDecl, const CXXRecordDecl *StaticDecl, const CXXMethodDecl *InitialFunction) const
Definition: Context.cpp:411
bool evaluate(State &Parent, const Expr *E, APValue &Result, ConstantExprKind Kind)
Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
Definition: Context.cpp:99
Bytecode function.
Definition: Function.h:86
void clearTo(size_t NewSize)
Definition: InterpStack.cpp:41
void clear()
Clears the stack.
Definition: InterpStack.cpp:33
size_t size() const
Returns the size of the stack in bytes.
Definition: InterpStack.h:77
bool empty() const
Returns whether the stack is empty.
Definition: InterpStack.h:84
Interpreter context.
Definition: InterpState.h:43
A pointer to a memory block, live or dead.
Definition: Pointer.h:90
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
Definition: Pointer.h:155
int64_t getIndex() const
Returns the index into an array.
Definition: Pointer.h:608
unsigned getNumElems() const
Returns the number of elements.
Definition: Pointer.h:592
bool isLive() const
Checks if the pointer is live.
Definition: Pointer.h:264
std::optional< APValue > toRValue(const Context &Ctx, QualType ResultType) const
Converts the pointer to an APValue that is an rvalue.
Definition: Pointer.cpp:711
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
Definition: Pointer.h:322
size_t elemSize() const
Returns the element size of the innermost field.
Definition: Pointer.h:354
const std::byte * getRawAddress() const
If backed by actual data (i.e.
Definition: Pointer.h:602
The program contains and links the bytecode for all functions.
Definition: Program.h:36
Structure/Class descriptor.
Definition: Record.h:25
unsigned getNumBases() const
Definition: Record.h:92
llvm::iterator_range< const_base_iter > bases() const
Definition: Record.h:88
Interface for the VM to interact with the AST walker's context.
Definition: State.h:58
Defines the clang::TargetInfo interface.
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition: PrimType.h:185
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:34
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
Definition: PrimType.cpp:23
bool Interpret(InterpState &S)
Interpreter entry point.
Definition: Interp.cpp:2262
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isLambdaCallOperator(const CXXMethodDecl *MD)
Definition: ASTLambda.h:28
@ Result
The result type of a method or function.
@ AK_Read
Definition: State.h:27
for(const auto &A :T->param_types())
const FunctionProtoType * T
Describes a memory block created by an allocation site.
Definition: Descriptor.h:122
unsigned getElemSize() const
returns the size of an element when the structure is viewed as an array.
Definition: Descriptor.h:244
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition: Descriptor.h:254
PrimType getPrimType() const
Definition: Descriptor.h:236