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();
114 auto Res =
C.interpretExpr(E,
false,
116 ConstantExprKind::Initializer);
117 if (Res.isInvalid()) {
119 Stk.clearTo(StackSizeBefore);
129 Stk.clearTo(StackSizeBefore);
133 Result = Res.stealAPValue();
141 bool Recursing = !Stk.empty();
142 size_t StackSizeBefore = Stk.size();
145 bool CheckGlobalInitialized =
148 auto Res =
C.interpretDecl(VD,
Init, CheckGlobalInitialized);
149 if (Res.isInvalid()) {
151 Stk.clearTo(StackSizeBefore);
162 Stk.clearTo(StackSizeBefore);
166 Result = Res.stealAPValue();
175 auto Res =
C.interpretDestructor(VD,
Value);
177 if (Res.isInvalid()) {
192 C.registerRedecl(VD,
V);
195template <
typename ResultT>
196bool Context::evaluateStringRepr(
const EvalSettings &Settings,
197 const Expr *SizeExpr,
const Expr *PtrExpr,
207 if (!SizeValue.
isInt())
209 uint64_t Size = SizeValue.
getInt().getZExtValue();
214 if constexpr (std::is_same_v<ResultT, APValue>)
225 if (!
Ptr.isLive() || !
Ptr.isInitialized() ||
Ptr.isUnknownSizeArray() ||
230 if (
Ptr.isBlockPointer() &&
231 Ptr.getFieldDesc()->getElemDataSize() != 1 )
233 if (
Ptr.isStringPointer() &&
234 !
Ptr.asStringPointer().getLiteral()->isOrdinary())
237 bool Limited =
false;
238 if (Size >
Ptr.getNumElems()) {
245 if constexpr (std::is_same_v<ResultT, APValue>) {
248 for (uint64_t I = 0; I !=
Size; ++I) {
249 if (std::optional<APValue> ElemVal =
250 Ptr.atIndex(I).toRValue(*
this, CharTy))
251 Result.getArrayInitializedElt(I) = *ElemVal;
256 assert((std::is_same_v<ResultT, std::string>));
257 if (Size <
Result.max_size())
260 const char *
Addr =
reinterpret_cast<const char *
>(
Ptr.getRawAddress());
262 if (
Ptr.isStringPointer())
263 Result.assign(
Addr, Size -
static_cast<unsigned>(Limited));
271 if (PtrRes.isInvalid()) {
281 const Expr *SizeExpr,
const Expr *PtrExpr,
286 return evaluateStringRepr(Settings, SizeExpr, PtrExpr,
Result);
290 const Expr *SizeExpr,
const Expr *PtrExpr,
295 return evaluateStringRepr(Settings, SizeExpr, PtrExpr,
Result);
305 if (!Ptr.isReadablePointerType())
311 if (Ptr.isDummy() || Ptr.isUnknownSizeArray() || Ptr.isPastEnd())
314 unsigned N = Ptr.getNumElems();
316 if (Ptr.elemSize() == 1 ) {
317 const char *Chars =
reinterpret_cast<const char *
>(Ptr.getRawAddress());
318 if (Ptr.isStringPointer()) {
319 Result.assign(Chars, N - 1);
322 unsigned Length = strnlen(Chars, N);
326 Result.assign(Chars, Length);
331 if (Ptr.isBlockPointer()) {
332 ElemT = Ptr.getFieldDesc()->getPrimType();
336 assert(Ptr.isStringPointer());
337 if (!Ptr.asStringPointer().Decayed)
339 *
classify(Ptr.getType()->getAsArrayTypeUnsafe()->getElementType());
343 for (
unsigned I = Ptr.getIndex(); I != N; ++I) {
345 auto Elem = Ptr.loadElem<
T>(I);
348 Result.push_back(
static_cast<char>(Elem));
355 if (PtrRes.isInvalid()) {
368 std::optional<uint64_t>
Result;
371 if (!Ptr.isReadablePointerType())
377 if (Ptr.isStringPointer()) {
378 const auto *Lit = Ptr.asStringPointer().getLiteral();
379 int64_t
Off = Ptr.getByteOffset();
390 const Descriptor *FieldDesc = Ptr.getFieldDesc();
394 if (Ptr.isDummy() || Ptr.isUnknownSizeArray())
401 unsigned N = Ptr.getNumElems();
402 if (Ptr.elemSize() == 1) {
403 unsigned Size = N - Ptr.getIndex();
405 strnlen(
reinterpret_cast<const char *
>(Ptr.getRawAddress()), Size);
410 for (
unsigned I = Ptr.getIndex(); I != N; ++I) {
412 auto Elem = Ptr.elem<
T>(I);
422 if (PtrRes.isInvalid()) {
430std::optional<uint64_t>
432 unsigned Kind,
bool IsDynamic) {
436 std::optional<uint64_t>
Result;
439 QualType T = Ptr.getType().getNonReferenceType();
440 if (
T->isIncompleteType() ||
T->isFunctionType() ||
441 !
T->isConstantSizeType())
445 if (
auto ObjectSize =
453 if (PtrRes.isInvalid()) {
465 !ConditionT || ConditionT !=
PT_Bool) {
471 std::optional<bool>
Result =
502 llvm_unreachable(
"Unhandled BitWidth");
518 llvm_unreachable(
"Unhandled BitWidth");
522 T =
T.getCanonicalType();
524 if (
const auto *BT = dyn_cast<BuiltinType>(
T)) {
525 auto Kind = BT->getKind();
526 if (Kind == BuiltinType::Bool)
528 if (Kind == BuiltinType::NullPtr)
530 if (Kind == BuiltinType::BoundMember)
534 if (Kind == BuiltinType::Short)
536 if (Kind == BuiltinType::UShort)
539 if (Kind == BuiltinType::Int)
541 if (Kind == BuiltinType::UInt)
543 if (Kind == BuiltinType::Long)
545 if (Kind == BuiltinType::ULong)
547 if (Kind == BuiltinType::LongLong)
549 if (Kind == BuiltinType::ULongLong)
552 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
554 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
555 Kind == BuiltinType::Char8)
558 if (BT->isSignedInteger())
560 if (BT->isUnsignedInteger())
563 if (BT->isFloatingPoint())
567 if (
T->isPointerOrReferenceType())
570 if (
T->isMemberPointerType())
579 if (
const auto *D =
T->getAsEnumDecl()) {
580 if (!D->isComplete())
582 return classify(D->getIntegerType());
586 return classify(AT->getValueType());
588 if (
const auto *OBT =
T->getAs<OverflowBehaviorType>())
589 return classify(OBT->getUnderlyingType());
591 if (
T->isObjCObjectPointerType() ||
T->isBlockPointerType())
594 if (
T->isFixedPointType())
597 if (
T->isMetaInfoType())
605 return Ctx.getTargetInfo().getCharWidth();
611 return Ctx.getFloatTypeSemantics(
T);
627 Frame->~InterpFrame();
638 assert(InitialFunction);
657 if (
Base == StaticDecl ||
Base->isDerivedFrom(StaticDecl)) {
665 "Couldn't find an overriding function in the class hierarchy?");
679 bool IsLambdaStaticInvoker =
false;
680 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl);
681 MD && MD->isLambdaStaticInvoker()) {
687 IsLambdaStaticInvoker =
true;
705 bool HasThisPointer =
false;
706 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) {
707 if (!IsLambdaStaticInvoker) {
708 HasThisPointer = MD->isInstance();
709 if (MD->isImplicitObjectMemberFunction())
716 if (!MD->getParent()->isCompleteDefinition())
718 if (MD->isStatic()) {
719 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
722 MD->
getParent()->getCaptureFields(LC, LTC);
737 unsigned BlockOffset = 0;
738 for (
auto [ParamIndex, PD] : llvm::enumerate(FuncDecl->
parameters())) {
739 bool IsConst = PD->getType().isConstQualified();
740 bool IsVolatile = PD->getType().isVolatileQualified();
742 if (PD->isInvalidDecl() ||
744 FuncProto->getParamType(ParamIndex)))
749 Descriptor *Desc = P->createDescriptor(PD, PT,
nullptr, IsConst,
753 ParamDescriptors.emplace_back(Desc,
ParamOffset, BlockOffset, PT);
755 BlockOffset +=
sizeof(
Block) + PrimTSize;
759 assert(!P->getFunction(FuncDecl));
761 P->createFunction(FuncDecl,
ParamOffset, std::move(ParamDescriptors),
762 HasThisPointer, HasRVO, IsLambdaStaticInvoker);
775 bool IsConst = PD->getType().isConstQualified();
776 bool IsVolatile = PD->getType().isVolatileQualified();
780 Descriptor *Desc = P->createDescriptor(PD, PT,
nullptr, IsConst,
783 ParamDescriptors.emplace_back(Desc,
ParamOffset, ~0u, PT);
792 P->createFunction(E,
ParamOffset, std::move(ParamDescriptors),
797 Func->setDefined(
true);
799 Func->setIsFullyCompiled(
true);
810 const Record *CurRecord = P->getOrCreateRecord(CurDecl);
811 assert(CurDecl && FinalDecl);
813 unsigned OffsetSum = 0;
817 for (
const Record::Base &B : CurRecord->
bases()) {
820 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
821 OffsetSum += B.Offset;
827 if (CurDecl == FinalDecl)
831 assert(OffsetSum > 0);
836 return P->getOrCreateRecord(D);
840 return ID == Builtin::BI__builtin_classify_type ||
841 ID == Builtin::BI__builtin_os_log_format_buffer_size ||
842 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
const ConstantExprKind ConstexprKind