31 this->ShortWidth = Ctx.getTargetInfo().getShortWidth();
32 this->IntWidth = Ctx.getTargetInfo().getIntWidth();
33 this->LongWidth = Ctx.getTargetInfo().getLongWidth();
34 this->LongLongWidth = Ctx.getTargetInfo().getLongLongWidth();
35 assert(Ctx.getTargetInfo().getCharWidth() == 8 &&
36 "We're assuming 8 bit chars");
59 return Run(Settings,
Func);
67 size_t StackSizeBefore = Stk.size();
70 if (!
C.interpretCall(FD, E)) {
72 Stk.clearTo(StackSizeBefore);
79 bool Recursing = !Stk.empty();
80 size_t StackSizeBefore = Stk.size();
83 auto Res =
C.interpretExpr(E);
85 if (Res.isInvalid()) {
87 Stk.clearTo(StackSizeBefore);
98 Stk.clearTo(StackSizeBefore);
102 Result = Res.stealAPValue();
109 bool Recursing = !Stk.empty();
110 size_t StackSizeBefore = Stk.size();
113 auto Res =
C.interpretExpr(E,
false,
115 if (Res.isInvalid()) {
117 Stk.clearTo(StackSizeBefore);
127 Stk.clearTo(StackSizeBefore);
131 Result = Res.stealAPValue();
139 bool Recursing = !Stk.empty();
140 size_t StackSizeBefore = Stk.size();
143 bool CheckGlobalInitialized =
146 auto Res =
C.interpretDecl(VD,
Init, CheckGlobalInitialized);
147 if (Res.isInvalid()) {
149 Stk.clearTo(StackSizeBefore);
160 Stk.clearTo(StackSizeBefore);
164 Result = Res.stealAPValue();
173 auto Res =
C.interpretDestructor(VD,
Value);
175 if (Res.isInvalid()) {
190 C.registerRedecl(VD,
V);
193template <
typename ResultT>
194bool Context::evaluateStringRepr(
const EvalSettings &Settings,
195 const Expr *SizeExpr,
const Expr *PtrExpr,
205 if (!SizeValue.
isInt())
207 uint64_t Size = SizeValue.
getInt().getZExtValue();
212 if constexpr (std::is_same_v<ResultT, APValue>)
223 if (!
Ptr.isLive() || !
Ptr.isInitialized() ||
Ptr.isUnknownSizeArray() ||
228 if (
Ptr.isBlockPointer() &&
229 Ptr.getFieldDesc()->getElemDataSize() != 1 )
231 if (
Ptr.isStringPointer() &&
232 !
Ptr.asStringPointer().getLiteral()->isOrdinary())
235 bool Limited =
false;
236 if (Size >
Ptr.getNumElems()) {
243 if constexpr (std::is_same_v<ResultT, APValue>) {
246 for (uint64_t I = 0; I !=
Size; ++I) {
247 if (std::optional<APValue> ElemVal =
248 Ptr.atIndex(I).toRValue(*
this, CharTy))
249 Result.getArrayInitializedElt(I) = *ElemVal;
254 assert((std::is_same_v<ResultT, std::string>));
255 if (Size <
Result.max_size())
258 const char *
Addr =
reinterpret_cast<const char *
>(
Ptr.getRawAddress());
260 if (
Ptr.isStringPointer())
261 Result.assign(
Addr, Size -
static_cast<unsigned>(Limited));
269 if (PtrRes.isInvalid()) {
279 const Expr *SizeExpr,
const Expr *PtrExpr,
284 return evaluateStringRepr(Settings, SizeExpr, PtrExpr,
Result);
288 const Expr *SizeExpr,
const Expr *PtrExpr,
293 return evaluateStringRepr(Settings, SizeExpr, PtrExpr,
Result);
303 if (!Ptr.isReadablePointerType())
309 if (Ptr.isDummy() || Ptr.isUnknownSizeArray() || Ptr.isPastEnd())
312 unsigned N = Ptr.getNumElems();
314 if (Ptr.elemSize() == 1 ) {
315 const char *Chars =
reinterpret_cast<const char *
>(Ptr.getRawAddress());
316 if (Ptr.isStringPointer()) {
317 Result.assign(Chars, N - 1);
320 unsigned Length = strnlen(Chars, N);
324 Result.assign(Chars, Length);
329 if (Ptr.isBlockPointer()) {
330 ElemT = Ptr.getFieldDesc()->getPrimType();
334 assert(Ptr.isStringPointer());
335 if (!Ptr.asStringPointer().Decayed)
337 *
classify(Ptr.getType()->getAsArrayTypeUnsafe()->getElementType());
341 for (
unsigned I = Ptr.getIndex(); I != N; ++I) {
343 auto Elem = Ptr.loadElem<
T>(I);
346 Result.push_back(
static_cast<char>(Elem));
353 if (PtrRes.isInvalid()) {
366 std::optional<uint64_t>
Result;
369 if (!Ptr.isReadablePointerType())
375 if (Ptr.isStringPointer()) {
376 const auto *Lit = Ptr.asStringPointer().getLiteral();
377 int64_t
Off = Ptr.getByteOffset();
388 const Descriptor *FieldDesc = Ptr.getFieldDesc();
392 if (Ptr.isDummy() || Ptr.isUnknownSizeArray())
399 unsigned N = Ptr.getNumElems();
400 if (Ptr.elemSize() == 1) {
401 unsigned Size = N - Ptr.getIndex();
403 strnlen(
reinterpret_cast<const char *
>(Ptr.getRawAddress()), Size);
408 for (
unsigned I = Ptr.getIndex(); I != N; ++I) {
410 auto Elem = Ptr.elem<
T>(I);
420 if (PtrRes.isInvalid()) {
428std::optional<uint64_t>
430 unsigned Kind,
bool IsDynamic) {
434 std::optional<uint64_t>
Result;
437 QualType T = Ptr.getType().getNonReferenceType();
438 if (
T->isIncompleteType() ||
T->isFunctionType() ||
439 !
T->isConstantSizeType())
443 if (
auto ObjectSize =
451 if (PtrRes.isInvalid()) {
463 !ConditionT || ConditionT !=
PT_Bool) {
469 std::optional<bool>
Result =
500 llvm_unreachable(
"Unhandled BitWidth");
516 llvm_unreachable(
"Unhandled BitWidth");
520 T =
T.getCanonicalType();
522 if (
const auto *BT = dyn_cast<BuiltinType>(
T)) {
523 auto Kind = BT->getKind();
524 if (Kind == BuiltinType::Bool)
526 if (Kind == BuiltinType::NullPtr)
528 if (Kind == BuiltinType::BoundMember)
532 if (Kind == BuiltinType::Short)
534 if (Kind == BuiltinType::UShort)
537 if (Kind == BuiltinType::Int)
539 if (Kind == BuiltinType::UInt)
541 if (Kind == BuiltinType::Long)
543 if (Kind == BuiltinType::ULong)
545 if (Kind == BuiltinType::LongLong)
547 if (Kind == BuiltinType::ULongLong)
550 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
552 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
553 Kind == BuiltinType::Char8)
556 if (BT->isSignedInteger())
558 if (BT->isUnsignedInteger())
561 if (BT->isFloatingPoint())
565 if (
T->isPointerOrReferenceType())
568 if (
T->isMemberPointerType())
577 if (
const auto *D =
T->getAsEnumDecl()) {
578 if (!D->isComplete())
580 return classify(D->getIntegerType());
584 return classify(AT->getValueType());
586 if (
const auto *OBT =
T->getAs<OverflowBehaviorType>())
587 return classify(OBT->getUnderlyingType());
589 if (
T->isObjCObjectPointerType() ||
T->isBlockPointerType())
592 if (
T->isFixedPointType())
600 return Ctx.getTargetInfo().getCharWidth();
606 return Ctx.getFloatTypeSemantics(
T);
622 Frame->~InterpFrame();
633 assert(InitialFunction);
652 if (
Base == StaticDecl ||
Base->isDerivedFrom(StaticDecl)) {
660 "Couldn't find an overriding function in the class hierarchy?");
674 bool IsLambdaStaticInvoker =
false;
675 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl);
676 MD && MD->isLambdaStaticInvoker()) {
682 IsLambdaStaticInvoker =
true;
700 bool HasThisPointer =
false;
701 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) {
702 if (!IsLambdaStaticInvoker) {
703 HasThisPointer = MD->isInstance();
704 if (MD->isImplicitObjectMemberFunction())
711 if (!MD->getParent()->isCompleteDefinition())
713 if (MD->isStatic()) {
714 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
717 MD->
getParent()->getCaptureFields(LC, LTC);
732 unsigned BlockOffset = 0;
733 for (
auto [ParamIndex, PD] : llvm::enumerate(FuncDecl->
parameters())) {
734 bool IsConst = PD->getType().isConstQualified();
735 bool IsVolatile = PD->getType().isVolatileQualified();
737 if (PD->isInvalidDecl() ||
739 FuncProto->getParamType(ParamIndex)))
744 Descriptor *Desc = P->createDescriptor(PD, PT,
nullptr, IsConst,
748 ParamDescriptors.emplace_back(Desc,
ParamOffset, BlockOffset, PT);
750 BlockOffset +=
sizeof(
Block) + PrimTSize;
754 assert(!P->getFunction(FuncDecl));
756 P->createFunction(FuncDecl,
ParamOffset, std::move(ParamDescriptors),
757 HasThisPointer, HasRVO, IsLambdaStaticInvoker);
770 bool IsConst = PD->getType().isConstQualified();
771 bool IsVolatile = PD->getType().isVolatileQualified();
775 Descriptor *Desc = P->createDescriptor(PD, PT,
nullptr, IsConst,
778 ParamDescriptors.emplace_back(Desc,
ParamOffset, ~0u, PT);
787 P->createFunction(E,
ParamOffset, std::move(ParamDescriptors),
792 Func->setDefined(
true);
794 Func->setIsFullyCompiled(
true);
805 const Record *CurRecord = P->getOrCreateRecord(CurDecl);
806 assert(CurDecl && FinalDecl);
808 unsigned OffsetSum = 0;
812 for (
const Record::Base &B : CurRecord->
bases()) {
815 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
816 OffsetSum += B.Offset;
822 if (CurDecl == FinalDecl)
826 assert(OffsetSum > 0);
831 return P->getOrCreateRecord(D);
835 return ID == Builtin::BI__builtin_classify_type ||
836 ID == Builtin::BI__builtin_os_log_format_buffer_size ||
837 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()
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
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.
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.
std::optional< uint64_t > tryEvaluateObjectSize(const EvalSettings &Settings, const Expr *E, unsigned Kind, bool IsDynamic)
If.
const LangOptions & getLangOpts() const
Returns the language options.
void registerRedecl(const VarDecl *VD, const APValue &V)
const Function * getOrCreateObjCBlock(const BlockExpr *E)
bool evaluateString(const EvalSettings &Settings, const Expr *E, std::string &Result)
Evaluate.
~Context()
Cleans up the constexpr VM.
bool evaluateDestruction(const EvalSettings &Settings, const VarDecl *VD, APValue Value)
Evaluates the destruction of a variable.
Context(ASTContext &Ctx)
Initialises the constexpr VM.
bool isPotentialConstantExpr(const EvalSettings &Settings, const FunctionDecl *FD)
Checks if a function is a potential constant expression.
static bool isUnevaluatedBuiltin(unsigned ID)
Unevaluated builtins don't get their arguments put on the stack automatically.
unsigned getCharBit() const
Returns CHAR_BIT.
std::optional< bool > evaluateWithSubstitution(const EvalSettings &Settings, const FunctionDecl *Callee, ArrayRef< const Expr * > Args, const Expr *This, const Expr *Condition)
bool evaluate(const EvalSettings &Settings, const Expr *E, APValue &Result)
Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
const llvm::fltSemantics & getFloatSemantics(QualType T) const
Return the floating-point semantics for T.
bool evaluateAsInitializer(const EvalSettings &Settings, const VarDecl *VD, const Expr *Init, APValue &Result)
Evaluates a toplevel initializer.
unsigned collectBaseOffset(const RecordDecl *BaseDecl, const RecordDecl *DerivedDecl) const
const Record * getRecord(const RecordDecl *D) const
bool evaluateAsRValue(const EvalSettings &Settings, const Expr *E, APValue &Result)
Evaluates a toplevel expression as an rvalue.
const Function * getOrCreateFunction(const FunctionDecl *FuncDecl)
ASTContext & getASTContext() const
Returns the AST context.
OptPrimType classify(QualType T) const
Classifies a type.
bool evaluateCharRange(const EvalSettings &Settings, const Expr *SizeExpr, const Expr *PtrExpr, APValue &Result)
std::optional< uint64_t > evaluateStrlen(const EvalSettings &Settings, const Expr *E)
Evalute.
bool canClassify(QualType T) const
const CXXMethodDecl * getOverridingFunction(const CXXRecordDecl *DynamicDecl, const CXXRecordDecl *StaticDecl, const CXXMethodDecl *InitialFunction) const
void isPotentialConstantExprUnevaluated(const EvalSettings &Settings, const Expr *E, const FunctionDecl *FD)
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.
UnsignedOrNone evaluateBuiltinObjectSize(const ASTContext &ASTCtx, unsigned Kind, Pointer &Ptr, const Expr *E, bool IsDynamic)
Evaluate __builtin_object_size or __builtin_dynamic_object_size for the given pointer and Kind.
constexpr bool isIntegerType(PrimType T)
bool Interpret(InterpState &S)
Interpreter entry point.
Top level wrappers for InstallAPI frontend operations.
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)
EvalStatus is a struct with detailed info about an evaluation in progress.
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