29 this->ShortWidth = Ctx.getTargetInfo().getShortWidth();
30 this->IntWidth = Ctx.getTargetInfo().getIntWidth();
31 this->LongWidth = Ctx.getTargetInfo().getLongWidth();
32 this->LongLongWidth = Ctx.getTargetInfo().getLongLongWidth();
33 assert(Ctx.getTargetInfo().getCharWidth() == 8 &&
34 "We're assuming 8 bit chars");
56 return Run(Parent,
Func);
63 size_t StackSizeBefore = Stk.size();
66 if (!
C.interpretCall(FD, E)) {
68 Stk.clearTo(StackSizeBefore);
74 bool Recursing = !Stk.empty();
75 size_t StackSizeBefore = Stk.size();
80 if (Res.isInvalid()) {
82 Stk.clearTo(StackSizeBefore);
93 Stk.clearTo(StackSizeBefore);
97 Result = Res.stealAPValue();
105 bool Recursing = !Stk.empty();
106 size_t StackSizeBefore = Stk.size();
109 auto Res =
C.interpretExpr(E,
false,
111 if (Res.isInvalid()) {
113 Stk.clearTo(StackSizeBefore);
123 Stk.clearTo(StackSizeBefore);
127 Result = Res.stealAPValue();
134 bool Recursing = !Stk.empty();
135 size_t StackSizeBefore = Stk.size();
138 bool CheckGlobalInitialized =
141 auto Res =
C.interpretDecl(VD,
Init, CheckGlobalInitialized);
142 if (Res.isInvalid()) {
144 Stk.clearTo(StackSizeBefore);
155 Stk.clearTo(StackSizeBefore);
159 Result = Res.stealAPValue();
163template <
typename ResultT>
164bool Context::evaluateStringRepr(
State &Parent,
const Expr *SizeExpr,
174 if (!SizeValue.
isInt())
176 uint64_t Size = SizeValue.
getInt().getZExtValue();
178 auto PtrRes =
C.interpretAsPointer(PtrExpr, [&](
const Pointer &Ptr) {
180 if constexpr (std::is_same_v<ResultT, APValue>)
193 Parent.
FFDiag(SizeExpr, diag::note_constexpr_access_past_end) <<
AK_Read;
197 if constexpr (std::is_same_v<ResultT, APValue>) {
200 for (uint64_t I = 0; I !=
Size; ++I) {
201 if (std::optional<APValue> ElemVal =
203 Result.getArrayInitializedElt(I) = *ElemVal;
208 assert((std::is_same_v<ResultT, std::string>));
209 if (Size <
Result.max_size())
217 if (PtrRes.isInvalid()) {
231 return evaluateStringRepr(Parent, SizeExpr, PtrExpr,
Result);
239 return evaluateStringRepr(Parent, SizeExpr, PtrExpr,
Result);
247 auto PtrRes =
C.interpretAsPointer(E, [&](
const Pointer &Ptr) {
261 const char *Chars =
reinterpret_cast<const char *
>(Ptr.
getRawAddress());
262 unsigned Length = strnlen(Chars, N);
266 Result.assign(Chars, Length);
271 for (
unsigned I = Ptr.
getIndex(); I != N; ++I) {
273 auto Elem = Ptr.
elem<T>(I);
276 Result.push_back(
static_cast<char>(Elem));
283 if (PtrRes.isInvalid()) {
295 std::optional<uint64_t>
Result;
296 auto PtrRes =
C.interpretAsPointer(E, [&](
const Pointer &Ptr) {
311 strnlen(
reinterpret_cast<const char *
>(Ptr.
getRawAddress()), Size);
317 for (
unsigned I = Ptr.
getIndex(); I != N; ++I) {
319 auto Elem = Ptr.
elem<T>(I);
329 if (PtrRes.isInvalid()) {
337std::optional<uint64_t>
342 std::optional<uint64_t>
Result;
344 auto PtrRes =
C.interpretAsPointer(E, [&](
const Pointer &Ptr) {
350 if (T->isIncompleteType() || T->isFunctionType() ||
351 !T->isConstantSizeType())
362 if (PtrRes.isInvalid()) {
385 llvm_unreachable(
"Unhandled BitWidth");
401 llvm_unreachable(
"Unhandled BitWidth");
406 if (
const auto *BT = dyn_cast<BuiltinType>(T.getCanonicalType())) {
407 auto Kind = BT->getKind();
408 if (Kind == BuiltinType::Bool)
410 if (Kind == BuiltinType::NullPtr)
412 if (Kind == BuiltinType::BoundMember)
416 if (Kind == BuiltinType::Short)
418 if (Kind == BuiltinType::UShort)
421 if (Kind == BuiltinType::Int)
423 if (Kind == BuiltinType::UInt)
425 if (Kind == BuiltinType::Long)
427 if (Kind == BuiltinType::ULong)
429 if (Kind == BuiltinType::LongLong)
431 if (Kind == BuiltinType::ULongLong)
434 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
436 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
437 Kind == BuiltinType::Char8)
440 if (BT->isSignedInteger())
442 if (BT->isUnsignedInteger())
445 if (BT->isFloatingPoint())
449 if (T->isPointerOrReferenceType())
452 if (T->isMemberPointerType())
455 if (
const auto *BT = T->getAs<
BitIntType>()) {
461 if (
const auto *D = T->getAsEnumDecl()) {
462 if (!D->isComplete())
464 return classify(D->getIntegerType());
468 return classify(AT->getValueType());
470 if (
const auto *DT = dyn_cast<DecltypeType>(T))
471 return classify(DT->getUnderlyingType());
473 if (T->isObjCObjectPointerType() || T->isBlockPointerType())
476 if (T->isFixedPointType())
484 return Ctx.getTargetInfo().getCharWidth();
490 return Ctx.getFloatTypeSemantics(T);
510 assert(InitialFunction);
529 if (
Base == StaticDecl ||
Base->isDerivedFrom(StaticDecl)) {
537 "Couldn't find an overriding function in the class hierarchy?");
551 bool IsLambdaStaticInvoker =
false;
552 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl);
553 MD && MD->isLambdaStaticInvoker()) {
559 IsLambdaStaticInvoker =
true;
579 bool HasThisPointer =
false;
580 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) {
581 if (!IsLambdaStaticInvoker) {
582 HasThisPointer = MD->isInstance();
583 if (MD->isImplicitObjectMemberFunction()) {
592 if (!MD->getParent()->isCompleteDefinition())
594 if (MD->isStatic()) {
595 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
598 MD->
getParent()->getCaptureFields(LC, LTC);
610 for (
auto [ParamIndex, PD] : llvm::enumerate(FuncDecl->
parameters())) {
611 bool IsConst = PD->getType().isConstQualified();
612 bool IsVolatile = PD->getType().isVolatileQualified();
615 FuncProto->getParamType(ParamIndex)))
620 Descriptor *Desc = P->createDescriptor(PD, PT,
nullptr, std::nullopt,
623 ParamDescriptors.emplace_back(Desc,
ParamOffset, PT);
628 assert(!P->getFunction(FuncDecl));
630 P->createFunction(FuncDecl,
ParamOffset, std::move(ParamDescriptors),
631 HasThisPointer, HasRVO, IsLambdaStaticInvoker);
644 bool IsConst = PD->getType().isConstQualified();
645 bool IsVolatile = PD->getType().isVolatileQualified();
649 Descriptor *Desc = P->createDescriptor(PD, PT,
nullptr, std::nullopt,
652 ParamDescriptors.emplace_back(Desc,
ParamOffset, PT);
661 P->createFunction(E,
ParamOffset, std::move(ParamDescriptors),
666 Func->setDefined(
true);
668 Func->setIsFullyCompiled(
true);
679 const Record *CurRecord = P->getOrCreateRecord(CurDecl);
680 assert(CurDecl && FinalDecl);
682 unsigned OffsetSum = 0;
686 for (
const Record::Base &B : CurRecord->
bases()) {
689 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
690 OffsetSum += B.Offset;
696 if (CurDecl == FinalDecl)
700 assert(OffsetSum > 0);
705 return P->getOrCreateRecord(D);
709 return ID == Builtin::BI__builtin_classify_type ||
710 ID == Builtin::BI__builtin_os_log_format_buffer_size ||
711 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.
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.
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
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.
void clear()
Clears the stack.
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.
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.
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.
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.
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 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