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)) {
71 if (
D->getType()->isReferenceType())
75 S.FFDiag(
E, diag::note_constexpr_function_param_value_unknown) <<
D;
83 if (!
D->getType().isConstQualified()) {
85 }
else if (
const auto *VD = dyn_cast<VarDecl>(
D)) {
86 if (!VD->getAnyInitializer()) {
90 S.FFDiag(
Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
91 S.Note(VD->getLocation(), diag::note_declared_at);
106 if (
const auto *VarD = dyn_cast<VarDecl>(VD);
107 VarD && VarD->getType().isConstQualified() &&
108 !VarD->getAnyInitializer()) {
115 if (isa<ObjCIvarDecl>(VD))
119 S.FFDiag(
Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
125 S.
getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
126 : diag::note_constexpr_ltor_non_integral,
142 while (!
U.isRoot() &&
U.inUnion() && !
U.isActive()) {
150 const FieldDecl *InactiveField =
C.getField();
151 assert(InactiveField);
165 if (!
U.getFieldDesc()->isUnion())
169 const Record *R =
U.getRecord();
170 assert(R && R->
isUnion() &&
"Not a union");
173 for (
const Record::Field &F : R->
fields()) {
174 const Pointer &Field =
U.atField(F.Offset);
175 if (Field.isActive()) {
176 ActiveField = Field.getField();
182 S.FFDiag(
Loc, diag::note_constexpr_access_inactive_union_member)
183 << AK << InactiveField << !ActiveField << ActiveField;
193 const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
201 if (!MTE->isUsableInConstantExpressions(S.
getASTContext()) &&
204 S.FFDiag(
E, diag::note_constexpr_access_static_temporary, 1) << AK;
205 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
217 if (S.P.getCurrentDecl() == ID)
220 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
238 if (
Func->isUnevaluatedBuiltin())
243 if (
unsigned BID =
Func->getBuiltinID();
246 cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
247 for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
248 const Expr *A = CE->getArg(I);
254 if (S.Current->Caller &&
Func->isVariadic()) {
259 const Expr *
const *Args =
nullptr;
260 unsigned NumArgs = 0;
261 const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
262 if (
const auto *CE = dyn_cast<CallExpr>(CallSite)) {
263 Args = CE->getArgs();
264 NumArgs = CE->getNumArgs();
265 }
else if (
const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
266 Args = CE->getArgs();
267 NumArgs = CE->getNumArgs();
269 assert(
false &&
"Can't get arguments from that expression type");
271 assert(NumArgs >=
Func->getNumWrittenParams());
272 NumVarArgs = NumArgs - (
Func->getNumWrittenParams() +
273 isa<CXXOperatorCallExpr>(CallSite));
274 for (
unsigned I = 0; I != NumVarArgs; ++I) {
275 const Expr *A = Args[NumArgs - 1 - I];
294 if (!S.checkingPotentialConstantExpression() && S.
getLangOpts().CPlusPlus) {
305 S.FFDiag(
E, diag::note_constexpr_unsized_array_indexed);
312 const auto &Src = S.Current->getSource(OpPC);
315 S.FFDiag(Src, diag::note_constexpr_null_subobject) <<
CSK_Field;
317 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
323 const auto &Src = S.Current->getSource(OpPC);
326 S.FFDiag(Src, diag::note_constexpr_access_deleted_object) << AK;
327 }
else if (!S.checkingPotentialConstantExpression()) {
329 S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
332 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
334 S.Note(Ptr.
getDeclLoc(), diag::note_declared_at);
347 if (!
D || !
D->hasGlobalStorage())
350 if (
D == S.EvaluatingDecl)
353 if (
D->isConstexpr())
359 if (
const auto *VD = dyn_cast_if_present<VarDecl>(S.EvaluatingDecl);
375 S.CCEDiag(S.Current->getLocation(OpPC),
377 ? diag::note_constexpr_ltor_non_constexpr
378 : diag::note_constexpr_ltor_non_integral,
383 S.CCEDiag(S.Current->getLocation(OpPC));
412 S.FFDiag(
Loc, diag::note_constexpr_null_subobject)
413 << CSK << S.Current->getRange(OpPC);
424 S.FFDiag(
Loc, diag::note_constexpr_access_past_end)
425 << AK << S.Current->getRange(OpPC);
435 S.FFDiag(
Loc, diag::note_constexpr_past_end_subobject)
436 << CSK << S.Current->getRange(OpPC);
446 S.FFDiag(
Loc, diag::note_constexpr_past_end_subobject)
447 << CSK << S.Current->getRange(OpPC);
458 if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
461 const auto *
E = cast<CastExpr>(S.Current->getExpr(OpPC));
465 S.CCEDiag(
E, diag::note_constexpr_invalid_downcast)
466 << MostDerivedQT << TargetQT;
472 assert(Ptr.
isLive() &&
"Pointer is not live");
480 if (S.Current->getFunction()) {
483 Func && (
Func->isConstructor() ||
Func->isDestructor()) &&
495 S.FFDiag(
Loc, diag::note_constexpr_modify_const_type) << Ty;
500 assert(Ptr.
isLive() &&
"Pointer is not live");
512 S.FFDiag(
Loc, diag::note_constexpr_access_mutable, 1) <<
AK_Read << Field;
513 S.Note(Field->getLocation(), diag::note_declared_at);
532 S.FFDiag(
Loc, diag::note_constexpr_access_volatile_type) << AK << PtrType;
546 VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
548 if (VD->getAnyInitializer()) {
549 S.FFDiag(
Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
550 S.Note(VD->getLocation(), diag::note_declared_at);
557 if (!S.checkingPotentialConstantExpression()) {
558 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
559 << AK <<
true << S.Current->getRange(OpPC);
570 if ((!VD->hasConstantInitialization() &&
571 VD->mightBeUsableInConstantExpressions(S.
getASTContext())) ||
575 S.FFDiag(
Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
576 S.Note(VD->getLocation(), diag::note_declared_at);
587 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_var_init_weak)
589 S.Note(VD->getLocation(), diag::note_declared_at);
688 S.CCEDiag(
Loc, diag::note_constexpr_virtual_call);
710 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
711 if (CD && CD->isInheritingConstructor()) {
712 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
713 if (!Inherited->isConstexpr())
714 DiagDecl = CD = Inherited;
720 if (CD && CD->isInheritingConstructor()) {
721 S.FFDiag(
Loc, diag::note_constexpr_invalid_inhctor, 1)
722 << CD->getInheritedConstructor().getConstructor()->getParent();
723 S.Note(DiagDecl->
getLocation(), diag::note_declared_at);
730 S.checkingPotentialConstantExpression())
739 S.FFDiag(
Loc, diag::note_constexpr_invalid_function, 1)
744 diag::note_declared_at);
746 S.Note(DiagDecl->
getLocation(), diag::note_declared_at);
749 S.FFDiag(
Loc, diag::note_invalid_subexpr_in_const_expr);
756 if ((S.Current->getDepth() + 1) > S.
getLangOpts().ConstexprCallDepth) {
757 S.FFDiag(S.Current->getSource(OpPC),
758 diag::note_constexpr_depth_limit_exceeded)
772 bool IsImplicit =
false;
773 if (
const auto *
E = dyn_cast_if_present<CXXThisExpr>(
Loc.asExpr()))
774 IsImplicit =
E->isImplicit();
777 S.FFDiag(
Loc, diag::note_constexpr_this) << IsImplicit;
788 S.FFDiag(
E, diag::note_constexpr_pure_virtual_call, 1) << MD;
794 APFloat::opStatus Status,
FPOptions FPO) {
801 S.CCEDiag(
E, diag::note_constexpr_float_arithmetic)
802 <<
true << S.Current->getRange(OpPC);
803 return S.noteUndefinedBehavior();
808 if (S.inConstantContext())
811 if ((Status & APFloat::opInexact) &&
816 S.FFDiag(
E, diag::note_constexpr_dynamic_rounding);
820 if ((Status != APFloat::opOK) &&
823 FPO.getAllowFEnvAccess())) {
825 S.FFDiag(
E, diag::note_constexpr_float_arithmetic_strict);
829 if ((Status & APFloat::opStatus::opInvalidOp) &&
845 S.CCEDiag(
E, diag::note_constexpr_new);
852 const Expr *NewExpr) {
853 if (AllocForm == DeleteForm)
861 QualType ElemQT =
D->getType()->getPointeeType();
863 ElemQT,
APInt(64,
static_cast<uint64_t
>(
D->getNumElems()),
false),
866 TypeToDiagnose =
D->getType()->getPointeeType();
869 S.FFDiag(
E, diag::note_constexpr_new_delete_mismatch)
870 <<
static_cast<int>(DeleteForm) <<
static_cast<int>(AllocForm)
872 S.Note(NewExpr->
getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
880 if (isa_and_nonnull<CXXNewExpr>(Source))
883 if (
const auto *CE = dyn_cast_if_present<CallExpr>(Source);
884 CE && CE->getBuiltinCallee() == Builtin::BI__builtin_operator_new)
887 if (
const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(Source);
888 MCE && MCE->getMethodDecl()->
getIdentifier()->isStr(
"allocate"))
893 S.FFDiag(
Loc, diag::note_constexpr_delete_not_heap_alloc)
897 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
899 S.Note(Ptr.
getDeclLoc(), diag::note_declared_at);
926 S.FFDiag(
E, diag::note_constexpr_modify_global);
932 const CallExpr *CE,
unsigned ArgSize) {
937 for (
const Expr *Arg : Args) {
938 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
942 S.CCEDiag(
Loc, diag::note_non_null_attribute_failed);
967 S.FFDiag(
Loc, diag::note_constexpr_double_destroy);
974 const Function *DtorFunc = S.getContext().getOrCreateFunction(Dtor);
979 if (!
Call(S, OpPC, DtorFunc, 0))
999 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
1013 return DD->isVirtual();
1018 bool IsGlobalDelete) {
1022 const Expr *Source =
nullptr;
1023 const Block *BlockToDelete =
nullptr;
1040 if (!DeleteIsArrayForm && Ptr.
getType() != InitialType &&
1042 S.FFDiag(S.Current->getSource(OpPC),
1043 diag::note_constexpr_delete_base_nonvirt_dtor)
1044 << InitialType << Ptr.
getType();
1050 S.FFDiag(
Loc, diag::note_constexpr_delete_subobject)
1056 BlockToDelete = Ptr.
block();
1064 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1068 return DD->isVirtual() ? DD->getOperatorDelete() :
nullptr;
1076 S.FFDiag(S.Current->getSource(OpPC),
1077 diag::note_constexpr_new_non_replaceable)
1078 << isa<CXXMethodDecl>(VirtualDelete) << VirtualDelete;
1084 assert(BlockToDelete);
1092 std::optional<DynamicAllocator::Form> AllocForm =
1093 Allocator.getAllocationForm(Source);
1095 if (!Allocator.deallocate(Source, BlockToDelete, S)) {
1098 S.FFDiag(
Loc, diag::note_constexpr_double_delete);
1115 if (S.EvaluatingDecl && !S.EvaluatingDecl->isConstexpr())
1124 S.CCEDiag(
Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1125 << llvm::toString(
Value, 10) <<
Min.getSExtValue() <<
Max.getSExtValue()
1129 S.CCEDiag(
Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1130 << llvm::toString(
Value, 10) <<
Min.getZExtValue() <<
Max.getZExtValue()
1153 if (S.Current->getFunction() && S.Current->getFunction()->isConstructor() &&
1154 S.Current->getThis().getDeclDesc()->asDecl() == S.EvaluatingDecl) {
1158 const Expr *
E = S.Current->getExpr(OpPC);
1160 S.FFDiag(
E, diag::note_constexpr_nonliteral) <<
E->
getType();
1162 S.FFDiag(
E, diag::note_invalid_subexpr_in_const_expr);
1168 if (S.
getLangOpts().CPlusPlus && S.inConstantContext() &&
1190 S.FFDiag(S.Current->getSource(OpPC),
1191 diag::note_constexpr_access_unreadable_object)
1204 const auto &Ptr = S.Stk.peek<
Pointer>();
1205 return getField(S, OpPC, Ptr, Off);
1209 const auto &Ptr = S.Stk.pop<
Pointer>();
1210 return getField(S, OpPC, Ptr, Off);
1215 assert(
Func->isConstructor());
1224 if (
D->ElemRecord->getNumVirtualBases() == 0)
1227 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_virtual_base)
1228 <<
Func->getParentDecl();
1233 uint32_t VarArgSize) {
1234 if (
Func->hasThisPointer()) {
1235 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1243 if (!(S.Current->getFunction() &&
1244 S.Current->getFunction()->isLambdaStaticInvoker() &&
1245 Func->isLambdaCallOperator())) {
1250 if (S.checkingPotentialConstantExpression())
1260 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC, VarArgSize);
1262 S.Current = NewFrame.get();
1269 assert(S.Current == FrameBefore);
1275 S.Current = FrameBefore;
1280 uint32_t VarArgSize) {
1282 auto cleanup = [&]() ->
bool {
1287 if (
Func->hasThisPointer()) {
1288 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1296 if (ThisPtr.isDummy() &&
Func->isVirtual())
1303 if (S.Current->getFunction() &&
1304 S.Current->getFunction()->isLambdaStaticInvoker() &&
1305 Func->isLambdaCallOperator()) {
1306 assert(ThisPtr.isZero());
1322 if (
Func->hasThisPointer() && S.checkingPotentialConstantExpression() &&
1323 !
Func->isConstructor())
1329 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC, VarArgSize);
1331 S.Current = NewFrame.get();
1339 assert(S.Current == FrameBefore);
1345 S.Current = FrameBefore;
1350 uint32_t VarArgSize) {
1351 assert(
Func->hasThisPointer());
1352 assert(
Func->isVirtual());
1353 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1365 DynamicDecl =
DynamicType->getPointeeCXXRecordDecl();
1369 assert(DynamicDecl);
1371 const auto *StaticDecl = cast<CXXRecordDecl>(
Func->getParentDecl());
1372 const auto *InitialFunction = cast<CXXMethodDecl>(
Func->getDecl());
1373 const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
1374 DynamicDecl, StaticDecl, InitialFunction);
1376 if (Overrider != InitialFunction) {
1381 const Expr *
E = S.Current->getExpr(OpPC);
1385 Func = S.getContext().getOrCreateFunction(Overrider);
1388 ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
1389 if (
Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
1393 while (ThisPtr.isBaseClass())
1394 ThisPtr = ThisPtr.getBase();
1398 if (!
Call(S, OpPC,
Func, VarArgSize))
1403 if (Overrider != InitialFunction &&
1405 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
1414 unsigned Offset = S.getContext().collectBaseOffset(
1424 const CallExpr *CE, uint32_t BuiltinID) {
1427 if (BuiltinID == Builtin::BI__builtin_operator_new &&
1428 S.checkingPotentialConstantExpression())
1430 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC);
1433 S.Current = NewFrame.get();
1439 assert(S.Current == FrameBefore);
1445 S.Current = FrameBefore;
1455 const auto *
E = cast<CallExpr>(S.Current->getExpr(OpPC));
1456 S.FFDiag(
E, diag::note_constexpr_null_callee)
1461 if (!FuncPtr.
isValid() || !F->getDecl())
1468 if (S.Ctx.classify(F->getDecl()->getReturnType()) !=
1469 S.Ctx.classify(CE->
getType()))
1473 if (F->hasNonNullAttr()) {
1478 assert(ArgSize >= F->getWrittenArgSize());
1479 uint32_t VarArgSize = ArgSize - F->getWrittenArgSize();
1483 if (F->isThisPointerExplicit())
1487 return CallVirt(S, OpPC, F, VarArgSize);
1489 return Call(S, OpPC, F, VarArgSize);
1493 std::optional<uint64_t> ArraySize) {
1502 const auto *NewExpr = cast<CXXNewExpr>(
E);
1516 NewExpr->getAllocatedType(),
1517 APInt(64,
static_cast<uint64_t
>(*ArraySize),
false),
nullptr,
1520 AllocType = NewExpr->getAllocatedType();
1523 unsigned StorageSize = 1;
1524 unsigned AllocSize = 1;
1525 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AllocType))
1526 AllocSize = CAT->getZExtSize();
1527 if (
const auto *CAT = dyn_cast<ConstantArrayType>(StorageType))
1528 StorageSize = CAT->getZExtSize();
1530 if (AllocSize > StorageSize ||
1533 S.FFDiag(S.Current->getLocation(OpPC),
1534 diag::note_constexpr_placement_new_wrong_type)
1535 << StorageType << AllocType;
1552 const auto &
Loc = S.Current->getSource(OpPC);
1554 if (
const auto *NewExpr = dyn_cast<CXXNewExpr>(
E)) {
1555 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
1557 if (!S.
getLangOpts().CPlusPlus26 && NewExpr->getNumPlacementArgs() > 0) {
1559 if (S.Current->isStdFunction())
1561 S.FFDiag(
Loc, diag::note_constexpr_new_placement)
1563 }
else if (NewExpr->getNumPlacementArgs() == 1 &&
1564 !OperatorNew->isReservedGlobalPlacementOperator()) {
1565 S.FFDiag(
Loc, diag::note_constexpr_new_placement)
1567 }
else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) {
1568 S.FFDiag(
Loc, diag::note_constexpr_new_non_replaceable)
1569 << isa<CXXMethodDecl>(OperatorNew) << OperatorNew;
1572 const auto *DeleteExpr = cast<CXXDeleteExpr>(
E);
1573 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
1574 if (!OperatorDelete->isReplaceableGlobalAllocationFunction()) {
1575 S.FFDiag(
Loc, diag::note_constexpr_new_non_replaceable)
1576 << isa<CXXMethodDecl>(OperatorDelete) << OperatorDelete;
1585 const Expr *
E = S.Current->getExpr(OpPC);
1586 if (S.checkingForUndefinedBehavior()) {
1588 E->
getExprLoc(), diag::warn_fixedpoint_constant_overflow)
1591 S.CCEDiag(
E, diag::note_constexpr_overflow)
1593 return S.noteUndefinedBehavior();
1599 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
1605 const Pointer &Ptr,
unsigned BitWidth) {
1610 S.CCEDiag(
E, diag::note_constexpr_invalid_cast)
1611 << 2 << S.
getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
1645 bool TargetIsUCharOrByte) {
1647 if (!HasIndeterminateBits)
1651 if (TargetIsUCharOrByte)
1654 const Expr *
E = S.Current->getExpr(OpPC);
1656 S.FFDiag(
E, diag::note_constexpr_bit_cast_indet_dest)
1662 const Type *TypeInfoType) {
1663 S.Stk.push<
Pointer>(TypePtr, TypeInfoType);
1668 const auto &
P = S.Stk.pop<
Pointer>();
1670 if (!
P.isBlockPointer())
1673 S.Stk.push<
Pointer>(
P.getType().getTypePtr(), TypeInfoType);
1678 const auto *
E = cast<CXXTypeidExpr>(S.Current->getExpr(OpPC));
1679 S.CCEDiag(
E, diag::note_constexpr_typeid_polymorphic)
1686#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
1687#pragma optimize("", off)
1695 assert(!S.Current->isRoot());
1696 CodePtr PC = S.Current->getPC();
1708#include "Opcodes.inc"
1714#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
1715#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)
static StringRef getIdentifier(const Token &Tok)
#define TYPE_SWITCH(Expr, B)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
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 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
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