26#include "llvm/ADT/StringExtras.h"
32 llvm::report_fatal_error(
"Interpreter cannot return values");
59#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
60#pragma optimize("", off)
65 [[maybe_unused]]
CodePtr PCBefore = RealPC;
66 size_t StackSizeBefore = S.
Stk.
size();
68 auto SpeculativeInterp = [&S, RealPC]() ->
bool {
74 if (Op == OP_EndSpeculation)
84 llvm_unreachable(
"We didn't see an EndSpeculation op?");
87 if (SpeculativeInterp()) {
90 assert(S.
Stk.
size() == StackSizeBefore);
96 assert(S.
Stk.
size() == StackSizeBefore);
108 assert(*RealPC == *PCBefore);
115 assert(Offset >= ParamSize);
116 RealPC += Offset - ParamSize;
118 [[maybe_unused]]
CodePtr PCCopy = RealPC;
119 assert(PCCopy.
read<
Opcode>() == OP_EndSpeculation);
124#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
125#pragma optimize("", on)
131 S.
FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
154 S.
FFDiag(Loc, diag::note_constexpr_function_param_value_unknown) << D;
164 }
else if (
const auto *VD = dyn_cast<VarDecl>(D)) {
165 if (!VD->getAnyInitializer()) {
169 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
170 S.
Note(VD->getLocation(), diag::note_declared_at);
188 if (
const auto *VarD = dyn_cast<VarDecl>(VD);
189 VarD && VarD->getType().isConstQualified() &&
190 !VarD->getAnyInitializer()) {
201 S.
FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
207 S.
getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
208 : diag::note_constexpr_ltor_non_integral,
220 const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
231 S.
FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
233 diag::note_constexpr_temporary_here);
271 const Expr *
const *Args =
nullptr;
272 unsigned NumArgs = 0;
274 if (
const auto *CE = dyn_cast<CallExpr>(CallSite)) {
275 Args = CE->getArgs();
276 NumArgs = CE->getNumArgs();
277 }
else if (
const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
278 Args = CE->getArgs();
279 NumArgs = CE->getNumArgs();
281 assert(
false &&
"Can't get arguments from that expression type");
283 assert(NumArgs >=
Func->getNumWrittenParams());
284 NumVarArgs = NumArgs - (
Func->getNumWrittenParams() +
286 for (
unsigned I = 0; I != NumVarArgs; ++I) {
287 const Expr *A = Args[NumArgs - 1 - I];
337 while (!
U.isRoot() && !
U.isActive()) {
342 if (
U.getRecord() &&
U.getRecord()->isAnonymousUnion())
362 if (!
U.getFieldDesc()->isUnion())
366 assert(!
C.isActive());
367 const FieldDecl *InactiveField =
C.getField();
368 assert(InactiveField);
371 const Record *R =
U.getRecord();
372 assert(R && R->
isUnion() &&
"Not a union");
375 for (
const Record::Field &F : R->
fields()) {
376 const Pointer &Field =
U.atField(F.Offset);
377 if (Field.isActive()) {
378 ActiveField = Field.getField();
384 S.
FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
385 << AK << InactiveField << !ActiveField << ActiveField;
410 S.
FFDiag(E, diag::note_constexpr_unsized_array_indexed);
422 S.
FFDiag(Src, diag::note_constexpr_access_null) << AK;
431 S.
FFDiag(Src, diag::note_constexpr_access_deleted_object) << AK;
434 S.
FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
458 if (
const auto *VD = dyn_cast_if_present<VarDecl>(S.
EvaluatingDecl);
464 if (
T->isIntegralOrEnumerationType()) {
476 ? diag::note_constexpr_ltor_non_constexpr
477 : diag::note_constexpr_ltor_non_integral,
480 S.
Note(D->getLocation(), diag::note_declared_at);
487 if (
T->isPointerOrReferenceType()) {
513 S.
FFDiag(Loc, diag::note_constexpr_null_subobject)
525 S.
FFDiag(Loc, diag::note_constexpr_access_past_end)
536 S.
FFDiag(Loc, diag::note_constexpr_past_end_subobject)
547 S.
FFDiag(Loc, diag::note_constexpr_past_end_subobject)
559 if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
566 S.
CCEDiag(E, diag::note_constexpr_invalid_downcast)
567 << MostDerivedQT << TargetQT;
573 assert(Ptr.
isLive() &&
"Pointer is not live");
590 S.
FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
595 assert(Ptr.
isLive() &&
"Pointer is not live");
614 S.
FFDiag(Loc, diag::note_constexpr_access_mutable, 1) <<
AK_Read << Field;
615 S.
Note(Field->getLocation(), diag::note_declared_at);
643 Loc = F->getLocation();
647 Loc = VD->getLocation();
652 Loc = E->getExprLoc();
656 diag::note_constexpr_access_volatile_obj, 1)
657 << AK << DiagKind << ND;
658 S.
Note(Loc, diag::note_constexpr_volatile_here) << DiagKind;
675 VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
678 !(S.
getLangOpts().CPlusPlus23 && VD->getType()->isReferenceType())) {
686 S.
FFDiag(Loc, diag::note_constexpr_access_uninit)
692 if (VD->getAnyInitializer()) {
694 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
695 S.
Note(VD->getLocation(), diag::note_declared_at);
729 S.
Note(VD->getLocation(), diag::note_declared_at);
762 diag::note_constexpr_access_volatile_obj, 1)
776 if (!Desc.IsInitialized)
785 diag::note_constexpr_access_volatile_obj, 1)
801 S.
FFDiag(Src, diag::note_constexpr_access_null) << AK;
921 S.
CCEDiag(Loc, diag::note_constexpr_virtual_call);
948 Name ==
"__assert_rtn" || Name ==
"__assert_fail" || Name ==
"_wassert";
951 diag::note_constexpr_assert_failed);
965 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
966 if (CD && CD->isInheritingConstructor()) {
967 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
968 if (!Inherited->isConstexpr())
969 DiagDecl = CD = Inherited;
974 if (CD && CD->getParent()->isInvalidDecl())
980 if (CD && CD->isInheritingConstructor()) {
982 diag::note_constexpr_invalid_inhctor, 1)
983 << CD->getInheritedConstructor().getConstructor()->getParent();
991 if (!IsDefined && !IsExtern && DiagDecl->
isConstexpr() &&
1002 diag::note_constexpr_invalid_function, 1)
1003 << DiagDecl->
isConstexpr() << (bool)CD << DiagDecl;
1007 diag::note_declared_at);
1013 diag::note_invalid_subexpr_in_const_expr);
1022 diag::note_constexpr_depth_limit_exceeded)
1036 bool IsImplicit =
false;
1037 if (
const auto *TE = dyn_cast<CXXThisExpr>(E))
1038 IsImplicit = TE->isImplicit();
1039 S.
FFDiag(E, diag::note_constexpr_this) << IsImplicit;
1048 APFloat::opStatus Status,
FPOptions FPO) {
1055 S.
CCEDiag(E, diag::note_constexpr_float_arithmetic)
1065 if ((Status & APFloat::opInexact) &&
1070 S.
FFDiag(E, diag::note_constexpr_dynamic_rounding);
1074 if ((Status != APFloat::opOK) &&
1077 FPO.getAllowFEnvAccess())) {
1079 S.
FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
1083 if ((Status & APFloat::opStatus::opInvalidOp) &&
1099 S.
CCEDiag(E, diag::note_constexpr_new);
1106 const Expr *NewExpr) {
1107 if (AllocForm == DeleteForm)
1113 S.
FFDiag(E, diag::note_constexpr_new_delete_mismatch)
1114 <<
static_cast<int>(DeleteForm) <<
static_cast<int>(AllocForm)
1116 S.
Note(NewExpr->
getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
1124 if (isa_and_nonnull<CXXNewExpr>(Source))
1127 if (
const auto *CE = dyn_cast_if_present<CallExpr>(Source);
1128 CE && CE->getBuiltinCallee() == Builtin::BI__builtin_operator_new)
1131 if (
const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(Source);
1132 MCE && MCE->getMethodDecl()->
getIdentifier()->isStr(
"allocate"))
1137 S.
FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
1167 S.
FFDiag(E, diag::note_constexpr_modify_global);
1173 const CallExpr *CE,
unsigned ArgSize) {
1176 unsigned Offset = 0;
1178 for (
const Expr *Arg : Args) {
1179 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
1183 S.
CCEDiag(Loc, diag::note_non_null_attribute_failed);
1204 S.
FFDiag(Loc, diag::note_constexpr_double_destroy);
1217 return Call(S, OpPC, DtorFunc, 0);
1240 for (
int I =
static_cast<int>(N) - 1; I >= 0; --I) {
1254 return DD->isVirtual();
1259 bool IsGlobalDelete) {
1265 const Expr *Source =
nullptr;
1266 const Block *BlockToDelete =
nullptr;
1282 BlockToDelete = Ptr.
block();
1286 if (std::optional<DynamicAllocator::Form> AllocForm =
1298 if (!DeleteIsArrayForm && Ptr.
getType() != InitialType &&
1301 diag::note_constexpr_delete_base_nonvirt_dtor)
1302 << InitialType << Ptr.
getType();
1309 S.
FFDiag(Loc, diag::note_constexpr_delete_subobject)
1319 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1324 return DD->isVirtual() ? DD->getOperatorDelete() :
nullptr;
1334 diag::note_constexpr_new_non_replaceable)
1341 assert(BlockToDelete);
1347 if (!Allocator.
deallocate(Source, BlockToDelete, S)) {
1350 S.
FFDiag(Loc, diag::note_constexpr_double_delete);
1370 S.
CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1371 << llvm::toString(
Value, 10) <<
Min.getSExtValue() <<
Max.getSExtValue()
1375 S.
CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1376 << llvm::toString(
Value, 10) <<
Min.getZExtValue() <<
Max.getZExtValue()
1406 S.
FFDiag(E, diag::note_constexpr_nonliteral) << E->
getType();
1408 S.
FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
1435 diag::note_constexpr_access_unreadable_object)
1449 return getField(S, OpPC, Ptr, Off);
1454 return getField(S, OpPC, Ptr, Off);
1459 assert(
Func->isConstructor());
1461 if (
Func->getParentDecl()->isInvalidDecl())
1474 <<
Func->getParentDecl();
1489 S.
FFDiag(E, diag::note_constexpr_modify_global);
1505 uint32_t VarArgSize) {
1506 if (
Func->hasThisPointer()) {
1507 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1517 Func->isLambdaCallOperator())) {
1526 if (!
Func->isFullyCompiled())
1535 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC, VarArgSize);
1544 assert(S.
Current == FrameBefore);
1554 uint32_t VarArgSize) {
1556 auto cleanup = [&]() ->
bool {
1561 if (
Func->hasThisPointer()) {
1562 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1579 Func->isLambdaCallOperator()) {
1580 assert(ThisPtr.
isZero());
1584 if (!
Func->isConstructor() && !
Func->isDestructor() &&
1594 if (
Func->isConstructor() ||
Func->isDestructor())
1598 if (!
Func->isFullyCompiled())
1608 !
Func->isConstructor())
1614 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC, VarArgSize);
1624 if (
Func->isConstructor() ||
Func->isDestructor())
1635 assert(S.
Current == FrameBefore);
1640 uint32_t VarArgSize) {
1641 assert(
Func->hasThisPointer());
1642 assert(
Func->isVirtual());
1643 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1648 if (!
Func->isFullyCompiled())
1654 if (Callee->isPureVirtual()) {
1658 S.
Note(Callee->getLocation(), diag::note_declared_at);
1670 DynamicDecl =
DynamicType->getPointeeCXXRecordDecl();
1674 assert(DynamicDecl);
1680 if (StaticDecl != DynamicDecl) {
1687 Overrider = InitialFunction;
1690 if (Overrider != InitialFunction) {
1703 if (
Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
1712 if (!
Call(S, OpPC,
Func, VarArgSize))
1717 if (Overrider != InitialFunction &&
1719 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
1738 uint32_t BuiltinID) {
1741 if (BuiltinID == Builtin::BI__builtin_operator_new &&
1754 S.
FFDiag(E, diag::note_constexpr_null_callee)
1790 return CallVirt(S, OpPC, F, VarArgSize);
1792 return Call(S, OpPC, F, VarArgSize);
1798 for (
const Record::Field &Fi : R->fields())
1806 for (
unsigned I = 0; I != FieldDesc->getNumElems(); ++I)
1827 for (
const Record::Field &Fi : R->fields())
1836 for (
unsigned I = 0; I != FieldDesc->getNumElems(); ++I)
1851 if (Ptr.isArrayElement())
1865 if (Ptr.isArrayElement())
1873 std::optional<uint64_t> ArraySize) {
1923 NewExpr->getAllocatedType(),
1924 APInt(64,
static_cast<uint64_t
>(*ArraySize),
false),
nullptr,
1927 AllocType = NewExpr->getAllocatedType();
1930 unsigned StorageSize = 1;
1931 unsigned AllocSize = 1;
1932 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AllocType))
1933 AllocSize = CAT->getZExtSize();
1934 if (
const auto *CAT = dyn_cast<ConstantArrayType>(StorageType))
1935 StorageSize = CAT->getZExtSize();
1937 if (AllocSize > StorageSize ||
1941 diag::note_constexpr_placement_new_wrong_type)
1942 << StorageType << AllocType;
1956 if (
const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
1957 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
1959 if (NewExpr->getNumPlacementArgs() > 0) {
1967 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
1969 diag::note_constexpr_new_non_replaceable)
1973 NewExpr->getNumPlacementArgs() == 1 &&
1974 !OperatorNew->isReservedGlobalPlacementOperator()) {
1984 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
1986 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
1988 diag::note_constexpr_new_non_replaceable)
2002 E->
getExprLoc(), diag::warn_fixedpoint_constant_overflow)
2005 S.
CCEDiag(E, diag::note_constexpr_overflow)
2013 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
2019 const Pointer &Ptr,
unsigned BitWidth) {
2026 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
2065 bool TargetIsUCharOrByte) {
2067 if (!HasIndeterminateBits)
2071 if (TargetIsUCharOrByte)
2076 S.
FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
2082 const Type *TypeInfoType) {
2090 if (!P.isBlockPointer())
2094 CanQualType T = P.getDeclPtr().getType()->getCanonicalTypeUnqualified();
2100 Func && (
Func->isConstructor() ||
Func->isDestructor()) &&
2101 P.block() ==
Frame->getThis().block()) {
2103 Func->getParentDecl());
2115 S.
CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
2116 << E->getExprOperand()->getType()
2117 << E->getExprOperand()->getSourceRange();
2130 int32_t IndexDiff = RHSOffset - LHSOffset;
2131 if (IndexDiff < 0) {
2132 if (
static_cast<int32_t
>(LHSLength) < -IndexDiff)
2134 LHSStr = LHSStr.drop_front(-IndexDiff);
2136 if (
static_cast<int32_t
>(RHSLength) < IndexDiff)
2138 RHSStr = RHSStr.drop_front(IndexDiff);
2141 unsigned ShorterCharWidth;
2144 if (LHSLength < RHSLength) {
2157 for (
unsigned NullByte : llvm::seq(ShorterCharWidth)) {
2158 if (Shorter.size() + NullByte >= Longer.size())
2160 if (Longer[Shorter.size() + NullByte])
2163 return Shorter == Longer.take_front(Shorter.size());
2171 if (!Val.singleWord()) {
2172 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
2173 Val.take(NewMemory);
2177 if (!Val.singleWord()) {
2178 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
2179 Val.take(NewMemory);
2183 if (!Val.singleWord()) {
2184 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
2185 Val.take(NewMemory);
2190template <
typename T>
2193 auto &Val = Ptr.
deref<
T>();
2194 if (!Val.singleWord()) {
2195 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
2196 Val.take(NewMemory);
2202 for (
const Record::Field &Fi : R->fields()) {
2203 if (Fi.Desc->isPrimitive()) {
2205 copyPrimitiveMemory<T>(S, Ptr.atField(Fi.Offset));
2215 unsigned NumElems = D->getNumElems();
2219 if (D->isPrimitiveArray()) {
2223 assert(NumElems >= 1);
2225 bool AllSingleWord =
true;
2227 if (!EP.
deref<
T>().singleWord()) {
2229 AllSingleWord =
false;
2234 for (
unsigned I = 1; I != D->getNumElems(); ++I) {
2239 assert(D->isCompositeArray());
2240 for (
unsigned I = 0; I != D->getNumElems(); ++I) {
2261#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
2262#pragma optimize("", off)
2283#include "Opcodes.inc"
2289#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
2290#pragma optimize("", on)
Defines the clang::ASTContext interface.
Defines the clang::Expr interface and subclasses for C++ expressions.
static const FunctionDecl * getVirtualOperatorDelete(QualType T)
static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset)
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK)
static bool BCP(InterpState &S, CodePtr &RealPC, int32_t Offset, PrimType PT)
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset)
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, const ValueDecl *D)
static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset)
static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
static bool RetValue(InterpState &S, CodePtr &Pt)
static StringRef getIdentifier(const Token &Tok)
#define TYPE_SWITCH_ALLOC(Expr, B)
#define TYPE_SWITCH(Expr, B)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
bool hasSimilarType(QualType T1, QualType T2) const
Determine if two types are similar, according to the C++ rules.
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Expr ** getArgs()
Retrieve the call arguments.
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
A reference to a declared variable, function, enum, etc.
bool isInvalidDecl() const
SourceLocation getLocation() const
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getNumNegativeBits() const
Returns the width in bits required to store all the negative enumerators of this enum.
void getValueRange(llvm::APInt &Max, llvm::APInt &Min) const
Calculates the [Min,Max) values the enum can store based on the NumPositiveBits and NumNegativeBits.
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
LangOptions::FPExceptionModeKind getExceptionMode() const
RoundingMode getRoundingMode() const
Represents a member of a struct/union/class.
Represents a function declaration or definition.
QualType getReturnType() const
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
bool isUsableAsGlobalAllocationFunctionInConstantEvaluation(UnsignedOrNone *AlignmentParam=nullptr, bool *IsNothrow=nullptr) const
Determines whether this function is one of the replaceable global allocation functions described in i...
FunctionDecl * getDefinition()
Get the definition for this declaration.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
@ FPE_Ignore
Assume that floating-point exceptions are masked.
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
bool isConstQualified() const
Determine whether this type is const-qualified.
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isAnyComplexType() const
bool isPointerOrReferenceType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
A memory block, either on the stack or in the heap.
unsigned getSize() const
Returns the size of the block.
bool isExtern() const
Checks if the block is extern.
const Descriptor * getDescriptor() const
Returns the block's descriptor.
bool isStatic() const
Checks if the block has static storage duration.
bool isTemporary() const
Checks if the block is temporary.
std::byte * rawData()
Returns a pointer to the raw data, including metadata.
UnsignedOrNone getDeclID() const
Returns the declaration ID.
unsigned getEvalID() const
The Evaluation ID this block was created in.
bool isAccessible() const
Pointer into the code segment.
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
Compilation context for expressions.
unsigned collectBaseOffset(const RecordDecl *BaseDecl, const RecordDecl *DerivedDecl) const
const Function * getOrCreateFunction(const FunctionDecl *FuncDecl)
ASTContext & getASTContext() const
Returns the AST context.
OptPrimType classify(QualType T) const
Classifies a type.
const CXXMethodDecl * getOverridingFunction(const CXXRecordDecl *DynamicDecl, const CXXRecordDecl *StaticDecl, const CXXMethodDecl *InitialFunction) const
unsigned getEvalID() const
Manages dynamic memory allocations done during bytecode interpretation.
bool deallocate(const Expr *Source, const Block *BlockToDelete, InterpState &S)
Deallocate the given source+block combination.
std::optional< Form > getAllocationForm(const Expr *Source) const
Checks whether the allocation done at the given source is an array allocation.
Wrapper around fixed point types.
std::string toDiagnosticString(const ASTContext &Ctx) const
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Base class for stack frames, shared between VM and walker.
const Function * getFunction() const
bool isDestructor() const
Checks if the function is a destructor.
bool isVirtual() const
Checks if the function is virtual.
bool isDefined() const
Checks if the function is defined.
bool hasNonNullAttr() const
bool isConstructor() const
Checks if the function is a constructor.
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
bool hasBody() const
Checks if the function already has a body attached.
bool isThisPointerExplicit() const
unsigned getWrittenArgSize() const
bool isLambdaStaticInvoker() const
Returns whether this function is a lambda static invoker, which we generate custom byte code for.
bool isValid() const
Checks if the function is valid to call.
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Wrapper around numeric types.
static Integral from(ValT Value)
Frame storing local variables.
const Expr * getExpr(CodePtr PC) const
InterpFrame * Caller
The frame of the previous function.
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
CodePtr getRetPC() const
Returns the return address of the frame.
CodePtr getPC() const
Returns the PC of the frame's code start.
SourceLocation getLocation(CodePtr PC) const
const Pointer & getThis() const
Returns the 'this' pointer.
const Function * getFunction() const
Returns the current function.
SourceRange getRange(CodePtr PC) const
bool isRoot() const
Checks if the frame is a root frame - return should quit the interpreter.
unsigned getDepth() const
bool isStdFunction() const
void clearTo(size_t NewSize)
T pop()
Returns the value from the top of the stack and removes it.
void push(Tys &&...Args)
Constructs a value in place on the top of the stack.
size_t size() const
Returns the size of the stack in bytes.
void discard()
Discards the top value from the stack.
T & peek() const
Returns a reference to the value on the top of the stack.
Context & getContext() const
bool noteUndefinedBehavior() override
DynamicAllocator & getAllocator()
Context & Ctx
Interpreter Context.
llvm::SmallVector< const Block * > InitializingBlocks
List of blocks we're currently running either constructors or destructors for.
ASTContext & getASTContext() const override
InterpStack & Stk
Temporary stack.
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
InterpFrame * Current
The current frame.
T allocAP(unsigned BitWidth)
bool inConstantContext() const
Program & P
Reference to the module containing all bytecode.
PrimType value_or(PrimType PT) const
A pointer to a memory block, live or dead.
Pointer narrow() const
Restricts the scope of an array element pointer.
UnsignedOrNone getDeclID() const
Returns the declaration ID.
bool isVolatile() const
Checks if an object or a subfield is volatile.
bool isInitialized() const
Checks if an object was initialized.
bool isStatic() const
Checks if the storage is static.
bool isDynamic() const
Checks if the storage has been dynamically allocated.
bool isZeroSizeArray() const
Checks if the pointer is pointing to a zero-size array.
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
bool isDummy() const
Checks if the pointer points to a dummy value.
bool isExtern() const
Checks if the storage is extern.
int64_t getIndex() const
Returns the index into an array.
bool isActive() const
Checks if the object is active.
bool isConst() const
Checks if an object or a subfield is mutable.
Pointer atField(unsigned Off) const
Creates a pointer to a field.
T & deref() const
Dereferences the pointer, if it's live.
bool isMutable() const
Checks if the field is mutable.
bool isConstInMutable() const
unsigned getNumElems() const
Returns the number of elements.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
void activate() const
Activats a field.
bool isIntegralPointer() const
QualType getType() const
Returns the type of the innermost field.
bool isArrayElement() const
Checks if the pointer points to an array.
bool isLive() const
Checks if the pointer is live.
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
uint64_t getByteOffset() const
Returns the byte offset from the start.
bool isTypeidPointer() const
std::string toDiagnosticString(const ASTContext &Ctx) const
Converts the pointer to a string usable in diagnostics.
bool isZero() const
Checks if the pointer is null.
const IntPointer & asIntPointer() const
bool isRoot() const
Pointer points directly to a block.
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
static bool pointToSameBlock(const Pointer &A, const Pointer &B)
Checks if both given pointers point to the same block.
bool isOnePastEnd() const
Checks if the index is one past end.
uint64_t getIntegerRepresentation() const
const FieldDecl * getField() const
Returns the field information.
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
void startLifetime() const
bool isBlockPointer() const
bool isTemporary() const
Checks if the storage is temporary.
const FunctionPointer & asFunctionPointer() const
SourceLocation getDeclLoc() const
const Block * block() const
bool isFunctionPointer() const
Pointer getDeclPtr() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
bool isBaseClass() const
Checks if a structure is a base class.
size_t elemSize() const
Returns the element size of the innermost field.
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
Lifetime getLifetime() const
void initialize() const
Initializes a field.
const std::byte * getRawAddress() const
If backed by actual data (i.e.
bool isField() const
Checks if the item is a field in an object.
const Record * getRecord() const
Returns the record descriptor of a class.
UnsignedOrNone getCurrentDecl() const
Returns the current declaration ID.
Structure/Class descriptor.
bool isUnion() const
Checks if the record is a union.
const CXXDestructorDecl * getDestructor() const
Returns the destructor of the record, if any.
unsigned getNumVirtualBases() const
llvm::iterator_range< const_field_iter > fields() const
Describes the statement/declaration an opcode was generated from.
bool checkingForUndefinedBehavior() const
Are we checking an expression for overflow?
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
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)
const LangOptions & getLangOpts() const
OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation does not produce a C++11 core constant expression.
bool checkingPotentialConstantExpression() const
Are we checking whether the expression is a potential constant expression?
Defines the clang::TargetInfo interface.
bool arePotentiallyOverlappingStringLiterals(const Pointer &LHS, const Pointer &RHS)
bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off)
static bool CheckCallDepth(InterpState &S, CodePtr OpPC)
static void startLifetimeRecurse(const Pointer &Ptr)
bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
static bool CheckLifetime(InterpState &S, CodePtr OpPC, Lifetime LT, AccessKinds AK)
static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
bool EndLifetimePop(InterpState &S, CodePtr OpPC)
Ends the lifetime of the pop'd pointer.
static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
static bool runRecordDestructor(InterpState &S, CodePtr OpPC, const Pointer &BasePtr, const Descriptor *Desc)
bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType)
bool LT(InterpState &S, CodePtr OpPC)
bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t Offset)
Checks if the dowcast using the given offset is possible with the given pointer.
bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC, DynamicAllocator::Form AllocForm, DynamicAllocator::Form DeleteForm, const Descriptor *D, const Expr *NewExpr)
Diagnose mismatched new[]/delete or new/delete[] pairs.
bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B)
Checks a direct load of a primitive value from a global or local variable.
bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR)
We aleady know the given DeclRefExpr is invalid for some reason, now figure out why and print appropr...
bool EndLifetime(InterpState &S, CodePtr OpPC)
Ends the lifetime of the peek'd pointer.
bool GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr, const Type *TypeInfoType)
Typeid support.
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks the 'this' pointer.
static bool CheckWeak(InterpState &S, CodePtr OpPC, const Block *B)
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Checks if the Descriptor is of a constexpr or const global variable.
bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, unsigned BitWidth)
static bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B)
bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off)
1) Peeks a Pointer 2) Pushes Pointer.atField(Off) on the stack
static bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *CE, unsigned ArgSize)
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
static void finishGlobalRecurse(InterpState &S, const Pointer &Ptr)
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if Ptr is a one-past-the-end pointer.
bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC, const FixedPoint &FP)
static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t Off)
static bool hasVirtualDestructor(QualType T)
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a value can be loaded from a block.
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
bool CheckBCPResult(InterpState &S, const Pointer &Ptr)
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
bool This(InterpState &S, CodePtr OpPC)
bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC)
Checks if dynamic memory allocation is available in the current language mode.
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
bool DiagTypeid(InterpState &S, CodePtr OpPC)
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
This is not used by any of the opcodes directly.
bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits, bool TargetIsUCharOrByte)
static void popArg(InterpState &S, const Expr *Arg)
static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func, const Pointer &ThisPtr)
void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED, const APSInt &Value)
bool StartLifetime(InterpState &S, CodePtr OpPC)
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be stored in a block.
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source, const Pointer &Ptr)
Check the source of the pointer passed to delete/delete[] has actually been heap allocated by us.
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result, APFloat::opStatus Status, FPOptions FPO)
Checks if the result of a floating-point operation is valid in the current context.
PrimType
Enumeration of the primitive types of the VM.
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, uint32_t BuiltinID)
Interpret a builtin function.
bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
constexpr bool needsAlloc()
bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index)
bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK)
Checks if a pointer is a dummy pointer.
bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E, std::optional< uint64_t > ArraySize)
Check if the initializer and storage types of a placement-new expression match.
bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T)
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
static void compileFunction(InterpState &S, const Function *Func)
bool FinishInitGlobal(InterpState &S, CodePtr OpPC)
bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC, const Function *Func)
static void copyPrimitiveMemory(InterpState &S, const Pointer &Ptr, PrimType T)
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm, bool IsGlobalDelete)
bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E)
bool CallBI(InterpState &S, CodePtr OpPC, const CallExpr *CE, uint32_t BuiltinID)
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B)
static bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
bool isConstexprUnknown(const Pointer &P)
bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK)
bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
llvm::BitVector collectNonNullArgs(const FunctionDecl *F, ArrayRef< const Expr * > Args)
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, const CallExpr *CE)
bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
static void endLifetimeRecurse(const Pointer &Ptr)
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
bool Interpret(InterpState &S)
Interpreter entry point.
bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
@ Success
Annotation was successful.
CheckSubobjectKind
The order of this enum is important for diagnostics.
@ Result
The result type of a method or function.
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Describes a memory block created by an allocation site.
unsigned getNumElems() const
Returns the number of elements stored in the block.
bool isPrimitive() const
Checks if the descriptor is of a primitive.
bool hasTrivialDtor() const
Whether variables of this descriptor need their destructor called or not.
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
const ValueDecl * asValueDecl() const
const Decl * asDecl() const
const Descriptor *const ElemDesc
Descriptor of the array element.
unsigned getMetadataSize() const
Returns the size of the metadata.
SourceLocation getLocation() const
QualType getDataType(const ASTContext &Ctx) const
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
const VarDecl * asVarDecl() const
bool isRecord() const
Checks if the descriptor is of a record.
const Record *const ElemRecord
Pointer to the record, if block contains records.
const Expr * asExpr() const
bool isArray() const
Checks if the descriptor is of an array.
Descriptor used for global variables.
Inline descriptor embedded in structures and arrays.