31 "We're assuming 8 bit chars");
60 size_t StackSizeBefore = Stk.
size();
63 if (!
C.interpretCall(FD,
E)) {
71 bool Recursing = !Stk.
empty();
72 size_t StackSizeBefore = Stk.
size();
77 if (Res.isInvalid()) {
94 Result = Res.stealAPValue();
102 bool Recursing = !Stk.
empty();
103 size_t StackSizeBefore = Stk.
size();
106 auto Res =
C.interpretExpr(
E,
false,
108 if (Res.isInvalid()) {
124 Result = Res.stealAPValue();
131 bool Recursing = !Stk.
empty();
132 size_t StackSizeBefore = Stk.
size();
135 bool CheckGlobalInitialized =
138 auto Res =
C.interpretDecl(VD, CheckGlobalInitialized);
139 if (Res.isInvalid()) {
156 Result = Res.stealAPValue();
160template <
typename ResultT>
171 if (!SizeValue.
isInt())
173 uint64_t Size = SizeValue.
getInt().getZExtValue();
175 auto PtrRes =
C.interpretAsPointer(PtrExpr, [&](
const Pointer &Ptr) {
177 if constexpr (std::is_same_v<ResultT, APValue>)
190 Parent.FFDiag(SizeExpr, diag::note_constexpr_access_past_end) <<
AK_Read;
194 if constexpr (std::is_same_v<ResultT, APValue>) {
197 for (uint64_t I = 0; I !=
Size; ++I) {
198 if (std::optional<APValue> ElemVal =
200 Result.getArrayInitializedElt(I) = *ElemVal;
205 assert((std::is_same_v<ResultT, std::string>));
206 if (Size <
Result.max_size())
214 if (PtrRes.isInvalid()) {
228 return evaluateStringRepr(
Parent, SizeExpr, PtrExpr,
Result);
236 return evaluateStringRepr(
Parent, SizeExpr, PtrExpr,
Result);
243 auto PtrRes =
C.interpretAsPointer(
E, [&](
const Pointer &Ptr) {
250 Result = strnlen(reinterpret_cast<const char *>(Ptr.getRawAddress()), N);
257 INT_TYPE_SWITCH(ElemT, {
258 auto Elem = Ptr.elem<T>(I);
268 if (PtrRes.isInvalid()) {
291 llvm_unreachable(
"Unhandled BitWidth");
307 llvm_unreachable(
"Unhandled BitWidth");
312 if (
const auto *BT = dyn_cast<BuiltinType>(
T.getCanonicalType())) {
313 auto Kind = BT->getKind();
314 if (Kind == BuiltinType::Bool)
316 if (Kind == BuiltinType::NullPtr)
318 if (Kind == BuiltinType::BoundMember)
322 if (Kind == BuiltinType::Short)
324 if (Kind == BuiltinType::UShort)
327 if (Kind == BuiltinType::Int)
329 if (Kind == BuiltinType::UInt)
331 if (Kind == BuiltinType::Long)
333 if (Kind == BuiltinType::ULong)
335 if (Kind == BuiltinType::LongLong)
337 if (Kind == BuiltinType::ULongLong)
340 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
342 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
343 Kind == BuiltinType::Char8)
346 if (BT->isSignedInteger())
348 if (BT->isUnsignedInteger())
351 if (BT->isFloatingPoint())
368 if (!
D->isComplete())
374 return classify(AT->getValueType());
376 if (
const auto *DT = dyn_cast<DecltypeType>(
T))
377 return classify(DT->getUnderlyingType());
416 assert(InitialFunction);
435 if (
Base == StaticDecl ||
Base->isDerivedFrom(StaticDecl)) {
443 "Couldn't find an overriding function in the class hierarchy?");
459 bool IsLambdaStaticInvoker =
false;
460 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl);
461 MD && MD->isLambdaStaticInvoker()) {
467 IsLambdaStaticInvoker =
true;
470 assert(ClosureClass->
captures().empty());
473 assert(MD->isFunctionTemplateSpecialization() &&
474 "A generic lambda's static-invoker function must be a "
475 "template specialization");
479 void *InsertPos =
nullptr;
482 assert(CorrespondingCallOpSpecialization);
483 FuncDecl = CorrespondingCallOpSpecialization;
490 llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;
499 ParamTypes.push_back(
PT_Ptr);
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);
521 if (!MD->getParent()->isCompleteDefinition())
523 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
526 MD->
getParent()->getCaptureFields(LC, LTC);
528 if (MD->isStatic() && !LC.empty()) {
541 Descriptor *Desc = P->createDescriptor(PD, PT);
542 ParamDescriptors.insert({
ParamOffset, {PT, Desc}});
545 ParamTypes.push_back(PT);
549 assert(!P->getFunction(FuncDecl));
551 FuncDecl,
ParamOffset, std::move(ParamTypes), std::move(ParamDescriptors),
552 std::move(ParamOffsets), HasThisPointer, HasRVO, IsLambdaStaticInvoker);
562 llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;
569 Descriptor *Desc = P->createDescriptor(PD, PT);
570 ParamDescriptors.insert({
ParamOffset, {PT, Desc}});
573 ParamTypes.push_back(PT);
581 P->createFunction(
E,
ParamOffset, std::move(ParamTypes),
582 std::move(ParamDescriptors), std::move(ParamOffsets),
587 Func->setDefined(
true);
589 Func->setIsFullyCompiled(
true);
597 const auto *FinalDecl = cast<CXXRecordDecl>(BaseDecl);
599 const Record *CurRecord = P->getOrCreateRecord(CurDecl);
600 assert(CurDecl && FinalDecl);
602 unsigned OffsetSum = 0;
606 for (
const Record::Base &B : CurRecord->
bases()) {
607 const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl);
609 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
610 OffsetSum += B.Offset;
616 if (CurDecl == FinalDecl)
620 assert(OffsetSum > 0);
625 return P->getOrCreateRecord(
D);
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;
This file provides some common utility functions for processing Lambda related AST Constructs.
static PrimType integralTypeToPrimTypeS(unsigned BitWidth)
static PrimType integralTypeToPrimTypeU(unsigned BitWidth)
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 ...
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
const TargetInfo & getTargetInfo() const
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.
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.
bool isGenericLambda() const
Determine whether this class describes a generic lambda function object (i.e.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_iterator bases_begin()
capture_const_range captures() const
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
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.
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
param_iterator param_begin()
Declaration of a template function.
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...
Represents a parameter to a function.
A (possibly-)qualified type.
Represents a struct/union/class.
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getShortWidth() const
getShortWidth/Align - Return the size of 'signed short' and 'unsigned short' for this target,...
unsigned getIntWidth() const
getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for this target,...
unsigned getLongLongWidth() const
getLongLongWidth/Align - Return the size of 'signed long long' and 'unsigned long long' for this targ...
unsigned getCharWidth() const
unsigned getLongWidth() const
getLongWidth/Align - Return the size of 'signed long' and 'unsigned long' for this target,...
A template argument list.
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
bool isBlockPointerType() const
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.
bool isFixedPointType() const
Return true if this is a fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
bool isMemberPointerType() const
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
bool isPointerOrReferenceType() const
bool isObjCObjectPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represents a variable declaration or definition.
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)
bool canClassify(QualType T)
static bool isUnevaluatedBuiltin(unsigned ID)
Unevaluated builtins don't get their arguments put on the stack automatically.
unsigned getCharBit() const
Returns CHAR_BIT.
bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result)
Evaluates a toplevel initializer.
bool evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result)
Evalute.
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
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)
OptPrimType classify(QualType T) const
Classifies a type.
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
bool evaluate(State &Parent, const Expr *E, APValue &Result, ConstantExprKind Kind)
Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
void clearTo(size_t NewSize)
void clear()
Clears the stack.
size_t size() const
Returns the size of the stack in bytes.
bool empty() const
Returns whether the stack is empty.
A pointer to a memory block, live or dead.
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
int64_t getIndex() const
Returns the index into an array.
unsigned getNumElems() const
Returns the number of elements.
bool isLive() const
Checks if the pointer is live.
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.
Defines the clang::TargetInfo interface.
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
PrimType
Enumeration of the primitive types of the VM.
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
bool Interpret(InterpState &S)
Interpreter entry point.
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)
@ Result
The result type of a method or function.
for(const auto &A :T->param_types())
const FunctionProtoType * T
Describes a memory block created by an allocation site.
unsigned getElemSize() const
returns the size of an element when the structure is viewed as an array.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
PrimType getPrimType() const