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;
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);
420 S.FFDiag(
Loc, diag::note_constexpr_access_past_end)
421 << AK << S.Current->getRange(OpPC);
430 S.FFDiag(
Loc, diag::note_constexpr_past_end_subobject)
431 << CSK << S.Current->getRange(OpPC);
441 S.FFDiag(
Loc, diag::note_constexpr_past_end_subobject)
442 << CSK << S.Current->getRange(OpPC);
453 if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
456 const auto *
E = cast<CastExpr>(S.Current->getExpr(OpPC));
460 S.CCEDiag(
E, diag::note_constexpr_invalid_downcast)
461 << MostDerivedQT << TargetQT;
467 assert(Ptr.
isLive() &&
"Pointer is not live");
475 if (S.Current->getFunction()) {
478 Func && (
Func->isConstructor() ||
Func->isDestructor()) &&
490 S.FFDiag(
Loc, diag::note_constexpr_modify_const_type) << Ty;
495 assert(Ptr.
isLive() &&
"Pointer is not live");
507 S.FFDiag(
Loc, diag::note_constexpr_access_mutable, 1) <<
AK_Read << Field;
508 S.Note(Field->getLocation(), diag::note_declared_at);
527 S.FFDiag(
Loc, diag::note_constexpr_access_volatile_type) << AK << PtrType;
543 if (VD->getAnyInitializer()) {
544 S.FFDiag(
Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
545 S.Note(VD->getLocation(), diag::note_declared_at);
552 if (!S.checkingPotentialConstantExpression()) {
553 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
554 << AK <<
true << S.Current->getRange(OpPC);
565 if ((!VD->hasConstantInitialization() &&
566 VD->mightBeUsableInConstantExpressions(S.
getASTContext())) ||
570 S.FFDiag(
Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
571 S.Note(VD->getLocation(), diag::note_declared_at);
582 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_var_init_weak)
584 S.Note(VD->getLocation(), diag::note_declared_at);
683 S.CCEDiag(
Loc, diag::note_constexpr_virtual_call);
705 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
706 if (CD && CD->isInheritingConstructor()) {
707 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
708 if (!Inherited->isConstexpr())
709 DiagDecl = CD = Inherited;
715 if (CD && CD->isInheritingConstructor()) {
716 S.FFDiag(
Loc, diag::note_constexpr_invalid_inhctor, 1)
717 << CD->getInheritedConstructor().getConstructor()->getParent();
718 S.Note(DiagDecl->
getLocation(), diag::note_declared_at);
725 S.checkingPotentialConstantExpression())
734 S.FFDiag(
Loc, diag::note_constexpr_invalid_function, 1)
739 diag::note_declared_at);
741 S.Note(DiagDecl->
getLocation(), diag::note_declared_at);
744 S.FFDiag(
Loc, diag::note_invalid_subexpr_in_const_expr);
751 if ((S.Current->getDepth() + 1) > S.
getLangOpts().ConstexprCallDepth) {
752 S.FFDiag(S.Current->getSource(OpPC),
753 diag::note_constexpr_depth_limit_exceeded)
767 bool IsImplicit =
false;
768 if (
const auto *
E = dyn_cast_if_present<CXXThisExpr>(
Loc.asExpr()))
769 IsImplicit =
E->isImplicit();
772 S.FFDiag(
Loc, diag::note_constexpr_this) << IsImplicit;
783 S.FFDiag(
E, diag::note_constexpr_pure_virtual_call, 1) << MD;
789 APFloat::opStatus Status,
FPOptions FPO) {
796 S.CCEDiag(
E, diag::note_constexpr_float_arithmetic)
797 <<
true << S.Current->getRange(OpPC);
798 return S.noteUndefinedBehavior();
803 if (S.inConstantContext())
806 if ((Status & APFloat::opInexact) &&
811 S.FFDiag(
E, diag::note_constexpr_dynamic_rounding);
815 if ((Status != APFloat::opOK) &&
818 FPO.getAllowFEnvAccess())) {
820 S.FFDiag(
E, diag::note_constexpr_float_arithmetic_strict);
824 if ((Status & APFloat::opStatus::opInvalidOp) &&
840 S.CCEDiag(
E, diag::note_constexpr_new);
847 const Expr *NewExpr) {
848 if (AllocForm == DeleteForm)
856 QualType ElemQT =
D->getType()->getPointeeType();
858 ElemQT,
APInt(64,
static_cast<uint64_t
>(
D->getNumElems()),
false),
861 TypeToDiagnose =
D->getType()->getPointeeType();
864 S.FFDiag(
E, diag::note_constexpr_new_delete_mismatch)
865 <<
static_cast<int>(DeleteForm) <<
static_cast<int>(AllocForm)
867 S.Note(NewExpr->
getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
876 if (isa_and_nonnull<CXXNewExpr>(Source))
878 if (
const CallExpr *CE = dyn_cast_if_present<CallExpr>(Source);
884 S.FFDiag(
Loc, diag::note_constexpr_delete_not_heap_alloc)
888 S.Note(Ptr.
getDeclLoc(), diag::note_constexpr_temporary_here);
890 S.Note(Ptr.
getDeclLoc(), diag::note_declared_at);
917 S.FFDiag(
E, diag::note_constexpr_modify_global);
923 const CallExpr *CE,
unsigned ArgSize) {
928 for (
const Expr *Arg : Args) {
929 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
933 S.CCEDiag(
Loc, diag::note_non_null_attribute_failed);
958 S.FFDiag(
Loc, diag::note_constexpr_double_destroy);
965 const Function *DtorFunc = S.getContext().getOrCreateFunction(Dtor);
970 if (!
Call(S, OpPC, DtorFunc, 0))
990 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
1004 return DD->isVirtual();
1009 bool IsGlobalDelete) {
1013 const Expr *Source =
nullptr;
1014 const Block *BlockToDelete =
nullptr;
1031 if (!DeleteIsArrayForm && Ptr.
getType() != InitialType &&
1033 S.FFDiag(S.Current->getSource(OpPC),
1034 diag::note_constexpr_delete_base_nonvirt_dtor)
1035 << InitialType << Ptr.
getType();
1041 S.FFDiag(
Loc, diag::note_constexpr_delete_subobject)
1047 BlockToDelete = Ptr.
block();
1055 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1059 return DD->isVirtual() ? DD->getOperatorDelete() :
nullptr;
1067 S.FFDiag(S.Current->getSource(OpPC),
1068 diag::note_constexpr_new_non_replaceable)
1069 << isa<CXXMethodDecl>(VirtualDelete) << VirtualDelete;
1075 assert(BlockToDelete);
1083 std::optional<DynamicAllocator::Form> AllocForm =
1084 Allocator.getAllocationForm(Source);
1086 if (!Allocator.deallocate(Source, BlockToDelete, S)) {
1089 S.FFDiag(
Loc, diag::note_constexpr_double_delete);
1106 if (S.EvaluatingDecl && !S.EvaluatingDecl->isConstexpr())
1115 S.CCEDiag(
Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1116 << llvm::toString(
Value, 10) <<
Min.getSExtValue() <<
Max.getSExtValue()
1120 S.CCEDiag(
Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1121 << llvm::toString(
Value, 10) <<
Min.getZExtValue() <<
Max.getZExtValue()
1144 if (S.Current->getFunction() && S.Current->getFunction()->isConstructor() &&
1145 S.Current->getThis().getDeclDesc()->asDecl() == S.EvaluatingDecl) {
1149 const Expr *
E = S.Current->getExpr(OpPC);
1151 S.FFDiag(
E, diag::note_constexpr_nonliteral) <<
E->
getType();
1153 S.FFDiag(
E, diag::note_invalid_subexpr_in_const_expr);
1159 assert(
Func->isConstructor());
1168 if (
D->ElemRecord->getNumVirtualBases() == 0)
1171 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_virtual_base)
1172 <<
Func->getParentDecl();
1177 uint32_t VarArgSize) {
1178 if (
Func->hasThisPointer()) {
1179 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1187 if (!(S.Current->getFunction() &&
1188 S.Current->getFunction()->isLambdaStaticInvoker() &&
1189 Func->isLambdaCallOperator())) {
1194 if (S.checkingPotentialConstantExpression())
1204 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC, VarArgSize);
1206 S.Current = NewFrame.get();
1213 assert(S.Current == FrameBefore);
1219 S.Current = FrameBefore;
1224 uint32_t VarArgSize) {
1226 auto cleanup = [&]() ->
bool {
1231 if (
Func->hasThisPointer()) {
1232 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1241 if (S.Current->getFunction() &&
1242 S.Current->getFunction()->isLambdaStaticInvoker() &&
1243 Func->isLambdaCallOperator()) {
1244 assert(ThisPtr.isZero());
1260 if (
Func->hasThisPointer() && S.checkingPotentialConstantExpression() &&
1261 !
Func->isConstructor())
1267 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC, VarArgSize);
1269 S.Current = NewFrame.get();
1277 assert(S.Current == FrameBefore);
1283 S.Current = FrameBefore;
1288 uint32_t VarArgSize) {
1289 assert(
Func->hasThisPointer());
1290 assert(
Func->isVirtual());
1291 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1303 DynamicDecl =
DynamicType->getPointeeCXXRecordDecl();
1307 assert(DynamicDecl);
1309 const auto *StaticDecl = cast<CXXRecordDecl>(
Func->getParentDecl());
1310 const auto *InitialFunction = cast<CXXMethodDecl>(
Func->getDecl());
1311 const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
1312 DynamicDecl, StaticDecl, InitialFunction);
1314 if (Overrider != InitialFunction) {
1319 const Expr *
E = S.Current->getExpr(OpPC);
1323 Func = S.getContext().getOrCreateFunction(Overrider);
1326 ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
1327 if (
Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
1331 while (ThisPtr.isBaseClass())
1332 ThisPtr = ThisPtr.getBase();
1336 if (!
Call(S, OpPC,
Func, VarArgSize))
1341 if (Overrider != InitialFunction &&
1343 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
1352 unsigned Offset = S.getContext().collectBaseOffset(
1362 const CallExpr *CE, uint32_t BuiltinID) {
1365 if (BuiltinID == Builtin::BI__builtin_operator_new &&
1366 S.checkingPotentialConstantExpression())
1368 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC);
1371 S.Current = NewFrame.get();
1377 assert(S.Current == FrameBefore);
1383 S.Current = FrameBefore;
1393 const auto *
E = cast<CallExpr>(S.Current->getExpr(OpPC));
1394 S.FFDiag(
E, diag::note_constexpr_null_callee)
1399 if (!FuncPtr.
isValid() || !F->getDecl())
1406 if (S.Ctx.classify(F->getDecl()->getReturnType()) !=
1407 S.Ctx.classify(CE->
getType()))
1411 if (F->hasNonNullAttr()) {
1416 assert(ArgSize >= F->getWrittenArgSize());
1417 uint32_t VarArgSize = ArgSize - F->getWrittenArgSize();
1421 if (F->isThisPointerExplicit())
1425 return CallVirt(S, OpPC, F, VarArgSize);
1427 return Call(S, OpPC, F, VarArgSize);
1431 std::optional<uint64_t> ArraySize) {
1440 const auto *NewExpr = cast<CXXNewExpr>(
E);
1453 NewExpr->getAllocatedType(),
1454 APInt(64,
static_cast<uint64_t
>(*ArraySize),
false),
nullptr,
1457 AllocType = NewExpr->getAllocatedType();
1460 unsigned StorageSize = 1;
1461 unsigned AllocSize = 1;
1462 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AllocType))
1463 AllocSize = CAT->getZExtSize();
1464 if (
const auto *CAT = dyn_cast<ConstantArrayType>(StorageType))
1465 StorageSize = CAT->getZExtSize();
1467 if (AllocSize > StorageSize ||
1470 S.FFDiag(S.Current->getLocation(OpPC),
1471 diag::note_constexpr_placement_new_wrong_type)
1472 << StorageType << AllocType;
1489 const auto &
Loc = S.Current->getSource(OpPC);
1491 if (
const auto *NewExpr = dyn_cast<CXXNewExpr>(
E)) {
1492 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
1494 if (!S.
getLangOpts().CPlusPlus26 && NewExpr->getNumPlacementArgs() > 0) {
1496 if (S.Current->isStdFunction())
1498 S.FFDiag(
Loc, diag::note_constexpr_new_placement)
1500 }
else if (NewExpr->getNumPlacementArgs() == 1 &&
1501 !OperatorNew->isReservedGlobalPlacementOperator()) {
1502 S.FFDiag(
Loc, diag::note_constexpr_new_placement)
1504 }
else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) {
1505 S.FFDiag(
Loc, diag::note_constexpr_new_non_replaceable)
1506 << isa<CXXMethodDecl>(OperatorNew) << OperatorNew;
1509 const auto *DeleteExpr = cast<CXXDeleteExpr>(
E);
1510 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
1511 if (!OperatorDelete->isReplaceableGlobalAllocationFunction()) {
1512 S.FFDiag(
Loc, diag::note_constexpr_new_non_replaceable)
1513 << isa<CXXMethodDecl>(OperatorDelete) << OperatorDelete;
1522 const Expr *
E = S.Current->getExpr(OpPC);
1523 if (S.checkingForUndefinedBehavior()) {
1525 E->
getExprLoc(), diag::warn_fixedpoint_constant_overflow)
1528 S.CCEDiag(
E, diag::note_constexpr_overflow)
1530 return S.noteUndefinedBehavior();
1536 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
1542 const Pointer &Ptr,
unsigned BitWidth) {
1547 S.CCEDiag(
E, diag::note_constexpr_invalid_cast)
1548 << 2 << S.
getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
1582 bool TargetIsUCharOrByte) {
1584 if (!HasIndeterminateBits)
1588 if (TargetIsUCharOrByte)
1591 const Expr *
E = S.Current->getExpr(OpPC);
1593 S.FFDiag(
E, diag::note_constexpr_bit_cast_indet_dest)
1599#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
1600#pragma optimize("", off)
1608 assert(!S.Current->isRoot());
1609 CodePtr PC = S.Current->getPC();
1621#include "Opcodes.inc"
1627#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
1628#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 ...
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 ...
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
A memory block, either on the stack or in the heap.
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.
bool isMutable() const
Checks if the field is mutable.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
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.
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 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 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 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 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 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 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