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>)
211 if (!
Ptr.isLive() || !
Ptr.isInitialized() ||
Ptr.isUnknownSizeArray() ||
216 if (
Ptr.isBlockPointer() &&
217 Ptr.getFieldDesc()->getElemDataSize() != 1 )
219 if (
Ptr.isStringPointer() &&
220 !
Ptr.asStringPointer().getLiteral()->isOrdinary())
223 bool Limited =
false;
224 if (Size >
Ptr.getNumElems()) {
231 if constexpr (std::is_same_v<ResultT, APValue>) {
234 for (uint64_t I = 0; I !=
Size; ++I) {
235 if (std::optional<APValue> ElemVal =
236 Ptr.atIndex(I).toRValue(*
this, CharTy))
237 Result.getArrayInitializedElt(I) = *ElemVal;
242 assert((std::is_same_v<ResultT, std::string>));
243 if (Size <
Result.max_size())
246 const char *
Addr =
reinterpret_cast<const char *
>(
Ptr.getRawAddress());
248 if (
Ptr.isStringPointer())
249 Result.assign(
Addr, Size -
static_cast<unsigned>(Limited));
257 if (PtrRes.isInvalid()) {
271 return evaluateStringRepr(Parent, SizeExpr, PtrExpr,
Result);
279 return evaluateStringRepr(Parent, SizeExpr, PtrExpr,
Result);
289 if (!Ptr.isReadablePointerType())
295 if (Ptr.isDummy() || Ptr.isUnknownSizeArray() || Ptr.isPastEnd())
298 unsigned N = Ptr.getNumElems();
300 if (Ptr.elemSize() == 1 ) {
301 const char *Chars =
reinterpret_cast<const char *
>(Ptr.getRawAddress());
302 if (Ptr.isStringPointer()) {
303 Result.assign(Chars, N - 1);
306 unsigned Length = strnlen(Chars, N);
310 Result.assign(Chars, Length);
315 if (Ptr.isBlockPointer()) {
316 ElemT = Ptr.getFieldDesc()->getPrimType();
320 assert(Ptr.isStringPointer());
321 if (!Ptr.asStringPointer().Decayed)
323 *
classify(Ptr.getType()->getAsArrayTypeUnsafe()->getElementType());
327 for (
unsigned I = Ptr.getIndex(); I != N; ++I) {
329 auto Elem = Ptr.loadElem<
T>(I);
332 Result.push_back(
static_cast<char>(Elem));
339 if (PtrRes.isInvalid()) {
351 std::optional<uint64_t>
Result;
354 if (!Ptr.isReadablePointerType())
360 if (Ptr.isStringPointer()) {
361 const auto *Lit = Ptr.asStringPointer().getLiteral();
362 int64_t
Off = Ptr.getByteOffset();
373 const Descriptor *FieldDesc = Ptr.getFieldDesc();
377 if (Ptr.isDummy() || Ptr.isUnknownSizeArray())
384 unsigned N = Ptr.getNumElems();
385 if (Ptr.elemSize() == 1) {
386 unsigned Size = N - Ptr.getIndex();
388 strnlen(
reinterpret_cast<const char *
>(Ptr.getRawAddress()), Size);
393 for (
unsigned I = Ptr.getIndex(); I != N; ++I) {
395 auto Elem = Ptr.elem<
T>(I);
405 if (PtrRes.isInvalid()) {
413std::optional<uint64_t>
418 std::optional<uint64_t>
Result;
422 const Descriptor *DeclDesc = Ptr.getDeclDesc();
427 if (
T->isIncompleteType() ||
T->isFunctionType() ||
428 !
T->isConstantSizeType())
439 if (PtrRes.isInvalid()) {
452 !ConditionT || ConditionT !=
PT_Bool) {
458 std::optional<bool>
Result =
489 llvm_unreachable(
"Unhandled BitWidth");
505 llvm_unreachable(
"Unhandled BitWidth");
509 T =
T.getCanonicalType();
511 if (
const auto *BT = dyn_cast<BuiltinType>(
T)) {
512 auto Kind = BT->getKind();
513 if (Kind == BuiltinType::Bool)
515 if (Kind == BuiltinType::NullPtr)
517 if (Kind == BuiltinType::BoundMember)
521 if (Kind == BuiltinType::Short)
523 if (Kind == BuiltinType::UShort)
526 if (Kind == BuiltinType::Int)
528 if (Kind == BuiltinType::UInt)
530 if (Kind == BuiltinType::Long)
532 if (Kind == BuiltinType::ULong)
534 if (Kind == BuiltinType::LongLong)
536 if (Kind == BuiltinType::ULongLong)
539 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
541 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
542 Kind == BuiltinType::Char8)
545 if (BT->isSignedInteger())
547 if (BT->isUnsignedInteger())
550 if (BT->isFloatingPoint())
554 if (
T->isPointerOrReferenceType())
557 if (
T->isMemberPointerType())
566 if (
const auto *D =
T->getAsEnumDecl()) {
567 if (!D->isComplete())
569 return classify(D->getIntegerType());
573 return classify(AT->getValueType());
575 if (
const auto *OBT =
T->getAs<OverflowBehaviorType>())
576 return classify(OBT->getUnderlyingType());
578 if (
T->isObjCObjectPointerType() ||
T->isBlockPointerType())
581 if (
T->isFixedPointType())
589 return Ctx.getTargetInfo().getCharWidth();
595 return Ctx.getFloatTypeSemantics(
T);
611 Frame->~InterpFrame();
622 assert(InitialFunction);
641 if (
Base == StaticDecl ||
Base->isDerivedFrom(StaticDecl)) {
649 "Couldn't find an overriding function in the class hierarchy?");
663 bool IsLambdaStaticInvoker =
false;
664 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl);
665 MD && MD->isLambdaStaticInvoker()) {
671 IsLambdaStaticInvoker =
true;
690 bool HasThisPointer =
false;
691 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) {
692 if (!IsLambdaStaticInvoker) {
693 HasThisPointer = MD->isInstance();
694 if (MD->isImplicitObjectMemberFunction())
701 if (!MD->getParent()->isCompleteDefinition())
703 if (MD->isStatic()) {
704 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
707 MD->
getParent()->getCaptureFields(LC, LTC);
719 unsigned BlockOffset = 0;
720 for (
auto [ParamIndex, PD] : llvm::enumerate(FuncDecl->
parameters())) {
721 bool IsConst = PD->getType().isConstQualified();
722 bool IsVolatile = PD->getType().isVolatileQualified();
724 if (PD->isInvalidDecl() ||
726 FuncProto->getParamType(ParamIndex)))
731 Descriptor *Desc = P->createDescriptor(PD, PT,
nullptr, IsConst,
735 ParamDescriptors.emplace_back(Desc,
ParamOffset, BlockOffset, PT);
737 BlockOffset +=
sizeof(
Block) + PrimTSize;
741 assert(!P->getFunction(FuncDecl));
743 P->createFunction(FuncDecl,
ParamOffset, std::move(ParamDescriptors),
744 HasThisPointer, HasRVO, IsLambdaStaticInvoker);
757 bool IsConst = PD->getType().isConstQualified();
758 bool IsVolatile = PD->getType().isVolatileQualified();
762 Descriptor *Desc = P->createDescriptor(PD, PT,
nullptr, IsConst,
765 ParamDescriptors.emplace_back(Desc,
ParamOffset, ~0u, PT);
774 P->createFunction(E,
ParamOffset, std::move(ParamDescriptors),
779 Func->setDefined(
true);
781 Func->setIsFullyCompiled(
true);
792 const Record *CurRecord = P->getOrCreateRecord(CurDecl);
793 assert(CurDecl && FinalDecl);
795 unsigned OffsetSum = 0;
799 for (
const Record::Base &B : CurRecord->
bases()) {
802 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
803 OffsetSum += B.Offset;
809 if (CurDecl == FinalDecl)
813 assert(OffsetSum > 0);
818 return P->getOrCreateRecord(D);
822 return ID == Builtin::BI__builtin_classify_type ||
823 ID == Builtin::BI__builtin_os_log_format_buffer_size ||
824 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.
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.
Top level wrappers for InstallAPI frontend operations.
Expr::ConstantExprKind ConstantExprKind
bool isLambdaCallOperator(const CXXMethodDecl *MD)
@ Result
The result type of a method or function.
OptionalUnsigned< unsigned > UnsignedOrNone
const FunctionProtoType * T
@ Off
Never emit colors regardless of the output stream.
U cast(CodeGen::Address addr)
Describes a memory block created by an allocation site.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
PrimType getPrimType() const