30 this->ShortWidth = Ctx.getTargetInfo().getShortWidth();
31 this->IntWidth = Ctx.getTargetInfo().getIntWidth();
32 this->LongWidth = Ctx.getTargetInfo().getLongWidth();
33 this->LongLongWidth = Ctx.getTargetInfo().getLongLongWidth();
34 assert(Ctx.getTargetInfo().getCharWidth() == 8 &&
35 "We're assuming 8 bit chars");
57 return Run(Parent,
Func);
64 size_t StackSizeBefore = Stk.size();
67 if (!
C.interpretCall(FD, E)) {
69 Stk.clearTo(StackSizeBefore);
75 bool Recursing = !Stk.empty();
76 size_t StackSizeBefore = Stk.size();
81 if (Res.isInvalid()) {
83 Stk.clearTo(StackSizeBefore);
94 Stk.clearTo(StackSizeBefore);
98 Result = Res.stealAPValue();
106 bool Recursing = !Stk.empty();
107 size_t StackSizeBefore = Stk.size();
110 auto Res =
C.interpretExpr(E,
false,
112 if (Res.isInvalid()) {
114 Stk.clearTo(StackSizeBefore);
124 Stk.clearTo(StackSizeBefore);
128 Result = Res.stealAPValue();
135 bool Recursing = !Stk.empty();
136 size_t StackSizeBefore = Stk.size();
139 bool CheckGlobalInitialized =
142 auto Res =
C.interpretDecl(VD,
Init, CheckGlobalInitialized);
143 if (Res.isInvalid()) {
145 Stk.clearTo(StackSizeBefore);
156 Stk.clearTo(StackSizeBefore);
160 Result = Res.stealAPValue();
169 auto Res =
C.interpretDestructor(VD,
Value);
171 if (Res.isInvalid()) {
182template <
typename ResultT>
183bool Context::evaluateStringRepr(
State &Parent,
const Expr *SizeExpr,
193 if (!SizeValue.
isInt())
195 uint64_t Size = SizeValue.
getInt().getZExtValue();
200 if constexpr (std::is_same_v<ResultT, APValue>)
224 if constexpr (std::is_same_v<ResultT, APValue>) {
227 for (uint64_t I = 0; I !=
Size; ++I) {
228 if (std::optional<APValue> ElemVal =
230 Result.getArrayInitializedElt(I) = *ElemVal;
235 assert((std::is_same_v<ResultT, std::string>));
236 if (Size <
Result.max_size())
244 if (PtrRes.isInvalid()) {
258 return evaluateStringRepr(Parent, SizeExpr, PtrExpr,
Result);
266 return evaluateStringRepr(Parent, SizeExpr, PtrExpr,
Result);
289 const char *Chars =
reinterpret_cast<const char *
>(Ptr.
getRawAddress());
290 unsigned Length = strnlen(Chars, N);
294 Result.assign(Chars, Length);
299 for (
unsigned I = Ptr.
getIndex(); I != N; ++I) {
301 auto Elem = Ptr.
elem<T>(I);
304 Result.push_back(
static_cast<char>(Elem));
311 if (PtrRes.isInvalid()) {
323 std::optional<uint64_t>
Result;
344 strnlen(
reinterpret_cast<const char *
>(Ptr.
getRawAddress()), Size);
349 for (
unsigned I = Ptr.
getIndex(); I != N; ++I) {
351 auto Elem = Ptr.
elem<T>(I);
361 if (PtrRes.isInvalid()) {
369std::optional<uint64_t>
374 std::optional<uint64_t>
Result;
383 if (T->isIncompleteType() || T->isFunctionType() ||
384 !T->isConstantSizeType())
395 if (PtrRes.isInvalid()) {
408 !ConditionT || ConditionT !=
PT_Bool) {
414 std::optional<bool>
Result =
445 llvm_unreachable(
"Unhandled BitWidth");
461 llvm_unreachable(
"Unhandled BitWidth");
466 if (
const auto *BT = dyn_cast<BuiltinType>(T.getCanonicalType())) {
467 auto Kind = BT->getKind();
468 if (Kind == BuiltinType::Bool)
470 if (Kind == BuiltinType::NullPtr)
472 if (Kind == BuiltinType::BoundMember)
476 if (Kind == BuiltinType::Short)
478 if (Kind == BuiltinType::UShort)
481 if (Kind == BuiltinType::Int)
483 if (Kind == BuiltinType::UInt)
485 if (Kind == BuiltinType::Long)
487 if (Kind == BuiltinType::ULong)
489 if (Kind == BuiltinType::LongLong)
491 if (Kind == BuiltinType::ULongLong)
494 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
496 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
497 Kind == BuiltinType::Char8)
500 if (BT->isSignedInteger())
502 if (BT->isUnsignedInteger())
505 if (BT->isFloatingPoint())
509 if (T->isPointerOrReferenceType())
512 if (T->isMemberPointerType())
515 if (
const auto *BT = T->getAs<
BitIntType>()) {
521 if (
const auto *D = T->getAsEnumDecl()) {
522 if (!D->isComplete())
524 return classify(D->getIntegerType());
528 return classify(AT->getValueType());
530 if (
const auto *DT = dyn_cast<DecltypeType>(T))
531 return classify(DT->getUnderlyingType());
533 if (
const auto *OBT = T.getCanonicalType()->getAs<OverflowBehaviorType>())
534 return classify(OBT->getUnderlyingType());
536 if (T->isObjCObjectPointerType() || T->isBlockPointerType())
539 if (T->isFixedPointType())
547 return Ctx.getTargetInfo().getCharWidth();
553 return Ctx.getFloatTypeSemantics(T);
569 Frame->~InterpFrame();
581 assert(InitialFunction);
600 if (
Base == StaticDecl ||
Base->isDerivedFrom(StaticDecl)) {
608 "Couldn't find an overriding function in the class hierarchy?");
622 bool IsLambdaStaticInvoker =
false;
623 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl);
624 MD && MD->isLambdaStaticInvoker()) {
630 IsLambdaStaticInvoker =
true;
649 bool HasThisPointer =
false;
650 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) {
651 if (!IsLambdaStaticInvoker) {
652 HasThisPointer = MD->isInstance();
653 if (MD->isImplicitObjectMemberFunction())
660 if (!MD->getParent()->isCompleteDefinition())
662 if (MD->isStatic()) {
663 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
666 MD->
getParent()->getCaptureFields(LC, LTC);
678 unsigned BlockOffset = 0;
679 for (
auto [ParamIndex, PD] : llvm::enumerate(FuncDecl->
parameters())) {
680 bool IsConst = PD->getType().isConstQualified();
681 bool IsVolatile = PD->getType().isVolatileQualified();
684 FuncProto->getParamType(ParamIndex)))
689 Descriptor *Desc = P->createDescriptor(PD, PT,
nullptr, std::nullopt,
693 ParamDescriptors.emplace_back(Desc,
ParamOffset, BlockOffset, PT);
695 BlockOffset +=
sizeof(
Block) + PrimTSize;
699 assert(!P->getFunction(FuncDecl));
701 P->createFunction(FuncDecl,
ParamOffset, std::move(ParamDescriptors),
702 HasThisPointer, HasRVO, IsLambdaStaticInvoker);
715 bool IsConst = PD->getType().isConstQualified();
716 bool IsVolatile = PD->getType().isVolatileQualified();
720 Descriptor *Desc = P->createDescriptor(PD, PT,
nullptr, std::nullopt,
723 ParamDescriptors.emplace_back(Desc,
ParamOffset, ~0u, PT);
732 P->createFunction(E,
ParamOffset, std::move(ParamDescriptors),
737 Func->setDefined(
true);
739 Func->setIsFullyCompiled(
true);
750 const Record *CurRecord = P->getOrCreateRecord(CurDecl);
751 assert(CurDecl && FinalDecl);
753 unsigned OffsetSum = 0;
757 for (
const Record::Base &B : CurRecord->
bases()) {
760 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
761 OffsetSum += B.Offset;
767 if (CurDecl == FinalDecl)
771 assert(OffsetSum > 0);
776 return P->getOrCreateRecord(D);
780 return ID == Builtin::BI__builtin_classify_type ||
781 ID == Builtin::BI__builtin_os_log_format_buffer_size ||
782 ID == Builtin::BI__builtin_constant_p || ID == Builtin::BI__noop;
This file provides some common utility functions for processing Lambda related AST Constructs.
static PrimType integralTypeToPrimTypeS(unsigned BitWidth)
static PrimType integralTypeToPrimTypeU(unsigned BitWidth)
#define INT_TYPE_SWITCH(Expr, B)
static bool isRecordType(QualType T)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
A fixed int type of a specified bitwidth.
Represents a block literal declaration, which is like an unnamed FunctionDecl.
bool hasCaptures() const
True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...
ArrayRef< ParmVarDecl * > parameters() const
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
const BlockDecl * getBlockDecl() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a static or instance method of a struct/union/class.
CXXMethodDecl * getCorrespondingMethodDeclaredInClass(const CXXRecordDecl *RD, bool MayBeBase=false)
Find if RD declares a function that overrides this function, and if so, return it.
Represents a C++ struct/union/class.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_iterator bases_begin()
This represents one expression.
Represents a member of a struct/union/class.
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Represents a function declaration or definition.
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
param_iterator param_begin()
Represents a prototype with parameter type info, e.g.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Represents a parameter to a function.
A (possibly-)qualified type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Represents a struct/union/class.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
const T * getAs() const
Member-template getAs<specific type>'.
Represents a variable declaration or definition.
A memory block, either on the stack or in the heap.
Pointer into the code segment.
Compilation context for expressions.
const LangOptions & getLangOpts() const
Returns the language options.
const Function * getOrCreateObjCBlock(const BlockExpr *E)
~Context()
Cleans up the constexpr VM.
Context(ASTContext &Ctx)
Initialises the constexpr VM.
bool evaluateCharRange(State &Parent, const Expr *SizeExpr, const Expr *PtrExpr, APValue &Result)
std::optional< uint64_t > evaluateStrlen(State &Parent, const Expr *E)
Evalute.
std::optional< bool > evaluateWithSubstitution(State &Parent, const FunctionDecl *Callee, ArrayRef< const Expr * > Args, const Expr *This, const Expr *Condition)
bool evaluateString(State &Parent, const Expr *E, std::string &Result)
Evaluate.
static bool isUnevaluatedBuiltin(unsigned ID)
Unevaluated builtins don't get their arguments put on the stack automatically.
unsigned getCharBit() const
Returns CHAR_BIT.
const llvm::fltSemantics & getFloatSemantics(QualType T) const
Return the floating-point semantics for T.
static bool shouldBeGloballyIndexed(const ValueDecl *VD)
Returns whether we should create a global variable for the given ValueDecl.
void isPotentialConstantExprUnevaluated(State &Parent, const Expr *E, const FunctionDecl *FD)
unsigned collectBaseOffset(const RecordDecl *BaseDecl, const RecordDecl *DerivedDecl) const
bool evaluateDestruction(State &Parent, const VarDecl *VD, APValue Value)
Evaluates the destruction of a variable.
const Record * getRecord(const RecordDecl *D) const
bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FD)
Checks if a function is a potential constant expression.
const Function * getOrCreateFunction(const FunctionDecl *FuncDecl)
ASTContext & getASTContext() const
Returns the AST context.
OptPrimType classify(QualType T) const
Classifies a type.
bool canClassify(QualType T) const
bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result)
Evaluates a toplevel expression as an rvalue.
const CXXMethodDecl * getOverridingFunction(const CXXRecordDecl *DynamicDecl, const CXXRecordDecl *StaticDecl, const CXXMethodDecl *InitialFunction) const
std::optional< uint64_t > tryEvaluateObjectSize(State &Parent, const Expr *E, unsigned Kind)
If.
bool evaluate(State &Parent, const Expr *E, APValue &Result, ConstantExprKind Kind)
Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
bool evaluateAsInitializer(State &Parent, const VarDecl *VD, const Expr *Init, APValue &Result)
Evaluates a toplevel initializer.
Base class for stack frames, shared between VM and walker.
Frame storing local variables.
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
static size_t allocSize(const Function *F)
Returns the number of bytes needed to allocate an InterpFrame for the given function.
void clear()
Clears the stack.
bool empty() const
Returns whether the stack is empty.
InterpFrame * Current
The current frame.
A pointer to a memory block, live or dead.
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
bool isDummy() const
Checks if the pointer points to a dummy value.
int64_t getIndex() const
Returns the index into an array.
bool isConst() const
Checks if an object or a subfield is mutable.
unsigned getNumElems() const
Returns the number of elements.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
bool isLive() const
Checks if the pointer is live.
T & elem(unsigned I) const
Dereferences the element at index I.
bool isZero() const
Checks if the pointer is null.
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
bool isPastEnd() const
Checks if the pointer points past the end of the object.
bool isBlockPointer() const
std::optional< APValue > toRValue(const Context &Ctx, QualType ResultType) const
Converts the pointer to an APValue that is an rvalue.
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
size_t elemSize() const
Returns the element size of the innermost field.
const std::byte * getRawAddress() const
If backed by actual data (i.e.
The program contains and links the bytecode for all functions.
Structure/Class descriptor.
unsigned getNumBases() const
llvm::iterator_range< const_base_iter > bases() const
Interface for the VM to interact with the AST walker's context.
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
Defines the clang::TargetInfo interface.
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
bool This(InterpState &S, CodePtr OpPC)
PrimType
Enumeration of the primitive types of the VM.
bool Init(InterpState &S, CodePtr OpPC)
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
constexpr bool isIntegerType(PrimType T)
UnsignedOrNone evaluateBuiltinObjectSize(const ASTContext &ASTCtx, unsigned Kind, Pointer &Ptr)
bool Interpret(InterpState &S)
Interpreter entry point.
The JSON file list parser is used to communicate input to InstallAPI.
Expr::ConstantExprKind ConstantExprKind
bool isLambdaCallOperator(const CXXMethodDecl *MD)
@ Result
The result type of a method or function.
U cast(CodeGen::Address addr)
Describes a memory block created by an allocation site.
unsigned getElemDataSize() const
Returns the element data size, i.e.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
PrimType getPrimType() const