25#include "llvm/ADT/StringExtras.h"
31 llvm::report_fatal_error(
"Interpreter cannot return values");
44 if (S.Stk.pop<
bool>()) {
51 if (!S.Stk.pop<
bool>()) {
60 S.FFDiag(
E, diag::note_constexpr_var_init_unknown, 1) << VD;
70 if (isa<ParmVarDecl>(
D)) {
72 S.FFDiag(
E, diag::note_constexpr_function_param_value_unknown) <<
D;
80 if (!
D->getType().isConstQualified()) {
82 }
else if (
const auto *VD = dyn_cast<VarDecl>(
D)) {
83 if (!VD->getAnyInitializer()) {
87 S.FFDiag(
Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
88 S.Note(VD->getLocation(), diag::note_declared_at);
103 if (
const auto *VarD = dyn_cast<VarDecl>(VD);
104 VarD && VarD->getType().isConstQualified() &&
105 !VarD->getAnyInitializer()) {
112 if (isa<ObjCIvarDecl>(VD))
116 S.FFDiag(
Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
122 S.
getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
123 : diag::note_constexpr_ltor_non_integral,
139 while (!
U.isRoot() &&
U.inUnion() && !
U.isActive()) {
147 const FieldDecl *InactiveField =
C.getField();
148 assert(InactiveField);
162 if (!
U.getFieldDesc()->isUnion())
166 const Record *R =
U.getRecord();
167 assert(R && R->
isUnion() &&
"Not a union");
170 for (
const Record::Field &F : R->
fields()) {
171 const Pointer &Field =
U.atField(F.Offset);
172 if (Field.isActive()) {
173 ActiveField = Field.getField();
179 S.FFDiag(
Loc, diag::note_constexpr_access_inactive_union_member)
180 << AK << InactiveField << !ActiveField << ActiveField;
190 const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
198 if (!MTE->isUsableInConstantExpressions(S.
getASTContext()) &&
201 S.FFDiag(
E, diag::note_constexpr_access_static_temporary, 1) << AK;
202 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
214 if (S.P.getCurrentDecl() == ID)
217 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
235 if (
Func->isUnevaluatedBuiltin())
240 if (
unsigned BID =
Func->getBuiltinID();
243 cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
244 for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
245 const Expr *A = CE->getArg(I);
251 if (S.Current->Caller &&
Func->isVariadic()) {
256 const Expr *
const *Args =
nullptr;
257 unsigned NumArgs = 0;
258 const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
259 if (
const auto *CE = dyn_cast<CallExpr>(CallSite)) {
260 Args = CE->getArgs();
261 NumArgs = CE->getNumArgs();
262 }
else if (
const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
263 Args = CE->getArgs();
264 NumArgs = CE->getNumArgs();
266 assert(
false &&
"Can't get arguments from that expression type");
268 assert(NumArgs >=
Func->getNumWrittenParams());
269 NumVarArgs = NumArgs - (
Func->getNumWrittenParams() +
270 isa<CXXOperatorCallExpr>(CallSite));
271 for (
unsigned I = 0; I != NumVarArgs; ++I) {
272 const Expr *A = Args[NumArgs - 1 - I];
291 if (!S.checkingPotentialConstantExpression() && S.
getLangOpts().CPlusPlus) {
302 S.FFDiag(
E, diag::note_constexpr_unsized_array_indexed);
309 const auto &Src = S.Current->getSource(OpPC);
312 S.FFDiag(Src, diag::note_constexpr_null_subobject) <<
CSK_Field;
314 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
320 const auto &Src = S.Current->getSource(OpPC);
323 S.FFDiag(Src, diag::note_constexpr_access_deleted_object) << AK;
324 }
else if (!S.checkingPotentialConstantExpression()) {
326 S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
329 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
331 S.Note(Ptr.
getDeclLoc(), diag::note_declared_at);
344 if (!
D || !
D->hasGlobalStorage())
347 if (
D == S.EvaluatingDecl)
350 if (
D->isConstexpr())
356 if (
const auto *VD = dyn_cast_if_present<VarDecl>(S.EvaluatingDecl);
372 S.CCEDiag(S.Current->getLocation(OpPC),
374 ? diag::note_constexpr_ltor_non_constexpr
375 : diag::note_constexpr_ltor_non_integral,
380 S.CCEDiag(S.Current->getLocation(OpPC));
409 S.FFDiag(
Loc, diag::note_constexpr_null_subobject)
410 << CSK << S.Current->getRange(OpPC);
421 S.FFDiag(
Loc, diag::note_constexpr_access_past_end)
422 << AK << S.Current->getRange(OpPC);
432 S.FFDiag(
Loc, diag::note_constexpr_past_end_subobject)
433 << CSK << S.Current->getRange(OpPC);
443 S.FFDiag(
Loc, diag::note_constexpr_past_end_subobject)
444 << CSK << S.Current->getRange(OpPC);
455 if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
458 const auto *
E = cast<CastExpr>(S.Current->getExpr(OpPC));
462 S.CCEDiag(
E, diag::note_constexpr_invalid_downcast)
463 << MostDerivedQT << TargetQT;
469 assert(Ptr.
isLive() &&
"Pointer is not live");
477 if (S.Current->getFunction()) {
480 Func && (
Func->isConstructor() ||
Func->isDestructor()) &&
492 S.FFDiag(
Loc, diag::note_constexpr_modify_const_type) << Ty;
497 assert(Ptr.
isLive() &&
"Pointer is not live");
509 S.FFDiag(
Loc, diag::note_constexpr_access_mutable, 1) <<
AK_Read << Field;
510 S.Note(Field->getLocation(), diag::note_declared_at);
529 S.FFDiag(
Loc, diag::note_constexpr_access_volatile_type) << AK << PtrType;
543 VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
545 if (VD->getAnyInitializer()) {
546 S.FFDiag(
Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
547 S.Note(VD->getLocation(), diag::note_declared_at);
554 if (!S.checkingPotentialConstantExpression()) {
555 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
556 << AK <<
true << S.Current->getRange(OpPC);
567 if ((!VD->hasConstantInitialization() &&
568 VD->mightBeUsableInConstantExpressions(S.
getASTContext())) ||
572 S.FFDiag(
Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
573 S.Note(VD->getLocation(), diag::note_declared_at);
584 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_var_init_weak)
586 S.Note(VD->getLocation(), diag::note_declared_at);
685 S.CCEDiag(
Loc, diag::note_constexpr_virtual_call);
707 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
708 if (CD && CD->isInheritingConstructor()) {
709 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
710 if (!Inherited->isConstexpr())
711 DiagDecl = CD = Inherited;
717 if (CD && CD->isInheritingConstructor()) {
718 S.FFDiag(
Loc, diag::note_constexpr_invalid_inhctor, 1)
719 << CD->getInheritedConstructor().getConstructor()->getParent();
720 S.Note(DiagDecl->
getLocation(), diag::note_declared_at);
727 S.checkingPotentialConstantExpression())
736 S.FFDiag(
Loc, diag::note_constexpr_invalid_function, 1)
741 diag::note_declared_at);
743 S.Note(DiagDecl->
getLocation(), diag::note_declared_at);
746 S.FFDiag(
Loc, diag::note_invalid_subexpr_in_const_expr);
753 if ((S.Current->getDepth() + 1) > S.
getLangOpts().ConstexprCallDepth) {
754 S.FFDiag(S.Current->getSource(OpPC),
755 diag::note_constexpr_depth_limit_exceeded)
769 bool IsImplicit =
false;
770 if (
const auto *
E = dyn_cast_if_present<CXXThisExpr>(
Loc.asExpr()))
771 IsImplicit =
E->isImplicit();
774 S.FFDiag(
Loc, diag::note_constexpr_this) << IsImplicit;
785 S.FFDiag(
E, diag::note_constexpr_pure_virtual_call, 1) << MD;
791 APFloat::opStatus Status,
FPOptions FPO) {
798 S.CCEDiag(
E, diag::note_constexpr_float_arithmetic)
799 <<
true << S.Current->getRange(OpPC);
800 return S.noteUndefinedBehavior();
805 if (S.inConstantContext())
808 if ((Status & APFloat::opInexact) &&
813 S.FFDiag(
E, diag::note_constexpr_dynamic_rounding);
817 if ((Status != APFloat::opOK) &&
820 FPO.getAllowFEnvAccess())) {
822 S.FFDiag(
E, diag::note_constexpr_float_arithmetic_strict);
826 if ((Status & APFloat::opStatus::opInvalidOp) &&
842 S.CCEDiag(
E, diag::note_constexpr_new);
849 const Expr *NewExpr) {
850 if (AllocForm == DeleteForm)
858 QualType ElemQT =
D->getType()->getPointeeType();
860 ElemQT,
APInt(64,
static_cast<uint64_t
>(
D->getNumElems()),
false),
863 TypeToDiagnose =
D->getType()->getPointeeType();
866 S.FFDiag(
E, diag::note_constexpr_new_delete_mismatch)
867 <<
static_cast<int>(DeleteForm) <<
static_cast<int>(AllocForm)
869 S.Note(NewExpr->
getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
878 if (isa_and_nonnull<CXXNewExpr>(Source))
880 if (
const CallExpr *CE = dyn_cast_if_present<CallExpr>(Source);
886 S.FFDiag(
Loc, diag::note_constexpr_delete_not_heap_alloc)
890 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
892 S.Note(Ptr.
getDeclLoc(), diag::note_declared_at);
919 S.FFDiag(
E, diag::note_constexpr_modify_global);
925 const CallExpr *CE,
unsigned ArgSize) {
930 for (
const Expr *Arg : Args) {
931 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
935 S.CCEDiag(
Loc, diag::note_non_null_attribute_failed);
960 S.FFDiag(
Loc, diag::note_constexpr_double_destroy);
967 const Function *DtorFunc = S.getContext().getOrCreateFunction(Dtor);
972 if (!
Call(S, OpPC, DtorFunc, 0))
992 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
1006 return DD->isVirtual();
1011 bool IsGlobalDelete) {
1015 const Expr *Source =
nullptr;
1016 const Block *BlockToDelete =
nullptr;
1033 if (!DeleteIsArrayForm && Ptr.
getType() != InitialType &&
1035 S.FFDiag(S.Current->getSource(OpPC),
1036 diag::note_constexpr_delete_base_nonvirt_dtor)
1037 << InitialType << Ptr.
getType();
1043 S.FFDiag(
Loc, diag::note_constexpr_delete_subobject)
1049 BlockToDelete = Ptr.
block();
1057 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1061 return DD->isVirtual() ? DD->getOperatorDelete() :
nullptr;
1069 S.FFDiag(S.Current->getSource(OpPC),
1070 diag::note_constexpr_new_non_replaceable)
1071 << isa<CXXMethodDecl>(VirtualDelete) << VirtualDelete;
1077 assert(BlockToDelete);
1085 std::optional<DynamicAllocator::Form> AllocForm =
1086 Allocator.getAllocationForm(Source);
1088 if (!Allocator.deallocate(Source, BlockToDelete, S)) {
1091 S.FFDiag(
Loc, diag::note_constexpr_double_delete);
1108 if (S.EvaluatingDecl && !S.EvaluatingDecl->isConstexpr())
1117 S.CCEDiag(
Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1118 << llvm::toString(
Value, 10) <<
Min.getSExtValue() <<
Max.getSExtValue()
1122 S.CCEDiag(
Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1123 << llvm::toString(
Value, 10) <<
Min.getZExtValue() <<
Max.getZExtValue()
1146 if (S.Current->getFunction() && S.Current->getFunction()->isConstructor() &&
1147 S.Current->getThis().getDeclDesc()->asDecl() == S.EvaluatingDecl) {
1151 const Expr *
E = S.Current->getExpr(OpPC);
1153 S.FFDiag(
E, diag::note_constexpr_nonliteral) <<
E->
getType();
1155 S.FFDiag(
E, diag::note_invalid_subexpr_in_const_expr);
1161 if (S.
getLangOpts().CPlusPlus && S.inConstantContext() &&
1183 S.FFDiag(S.Current->getSource(OpPC),
1184 diag::note_constexpr_access_unreadable_object)
1197 const auto &Ptr = S.Stk.peek<
Pointer>();
1198 return getField(S, OpPC, Ptr, Off);
1202 const auto &Ptr = S.Stk.pop<
Pointer>();
1203 return getField(S, OpPC, Ptr, Off);
1208 assert(
Func->isConstructor());
1217 if (
D->ElemRecord->getNumVirtualBases() == 0)
1220 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_virtual_base)
1221 <<
Func->getParentDecl();
1226 uint32_t VarArgSize) {
1227 if (
Func->hasThisPointer()) {
1228 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1236 if (!(S.Current->getFunction() &&
1237 S.Current->getFunction()->isLambdaStaticInvoker() &&
1238 Func->isLambdaCallOperator())) {
1243 if (S.checkingPotentialConstantExpression())
1253 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC, VarArgSize);
1255 S.Current = NewFrame.get();
1262 assert(S.Current == FrameBefore);
1268 S.Current = FrameBefore;
1273 uint32_t VarArgSize) {
1275 auto cleanup = [&]() ->
bool {
1280 if (
Func->hasThisPointer()) {
1281 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1290 if (S.Current->getFunction() &&
1291 S.Current->getFunction()->isLambdaStaticInvoker() &&
1292 Func->isLambdaCallOperator()) {
1293 assert(ThisPtr.isZero());
1309 if (
Func->hasThisPointer() && S.checkingPotentialConstantExpression() &&
1310 !
Func->isConstructor())
1316 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC, VarArgSize);
1318 S.Current = NewFrame.get();
1326 assert(S.Current == FrameBefore);
1332 S.Current = FrameBefore;
1337 uint32_t VarArgSize) {
1338 assert(
Func->hasThisPointer());
1339 assert(
Func->isVirtual());
1340 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1352 DynamicDecl =
DynamicType->getPointeeCXXRecordDecl();
1356 assert(DynamicDecl);
1358 const auto *StaticDecl = cast<CXXRecordDecl>(
Func->getParentDecl());
1359 const auto *InitialFunction = cast<CXXMethodDecl>(
Func->getDecl());
1360 const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
1361 DynamicDecl, StaticDecl, InitialFunction);
1363 if (Overrider != InitialFunction) {
1368 const Expr *
E = S.Current->getExpr(OpPC);
1372 Func = S.getContext().getOrCreateFunction(Overrider);
1375 ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
1376 if (
Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
1380 while (ThisPtr.isBaseClass())
1381 ThisPtr = ThisPtr.getBase();
1385 if (!
Call(S, OpPC,
Func, VarArgSize))
1390 if (Overrider != InitialFunction &&
1392 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
1401 unsigned Offset = S.getContext().collectBaseOffset(
1411 const CallExpr *CE, uint32_t BuiltinID) {
1414 if (BuiltinID == Builtin::BI__builtin_operator_new &&
1415 S.checkingPotentialConstantExpression())
1417 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC);
1420 S.Current = NewFrame.get();
1426 assert(S.Current == FrameBefore);
1432 S.Current = FrameBefore;
1442 const auto *
E = cast<CallExpr>(S.Current->getExpr(OpPC));
1443 S.FFDiag(
E, diag::note_constexpr_null_callee)
1448 if (!FuncPtr.
isValid() || !F->getDecl())
1455 if (S.Ctx.classify(F->getDecl()->getReturnType()) !=
1456 S.Ctx.classify(CE->
getType()))
1460 if (F->hasNonNullAttr()) {
1465 assert(ArgSize >= F->getWrittenArgSize());
1466 uint32_t VarArgSize = ArgSize - F->getWrittenArgSize();
1470 if (F->isThisPointerExplicit())
1474 return CallVirt(S, OpPC, F, VarArgSize);
1476 return Call(S, OpPC, F, VarArgSize);
1480 std::optional<uint64_t> ArraySize) {
1489 const auto *NewExpr = cast<CXXNewExpr>(
E);
1502 NewExpr->getAllocatedType(),
1503 APInt(64,
static_cast<uint64_t
>(*ArraySize),
false),
nullptr,
1506 AllocType = NewExpr->getAllocatedType();
1509 unsigned StorageSize = 1;
1510 unsigned AllocSize = 1;
1511 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AllocType))
1512 AllocSize = CAT->getZExtSize();
1513 if (
const auto *CAT = dyn_cast<ConstantArrayType>(StorageType))
1514 StorageSize = CAT->getZExtSize();
1516 if (AllocSize > StorageSize ||
1519 S.FFDiag(S.Current->getLocation(OpPC),
1520 diag::note_constexpr_placement_new_wrong_type)
1521 << StorageType << AllocType;
1538 const auto &
Loc = S.Current->getSource(OpPC);
1540 if (
const auto *NewExpr = dyn_cast<CXXNewExpr>(
E)) {
1541 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
1543 if (!S.
getLangOpts().CPlusPlus26 && NewExpr->getNumPlacementArgs() > 0) {
1545 if (S.Current->isStdFunction())
1547 S.FFDiag(
Loc, diag::note_constexpr_new_placement)
1549 }
else if (NewExpr->getNumPlacementArgs() == 1 &&
1550 !OperatorNew->isReservedGlobalPlacementOperator()) {
1551 S.FFDiag(
Loc, diag::note_constexpr_new_placement)
1553 }
else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) {
1554 S.FFDiag(
Loc, diag::note_constexpr_new_non_replaceable)
1555 << isa<CXXMethodDecl>(OperatorNew) << OperatorNew;
1558 const auto *DeleteExpr = cast<CXXDeleteExpr>(
E);
1559 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
1560 if (!OperatorDelete->isReplaceableGlobalAllocationFunction()) {
1561 S.FFDiag(
Loc, diag::note_constexpr_new_non_replaceable)
1562 << isa<CXXMethodDecl>(OperatorDelete) << OperatorDelete;
1571 const Expr *
E = S.Current->getExpr(OpPC);
1572 if (S.checkingForUndefinedBehavior()) {
1574 E->
getExprLoc(), diag::warn_fixedpoint_constant_overflow)
1577 S.CCEDiag(
E, diag::note_constexpr_overflow)
1579 return S.noteUndefinedBehavior();
1585 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
1591 const Pointer &Ptr,
unsigned BitWidth) {
1596 S.CCEDiag(
E, diag::note_constexpr_invalid_cast)
1597 << 2 << S.
getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
1631 bool TargetIsUCharOrByte) {
1633 if (!HasIndeterminateBits)
1637 if (TargetIsUCharOrByte)
1640 const Expr *
E = S.Current->getExpr(OpPC);
1642 S.FFDiag(
E, diag::note_constexpr_bit_cast_indet_dest)
1648 const Type *TypeInfoType) {
1649 S.Stk.push<
Pointer>(TypePtr, TypeInfoType);
1654 const auto &
P = S.Stk.pop<
Pointer>();
1656 if (!
P.isBlockPointer())
1662 S.FFDiag(S.Current->getSource(OpPC),
1663 diag::note_constexpr_polymorphic_unknown_dynamic_type)
1670 S.Stk.push<
Pointer>(
P.getType().getTypePtr(), TypeInfoType);
1675 const auto *
E = cast<CXXTypeidExpr>(S.Current->getExpr(OpPC));
1676 S.CCEDiag(
E, diag::note_constexpr_typeid_polymorphic)
1683#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
1684#pragma optimize("", off)
1692 assert(!S.Current->isRoot());
1693 CodePtr PC = S.Current->getPC();
1705#include "Opcodes.inc"
1711#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
1712#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 CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
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)
#define TYPE_SWITCH(Expr, B)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
Builtin::Context & BuiltinInfo
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
bool hasCustomTypechecking(unsigned ID) const
Determines whether this builtin has custom typechecking.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
unsigned getBuiltinCallee() const
getBuiltinCallee - If this is a call to a builtin, return the builtin ID of the callee.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Expr ** getArgs()
Retrieve the call arguments.
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 isPureVirtual() const
Whether this virtual function is pure, i.e.
FunctionDecl * getDefinition()
Get the definition for this declaration.
bool isReplaceableGlobalAllocationFunction(std::optional< unsigned > *AlignmentParam=nullptr, bool *IsNothrow=nullptr) const
Determines whether this function is one of the replaceable global allocation functions: void *operato...
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.
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
bool isConstant(const ASTContext &Ctx) const
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
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...
bool isPointerType() 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 isPointerOrReferenceType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
A memory block, either on the stack or in the heap.
unsigned getSize() const
Returns the size of the block.
const Descriptor * getDescriptor() const
Returns the block's descriptor.
unsigned getEvalID() const
The Evaluation ID this block was created in.
Pointer into the code segment.
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
Manages dynamic memory allocations done during bytecode interpretation.
Wrapper around fixed point types.
std::string toDiagnosticString(const ASTContext &Ctx) const
Base class for stack frames, shared between VM and walker.
const Function * getFunction() const
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
bool hasBody() const
Checks if the function already has a body attached.
bool isVirtual() const
Checks if the function is virtual.
bool isConstexpr() const
Checks if the function is valid to call in constexpr.
bool isLambdaStaticInvoker() const
Returns whether this function is a lambda static invoker, which we generate custom byte code for.
static IntegralAP from(T Value, unsigned NumBits=0)
Frame storing local variables.
A pointer to a memory block, live or dead.
Pointer narrow() const
Restricts the scope of an array element pointer.
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.
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.
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.
bool isMutable() const
Checks if the field is mutable.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
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.
bool isStaticTemporary() const
Checks if the storage is a static temporary.
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.
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.
bool isBlockPointer() const
bool isTemporary() const
Checks if the storage is temporary.
SourceLocation getDeclLoc() const
const Block * block() const
Pointer getDeclPtr() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
std::optional< unsigned > getDeclID() const
Returns the declaration ID.
bool isBaseClass() const
Checks if a structure is a base class.
bool isField() const
Checks if the item is a field in an object.
const Record * getRecord() const
Returns the record descriptor of a class.
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.
llvm::iterator_range< const_field_iter > fields() const
Describes the statement/declaration an opcode was generated from.
Defines the clang::TargetInfo interface.
bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off)
bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off)
bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
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.
static bool runRecordDestructor(InterpState &S, CodePtr OpPC, const Pointer &BasePtr, const Descriptor *Desc)
bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType)
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 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 GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr, const Type *TypeInfoType)
Typeid support.
bool CheckCallDepth(InterpState &S, CodePtr OpPC)
Checks if calling the currently active function would exceed the allowed call depth.
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks the 'this' pointer.
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
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
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.
bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
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)
PrimType
Enumeration of the primitive types of the VM.
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.
bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index)
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.
bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Check if a global variable is initialized.
bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *CE, unsigned ArgSize)
Checks if all the arguments annotated as 'nonnull' are in fact not null.
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is a dummy pointer.
static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC, const Function *Func)
llvm::BitVector collectNonNullArgs(const FunctionDecl *F, const llvm::ArrayRef< const Expr * > &Args)
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
bool CallBI(InterpState &S, CodePtr OpPC, const Function *Func, const CallExpr *CE, uint32_t BuiltinID)
bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm, bool IsGlobalDelete)
bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E)
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call, uint32_t BuiltinID)
Interpret a builtin function.
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
Checks if a method can be called.
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, const CallExpr *CE)
bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
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 CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a method can be invoked on an object.
The JSON file list parser is used to communicate input to InstallAPI.
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
llvm::StringRef getAsString(SyncScope S)
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 isCompositeArray() const
Checks if the descriptor is of an array of composites.
const ValueDecl * asValueDecl() const
const Descriptor *const ElemDesc
Descriptor of the array element.
unsigned getMetadataSize() const
Returns the size of the metadata.
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
IntPointer atOffset(const ASTContext &ASTCtx, unsigned Offset) const