26#include "llvm/ADT/StringExtras.h"
31#if __has_cpp_attribute(clang::musttail)
32#define MUSTTAIL [[clang::musttail]]
33#elif __has_cpp_attribute(msvc::musttail)
34#define MUSTTAIL [[msvc::musttail]]
35#elif __has_attribute(musttail)
36#define MUSTTAIL __attribute__((musttail))
43#if defined(_MSC_VER) || defined(__powerpc__) || !defined(MUSTTAIL) || \
44 defined(__i386__) || defined(__sparc__)
47#define USE_TAILCALLS 0
49#define USE_TAILCALLS 1
53 llvm::report_fatal_error(
"Interpreter cannot return values");
84 S.
FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
120 S.
FFDiag(Loc, diag::note_constexpr_access_unknown_variable, 1)
122 S.
Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
124 S.
FFDiag(Loc, diag::note_constexpr_function_param_value_unknown, 1) << D;
134 }
else if (
const auto *VD = dyn_cast<VarDecl>(D)) {
135 if (!VD->getAnyInitializer()) {
139 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
140 S.
Note(VD->getLocation(), diag::note_declared_at);
163 if (
const auto *VarD = dyn_cast<VarDecl>(VD);
164 VarD && VarD->getType().isConstQualified() &&
165 (VarD->isConstexpr() || !VarD->getType()->isArrayType()) &&
166 !VarD->getAnyInitializer()) {
178 S.
FFDiag(Loc, diag::note_constexpr_modify_global);
180 S.
FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
187 S.
getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
188 : diag::note_constexpr_ltor_non_integral,
200 const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
212 S.
FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
251 S.
CCEDiag(E, diag::note_constexpr_large_shift)
273 unsigned VariadicArgSize =
275 unsigned TargetStackSize = S.
Stk.
size() - VariadicArgSize;
276 while (S.
Stk.
size() != TargetStackSize) {
286 if (
Func->hasImplicitThisPointer())
334 while (!
U.isRoot() && !
U.isActive()) {
339 if (
U.getRecord() &&
U.getRecord()->isAnonymousUnion())
346 assert(
C.getBase() ==
U);
360 if (!
U.getFieldDesc()->isUnion())
370 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(R->getDecl());
371 CXXRD && !CXXRD->hasTrivialDefaultConstructor()) {
383 assert(!
C.isActive());
384 const FieldDecl *InactiveField =
C.getField();
385 assert(InactiveField);
388 const Record *R =
U.getRecord();
389 assert(R && R->isUnion() &&
"Not a union");
392 for (
const Record::Field &F : R->fields()) {
393 PtrView Field =
U.atField(F.Offset);
394 if (Field.isActive()) {
395 ActiveField = Field.getField();
401 diag::note_constexpr_access_inactive_union_member)
402 << AK << InactiveField << !ActiveField << ActiveField;
429 S.
FFDiag(E, diag::note_constexpr_unsized_array_indexed);
441 S.
FFDiag(Src, diag::note_constexpr_access_null) << AK;
450 S.
FFDiag(Src, diag::note_constexpr_access_deleted_object) << AK;
452 S.
FFDiag(Src, diag::note_constexpr_access_uninit)
471 if (D->getType().isConstQualified())
485 if (
T->isIntegralOrEnumerationType()) {
497 ? diag::note_constexpr_ltor_non_constexpr
498 : diag::note_constexpr_ltor_non_integral,
501 S.
Note(D->getLocation(), diag::note_declared_at);
508 if (
T->isPointerOrReferenceType()) {
538 S.
FFDiag(Loc, diag::note_constexpr_null_subobject)
549 S.
FFDiag(Loc, diag::note_constexpr_access_past_end)
560 S.
FFDiag(Loc, diag::note_constexpr_past_end_subobject)
571 S.
FFDiag(Loc, diag::note_constexpr_past_end_subobject)
583 if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
597 S.
CCEDiag(E, diag::note_constexpr_invalid_downcast)
598 << MostDerivedQT << TargetQT;
604 assert(Ptr.
isLive() &&
"Pointer is not live");
617 if (
V.block() != Ptr.
block())
619 if (!
V.getFieldDesc()->IsConst) {
634 bool FoundProblem =
false;
636 if (P.getFieldDesc()->IsConst) {
655 S.
FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
661 assert(Ptr.
isLive() &&
"Pointer is not live");
678 MutablePtr = MutablePtr.
getBase();
682 S.
FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK << Field;
683 S.
Note(Field->getLocation(), diag::note_declared_at);
715 Loc = F->getLocation();
719 Loc = VD->getLocation();
724 Loc = E->getExprLoc();
728 diag::note_constexpr_access_volatile_obj, 1)
729 << AK << DiagKind << ND;
730 S.
Note(Loc, diag::note_constexpr_volatile_here) << DiagKind;
757 VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
760 !(S.
getLangOpts().CPlusPlus23 && VD->getType()->isReferenceType())) {
769 S.
Note(VD->getFirstDecl()->getLocation(), diag::note_declared_at);
774 if (VD->getAnyInitializer()) {
776 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
777 S.
Note(VD->getLocation(), diag::note_declared_at);
818 S.
Note(VD->getLocation(), diag::note_declared_at);
849 diag::note_constexpr_access_volatile_obj, 1)
862 if (!Desc.IsInitialized)
872 diag::note_constexpr_access_volatile_obj, 1)
897 S.
FFDiag(Src, diag::note_constexpr_access_null) << AK;
949 if (
const auto *CLE =
950 dyn_cast_if_present<CompoundLiteralExpr>(Desc->
asExpr())) {
951 if (
QualType CLETy = CLE->getType();
954 diag::note_invalid_subexpr_in_const_expr)
956 S.
Note(CLE->getExprLoc(), diag::note_declared_at);
1000 bool WillBeActivated) {
1031 bool IsCtor,
bool IsDtor) {
1063 StringRef Name = DiagDecl->
getName();
1065 Name ==
"__assert_rtn" || Name ==
"__assert_fail" || Name ==
"_wassert";
1068 diag::note_constexpr_assert_failed);
1075 diag::note_invalid_subexpr_in_const_expr);
1081 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
1082 if (CD && CD->isInheritingConstructor()) {
1083 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
1084 if (!Inherited->isConstexpr())
1085 DiagDecl = CD = Inherited;
1090 if (CD && CD->getParent()->isInvalidDecl())
1096 if (CD && CD->isInheritingConstructor()) {
1099 << CD->getInheritedConstructor().getConstructor()->getParent();
1107 if (!IsDefined && !IsExtern && DiagDecl->
isConstexpr() &&
1117 diag::note_constexpr_invalid_function, 1)
1118 << DiagDecl->
isConstexpr() << (bool)CD << DiagDecl;
1134 S.
CCEDiag(Loc, diag::note_constexpr_virtual_call);
1158 diag::note_constexpr_depth_limit_exceeded)
1172 bool IsImplicit =
false;
1173 if (
const auto *TE = dyn_cast<CXXThisExpr>(E))
1174 IsImplicit = TE->isImplicit();
1175 S.
FFDiag(E, diag::note_constexpr_this) << IsImplicit;
1190 if ((Status & APFloat::opInexact) &&
1195 S.
FFDiag(E, diag::note_constexpr_dynamic_rounding);
1199 if ((Status != APFloat::opOK) &&
1202 FPO.getAllowFEnvAccess())) {
1204 S.
FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
1208 if ((Status & APFloat::opStatus::opInvalidOp) &&
1220 APFloat::opStatus Status,
FPOptions FPO) {
1231 S.
CCEDiag(E, diag::note_constexpr_float_arithmetic)
1244 S.
CCEDiag(E, diag::note_constexpr_new);
1251 const Expr *NewExpr) {
1252 if (AllocForm == DeleteForm)
1258 S.
FFDiag(E, diag::note_constexpr_new_delete_mismatch)
1259 <<
static_cast<int>(DeleteForm) <<
static_cast<int>(AllocForm)
1261 S.
Note(NewExpr->
getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
1269 if (isa_and_nonnull<CXXNewExpr>(Source))
1272 if (
const auto *CE = dyn_cast_if_present<CallExpr>(Source);
1273 CE && CE->getBuiltinCallee() == Builtin::BI__builtin_operator_new)
1276 if (
const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(Source);
1277 MCE && MCE->getMethodDecl()->
getIdentifier()->isStr(
"allocate"))
1282 S.
FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
1302 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
1303 S.
Note(VD->getLocation(), diag::note_declared_at);
1323 S.
FFDiag(E, diag::note_constexpr_modify_global);
1329 const CallExpr *CE,
unsigned ArgSize) {
1332 unsigned Offset = 0;
1334 for (
const Expr *Arg : Args) {
1335 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
1339 S.
CCEDiag(Loc, diag::note_non_null_attribute_failed);
1361 S.
FFDiag(Loc, diag::note_constexpr_double_destroy);
1368 assert(!
Dtor->isTrivial());
1374 return Call(S, OpPC, DtorFunc, 0);
1397 for (
int I =
static_cast<int>(N) - 1; I >= 0; --I) {
1411 return DD->isVirtual();
1416 bool IsGlobalDelete) {
1422 const Expr *Source =
nullptr;
1423 const Block *BlockToDelete =
nullptr;
1441 BlockToDelete = Ptr.
block();
1445 if (std::optional<DynamicAllocator::Form> AllocForm =
1457 if (!DeleteIsArrayForm && Ptr.
getType() != InitialType &&
1460 diag::note_constexpr_delete_base_nonvirt_dtor)
1461 << InitialType << Ptr.
getType();
1468 S.
FFDiag(Loc, diag::note_constexpr_delete_subobject)
1478 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1483 return DD->isVirtual() ? DD->getOperatorDelete() :
nullptr;
1493 diag::note_constexpr_new_non_replaceable)
1500 assert(BlockToDelete);
1506 if (!Allocator.
deallocate(Source, BlockToDelete)) {
1509 S.
FFDiag(Loc, diag::note_constexpr_double_delete);
1526 S.
CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1527 << llvm::toString(
Value, 10) <<
Min.getSExtValue() <<
Max.getSExtValue()
1531 S.
CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1532 << llvm::toString(
Value, 10) <<
Min.getZExtValue() <<
Max.getZExtValue()
1563 S.
FFDiag(E, diag::note_constexpr_nonliteral) << E->
getType();
1565 S.
FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
1570 const Pointer &Ptr,
unsigned Offset) {
1576 const Record::Field *Field = R->findField(Offset);
1580 std::string TypeIdStr;
1581 llvm::raw_string_ostream SS(TypeIdStr);
1586 SS << Field->Decl->getNameAsString();
1589 diag::note_constexpr_access_unreadable_object)
1608 if (std::optional<IntPointer> IntPtr =
1646 uint32_t
Off,
bool NullOK) {
1676 return getBase(S, OpPC, Ptr.narrow(),
Off,
true);
1680 return getBase(S, OpPC, Ptr.narrow(),
Off, NullOK);
1684 const Type *TargetType) {
1708 assert(TargetRecord);
1714 << MostDerivedType <<
QualType(TargetType, 0);
1724 assert(
Func->isConstructor());
1726 if (
Func->getParentDecl()->isInvalidDecl())
1742 <<
Func->getParentDecl();
1752 S.
FFDiag(ND->getLocation(), diag::note_constexpr_destroy_out_of_lifetime)
1753 << ND->getNameAsString();
1756 diag::note_constexpr_destroy_out_of_lifetime)
1783 S.
FFDiag(E, diag::note_constexpr_modify_global);
1806 bool SrcIsVoidPtr) {
1810 if (!Ptr.isBlockPointer())
1817 bool HasValidResult = !Ptr.isZero();
1819 if (HasValidResult) {
1829 S.
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
1830 << E->getSubExpr()->getType() << S.
getLangOpts().CPlusPlus26
1831 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
1834 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
1835 << diag::ConstexprInvalidCastKind::CastFrom <<
"'void *'"
1844 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
1862 uint32_t VarArgSize) {
1863 if (
Func->hasThisPointer()) {
1864 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1874 Func->isLambdaCallOperator())) {
1876 Func->isDestructor()))
1884 if (!
Func->isFullyCompiled())
1900 assert(S.
Current == FrameBefore);
1911 uint32_t VarArgSize) {
1918 auto cleanup = [&]() ->
bool {
1923 bool InstancePtrTracked =
false;
1924 if (
Func->hasThisPointer()) {
1925 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1942 Func->isLambdaCallOperator()) {
1943 assert(ThisPtr.
isZero());
1946 Func->isDestructor()))
1949 if (
Func->isCopyOrMoveOperator() ||
Func->isCopyOrMoveConstructor()) {
1956 if (!
Func->isConstructor() && !
Func->isDestructor() &&
1966 InstancePtrTracked = (
Func->isConstructor() ||
Func->isDestructor());
1967 if (InstancePtrTracked)
1971 if (!
Func->isFullyCompiled())
1994 if (InstancePtrTracked)
2005 assert(S.
Current == FrameBefore);
2015 auto depth = [](
PtrView V) ->
unsigned {
2017 while (!
V.isRoot()) {
2034 assert(depth(TypePtr) >= depth(InitPtr));
2035 unsigned D = depth(TypePtr) - depth(InitPtr);
2036 for (
unsigned I = 0; I != D; ++I)
2047 S.
FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
2054 DynamicDecl =
DynamicType->getPointeeCXXRecordDecl();
2062 return DynamicDecl !=
nullptr;
2066struct DynamicCastResult {
2070 bool valid()
const {
return !
Ambiguous && Offset; }
2072 void setOffset(
unsigned O) {
2080 void merge(DynamicCastResult
C) {
2081 Ambiguous |=
C.Ambiguous;
2095 DynamicCastResult Res;
2100 for (
const Record::Base &B : R->bases()) {
2103 N.Offset = *N.Offset + B.Offset;
2111 bool IsReferenceCast) {
2115 if (Ptr.isConstexprUnknown()) {
2120 S.
FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
2125 if (!Ptr.isBlockPointer() || !Ptr.getRecord())
2128 if (!Ptr.isInitialized())
2139 assert(LimitedPtr.
block() == Ptr.block());
2146 if (TargetType->isVoidType()) {
2151 assert(!TargetType.isNull());
2152 assert(!TargetType->isVoidType());
2153 assert(TargetType->isRecordType());
2160 assert(P.getRecord());
2164 auto baseIsPrivate = [&](
PtrView P) ->
bool {
2165 if (P.isRoot() || !P.isBaseClass())
2169 getRecord(P.getBase())->isDerivedFrom(getRecord(P), Paths);
2174 return llvm::all_of(Paths, [](
const CXXBasePath &P) ->
bool {
2180 DiagPrivateBase = 0,
2183 DiagPrivateSibling = 3
2186 auto diag = [&](
int DiagKind,
QualType ResultType) ->
bool {
2188 if (!IsReferenceCast) {
2194 diag::note_constexpr_dynamic_cast_to_reference_failed)
2195 << DiagKind << ResultType <<
DynamicType << TargetType;
2204 getRecord(LimitedPtr)
2205 ->isDerivedFrom(TargetType->getAsCXXRecordDecl(), Paths);
2206 if (std::distance(Paths.
begin(), Paths.
end()) == 0 &&
2207 !typesMatch(LimitedPtr.
getType(), TargetType)) {
2208 return diag(DiagNoBase, TargetType);
2213 if (baseIsPrivate(Ptr.view()))
2214 return diag(DiagPrivateBase, Ptr.getType());
2216 std::optional<PtrView>
Result;
2218 for (
PtrView Iter = Ptr.view();;) {
2219 if (Iter.isRoot() || !Iter.isBaseClass())
2222 if (typesMatch(TargetType, Iter.getType())) {
2227 Iter = Iter.getBase();
2233 if (baseIsPrivate(*
Result))
2234 return diag(DiagPrivateBase,
Result->getType());
2241 for (
PtrView Iter = LimitedPtr;;) {
2247 Result = Iter.atField(*R.Offset);
2249 }
else if (R.Ambiguous) {
2255 Iter = Iter.getBase();
2256 if (Iter.isRoot() || !Iter.isBaseClass())
2261 return diag(DiagAmbiguous, TargetType);
2265 if (baseIsPrivate(*
Result))
2266 return diag(DiagPrivateSibling, TargetType);
2272 return diag(DiagNoBase, TargetType);
2276 uint32_t VarArgSize) {
2277 assert(
Func->hasThisPointer());
2278 assert(
Func->isVirtual());
2279 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2291 assert(DynamicDecl);
2293 const auto *StaticDecl =
Func->getParentDecl();
2297 if (StaticDecl != DynamicDecl) {
2304 Overrider = InitialFunction;
2314 S.
Note(Callee->getLocation(), diag::note_declared_at);
2318 if (Overrider != InitialFunction) {
2331 if (
Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
2339 if (!
Call(S, OpPC,
Func, VarArgSize))
2344 if (Overrider != InitialFunction &&
2346 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
2354 OverriderPointeeType))
2371 uint32_t BuiltinID) {
2374 if (BuiltinID == Builtin::BI__builtin_operator_new &&
2438 return CallVirt(S, OpPC, F, VarArgSize);
2440 return Call(S, OpPC, F, VarArgSize);
2447 for (
const Record::Field &Fi : R->fields()) {
2457 for (
unsigned I = 0; I != FieldDesc->getNumElems(); ++I) {
2473 if (!Ptr.isBlockPointer())
2484 if (!Ptr.isBlockPointer())
2495 for (
const Record::Field &Fi : R->fields())
2505 for (
unsigned I = 0; I != FieldDesc->getNumElems(); ++I)
2542 std::optional<uint64_t> ArraySize) {
2546 auto directBaseIsUnion = [](
const Pointer &Ptr) ->
bool {
2547 if (Ptr.isArrayElement())
2549 const Record *R = Ptr.getBase().getRecord();
2550 return R && R->isUnion();
2553 if (Ptr.inUnion() && directBaseIsUnion(Ptr))
2562 if (!Ptr.isBlockPointer())
2572 if (!Ptr.block()->isAccessible()) {
2583 for (
PtrView P = Ptr.view();;) {
2606 QualType StorageType = Ptr.getType();
2610 NewExpr->getAllocatedType(),
2611 APInt(64,
static_cast<uint64_t
>(*ArraySize),
false),
nullptr,
2614 AllocType = NewExpr->getAllocatedType();
2617 if (AllocType->
isArrayType() && Ptr.isArrayElement() &&
2618 Ptr.expand().getIndex() == 0) {
2626 StorageType = Ptr.expand().getArray().getType();
2633 diag::note_constexpr_placement_new_wrong_type)
2634 << StorageType << AllocType;
2639 if (Ptr.inUnion() && !Ptr.isActive() && !directBaseIsUnion(Ptr))
2648 if (
const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
2649 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
2651 if (NewExpr->getNumPlacementArgs() > 0) {
2662 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
2664 diag::note_constexpr_new_non_replaceable)
2668 NewExpr->getNumPlacementArgs() == 1 &&
2669 !OperatorNew->isReservedGlobalPlacementOperator()) {
2679 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
2681 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
2683 diag::note_constexpr_new_non_replaceable)
2697 E->
getExprLoc(), diag::warn_fixedpoint_constant_overflow)
2700 S.
CCEDiag(E, diag::note_constexpr_overflow)
2708 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
2714 const Pointer &Ptr,
unsigned BitWidth) {
2716 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
2768 bool TargetIsUCharOrByte) {
2770 if (!HasIndeterminateBits)
2774 if (TargetIsUCharOrByte)
2779 S.
FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
2791 if (!ID.IsInitialized) {
2794 diag::note_constexpr_use_uninit_reference);
2811 if (!P.isBlockPointer())
2814 if (P.isConstexprUnknown()) {
2819 S.
FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
2825 CanQualType T = P.stripBaseCasts().getType()->getCanonicalTypeUnqualified();
2831 Func && (
Func->isConstructor() ||
Func->isDestructor()) &&
2832 P.block() ==
Frame->getThis().block()) {
2834 Func->getParentDecl());
2846 S.
CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
2847 << E->getExprOperand()->getType()
2848 << E->getExprOperand()->getSourceRange();
2862 StringRef LHSStr(LHSLit->getBytes());
2863 unsigned LHSLength = LHSStr.size();
2864 StringRef RHSStr(RHSLit->getBytes());
2865 unsigned RHSLength = RHSStr.size();
2867 int32_t IndexDiff = RHSOffset - LHSOffset;
2868 if (IndexDiff < 0) {
2869 if (
static_cast<int32_t
>(LHSLength) < -IndexDiff)
2871 LHSStr = LHSStr.drop_front(-IndexDiff);
2873 if (
static_cast<int32_t
>(RHSLength) < IndexDiff)
2875 RHSStr = RHSStr.drop_front(IndexDiff);
2878 unsigned ShorterCharWidth;
2881 if (LHSLength < RHSLength) {
2894 for (
unsigned NullByte : llvm::seq(ShorterCharWidth)) {
2895 if (Shorter.size() + NullByte >= Longer.size())
2897 if (Longer[Shorter.size() + NullByte])
2900 return Shorter == Longer.take_front(Shorter.size());
2906 if (!Val.singleWord()) {
2907 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
2908 Val.take(NewMemory);
2912 if (!Val.singleWord()) {
2913 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
2914 Val.take(NewMemory);
2918 if (!Val.singleWord()) {
2919 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
2920 Val.take(NewMemory);
2926 std::copy_n(Val.path(), PathLength, NewPath);
2927 Val.takePath(NewPath);
2931template <
typename T>
2934 if constexpr (std::is_same_v<T, MemberPointer>) {
2938 std::copy_n(Val.path(), PathLength, NewPath);
2939 Val.takePath(NewPath);
2941 auto &Val = Ptr.
deref<
T>();
2942 if (!Val.singleWord()) {
2943 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
2944 Val.take(NewMemory);
2951 for (
const Record::Field &Fi : R->fields()) {
2952 if (Fi.Desc->isPrimitive()) {
2954 copyPrimitiveMemory<T>(S, Ptr.atField(Fi.Offset));
2964 unsigned NumElems = D->getNumElems();
2968 if (D->isPrimitiveArray()) {
2972 assert(NumElems >= 1);
2974 bool AllSingleWord =
true;
2976 if (!EP.
deref<
T>().singleWord()) {
2978 AllSingleWord =
false;
2983 for (
unsigned I = 1; I != D->getNumElems(); ++I) {
2988 assert(D->isCompositeArray());
2989 for (
unsigned I = 0; I != D->getNumElems(); ++I) {
3014 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3015 << diag::ConstexprInvalidCastKind::Reinterpret
3019 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3020 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3027 S.
FFDiag(E, diag::note_constexpr_access_volatile_type)
3028 <<
AK_Read << E->getSubExpr()->getType();
3036 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3037 << diag::ConstexprInvalidCastKind::Dynamic;
3040 llvm_unreachable(
"Unhandled CastKind");
3067 if (MemberPtr.getPathLength() >= 2)
3068 Expected = MemberPtr.getPathEntry(MemberPtr.getPathLength() - 2);
3070 Expected = MemberPtr.getRecordDecl();
3083 unsigned OldPathLength = MemberPtr.getPathLength();
3084 unsigned NewPathLength = OldPathLength - 1;
3085 bool IsDerivedMember = NewPathLength != 0;
3087 std::copy_n(MemberPtr.path(), NewPathLength, NewPath);
3090 NewPath, IsDerivedMember));
3098 bool IsDerivedMember) {
3099 unsigned OldPathLength = MemberPtr.getPathLength();
3100 unsigned NewPathLength = OldPathLength + 1;
3103 std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
3107 NewPath, IsDerivedMember));
3116 if (!Ptr.isDerivedMember() && Ptr.hasPath())
3119 bool IsDerivedMember = Ptr.isDerivedMember() || !Ptr.hasPath();
3128 if (!Ptr.isDerivedMember()) {
3145 if (!MP.isBaseCastPossible())
3156 const auto *FD = dyn_cast_if_present<FunctionDecl>(D);
3160 const auto *
Method = dyn_cast<CXXMethodDecl>(FD);
3167 if (!
Base.getRecord() ||
Base.getRecord()->getDecl() != MethodParent)
3184 unsigned NewPathLength = OldPathLength + 1;
3187 std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
3191 MemberPtr.withPath(NewPathLength, NewPath, IsDerived));
3195template <
bool Signed>
3197 uint32_t BitWidth, uint32_t FPOI) {
3202 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite() &&
3230 return Op == OP_RetVoid || Op == OP_RetValue || Op == OP_NoRet ||
3231 Op == OP_RetSint8 || Op == OP_RetUint8 || Op == OP_RetSint16 ||
3232 Op == OP_RetUint16 || Op == OP_RetSint32 || Op == OP_RetUint32 ||
3233 Op == OP_RetSint64 || Op == OP_RetUint64 || Op == OP_RetIntAP ||
3234 Op == OP_RetIntAPS || Op == OP_RetBool || Op == OP_RetFixedPoint ||
3235 Op == OP_RetPtr || Op == OP_RetMemberPtr || Op == OP_RetFloat ||
3236 Op == OP_EndSpeculation;
3245#define GET_INTERPFN_DISPATCHERS
3246#include "Opcodes.inc"
3247#undef GET_INTERPFN_DISPATCHERS
3252#define GET_INTERPFN_LIST
3253#include "Opcodes.inc"
3254#undef GET_INTERPFN_LIST
3276 return InterpNext(S);
3304 [[maybe_unused]]
CodePtr PCBefore = S.
PC;
3305 size_t StackSizeBefore = S.
Stk.
size();
3311 assert(DepthBefore >= 1);
3314 auto SpeculativeInterp = [&S]() ->
bool {
3337 if (SpeculativeInterp()) {
3342 assert(S.
Stk.
size() == StackSizeBefore);
3348 assert(S.
Stk.
size() == StackSizeBefore);
Defines the clang::ASTContext interface.
Defines the clang::Expr interface and subclasses for C++ expressions.
static const FunctionDecl * getVirtualOperatorDelete(QualType T)
static PRESERVE_NONE bool RetValue(InterpState &S)
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK)
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
static bool Jf(InterpState &S, CodePtr OpPC, int32_t Offset)
static bool Jmp(InterpState &S, CodePtr OpPC, int32_t Offset)
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, const ValueDecl *D, AccessKinds AK=AK_Read)
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC, const ValueDecl *VD, AccessKinds AK=AK_Read)
static bool isModification(AccessKinds AK)
static void noteValueLocation(InterpState &S, const Block *B)
static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
static bool Jt(InterpState &S, CodePtr OpPC, int32_t Offset)
static StringRef getIdentifier(const Token &Tok)
#define TYPE_SWITCH_ALLOC(Expr, B)
#define TYPE_SWITCH(Expr, B)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U) const
Determine whether two function types are the same, ignoring exception specifications in cases where t...
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
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.
const clang::PrintingPolicy & getPrintingPolicy() const
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
bool hasSimilarType(QualType T1, QualType T2) const
Determine if two types are similar, according to the C++ rules.
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
CanQualType getCanonicalTagType(const TagDecl *TD) const
QualType getElementType() const
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
AccessSpecifier Access
The access along this inheritance path.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Expr ** getArgs()
Retrieve the call arguments.
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
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
static FPOptions getFromOpaqueInt(storage_type Value)
RoundingMode getRoundingMode() const
Represents a member of a struct/union/class.
Represents a function declaration or definition.
QualType getReturnType() const
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.
bool isUsableAsGlobalAllocationFunctionInConstantEvaluation(UnsignedOrNone *AlignmentParam=nullptr, bool *IsNothrow=nullptr) const
Determines whether this function is one of the replaceable global allocation functions described in i...
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
@ FPE_Ignore
Assume that floating-point exceptions are masked.
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
void addConst()
Add the const type qualifier to this QualType.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
bool isConstQualified() const
Determine whether this type is const-qualified.
Represents a struct/union/class.
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...
TagDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isAnyComplexType() const
bool isPointerOrReferenceType() const
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
bool isStaticDataMember() const
Determines whether this is a static data member.
A memory block, either on the stack or in the heap.
unsigned getSize() const
Returns the size of the block.
bool isExtern() const
Checks if the block is extern.
const Descriptor * getDescriptor() const
Returns the block's descriptor.
bool isStatic() const
Checks if the block has static storage duration.
bool isTemporary() const
Checks if the block is temporary.
std::byte * rawData()
Returns a pointer to the raw data, including metadata.
bool isInitialized() const
Returns whether the data of this block has been initialized via invoking the Ctor func.
UnsignedOrNone getDeclID() const
Returns the declaration ID.
unsigned getEvalID() const
The Evaluation ID this block was created in.
bool isAccessible() const
Pointer into the code segment.
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
Compilation context for expressions.
unsigned collectBaseOffset(const RecordDecl *BaseDecl, const RecordDecl *DerivedDecl) const
const Record * getRecord(const RecordDecl *D) const
const Function * getOrCreateFunction(const FunctionDecl *FuncDecl)
ASTContext & getASTContext() const
Returns the AST context.
OptPrimType classify(QualType T) const
Classifies a type.
const CXXMethodDecl * getOverridingFunction(const CXXRecordDecl *DynamicDecl, const CXXRecordDecl *StaticDecl, const CXXMethodDecl *InitialFunction) const
Manages dynamic memory allocations done during bytecode interpretation.
std::optional< Form > getAllocationForm(const Expr *Source) const
Checks whether the allocation done at the given source is an array allocation.
bool deallocate(const Expr *Source, const Block *BlockToDelete)
Deallocate the given source+block combination.
Wrapper around fixed point types.
std::string toDiagnosticString(const ASTContext &Ctx) const
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
APFloat::opStatus convertToInteger(APSInt &Result) const
APFloat getAPFloat() const
Base class for stack frames, shared between VM and walker.
bool hasExplicitThisPointer() const
Scope & getScope(unsigned Idx)
Returns a specific scope.
CodePtr getCodeBegin() const
Returns a pointer to the start of the code.
bool isDestructor() const
Checks if the function is a destructor.
bool isVirtual() const
Checks if the function is virtual.
bool hasNonNullAttr() const
bool isFullyCompiled() const
Checks if the function is fully done compiling.
bool isConstructor() const
Checks if the function is a constructor.
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
bool hasBody() const
Checks if the function already has a body attached.
unsigned getWrittenArgSize() const
unsigned getArgSize() const
Returns the size of the argument stack.
bool isLambdaStaticInvoker() const
Returns whether this function is a lambda static invoker, which we generate custom byte code for.
bool isValid() const
Checks if the function is valid to call.
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
void copy(const APInt &V)
Wrapper around numeric types.
static std::enable_if_t<!std::is_same_v< ValT, IntegralKind >, Integral > from(ValT V, unsigned NumBits=0)
Frame storing local variables.
static void free(InterpFrame *F)
const Expr * getExpr(CodePtr PC) const
InterpFrame * Caller
The frame of the previous function.
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
Block * getLocalBlock(unsigned Offset) const
SourceLocation getLocation(CodePtr PC) const
const Pointer & getThis() const
Returns the 'this' pointer.
unsigned MSVCConstexprAllowed
const Function * getFunction() const
Returns the current function.
SourceRange getRange(CodePtr PC) const
bool isBottomFrame() const
unsigned getArgSize() const
bool isRoot() const
Checks if the frame is a root frame - return should quit the interpreter.
bool hasThisPointer() const
Pointer getLocalPointer(unsigned Offset) const
Returns a pointer to a local variables.
unsigned getDepth() const
void destroy(unsigned Idx)
Invokes the destructors for a scope.
bool isStdFunction() const
static size_t allocSize(const Function *F)
Returns the number of bytes needed to allocate an InterpFrame for the given function.
void clearTo(size_t NewSize)
T pop()
Returns the value from the top of the stack and removes it.
void push(Tys &&...Args)
Constructs a value in place on the top of the stack.
size_t size() const
Returns the size of the stack in bytes.
void discard()
Discards the top value from the stack.
T & peek() const
Returns a reference to the value on the top of the stack.
bool lifetimeStartedInEvaluation(const Block *B) const
Context & getContext() const
bool initializingBlock(const Block *B) const
DynamicAllocator & getAllocator()
Context & Ctx
Interpreter Context.
bool noteStep(CodePtr OpPC)
Note that a step has been executed.
const unsigned EvalID
ID identifying this evaluation.
InterpStack & Stk
Temporary stack.
bool checkingConstantDestruction() const
Return if we're checking if a global variable has a constant destructor.
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
InterpFrame * Current
The current frame.
const CXXRecordDecl ** allocMemberPointerPath(unsigned Length)
llvm::SmallVector< PtrView > InitializingPtrs
List of blocks we're currently running either constructors or destructors for.
T allocAP(unsigned BitWidth)
unsigned SpeculationDepth
StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const
bool inConstantContext() const
Program & P
Reference to the module containing all bytecode.
unsigned getPathLength() const
Return the length of the cast path.
PrimType value_or(PrimType PT) const
A pointer to a memory block, live or dead.
Pointer narrow() const
Restricts the scope of an array element pointer.
UnsignedOrNone getDeclID() const
Returns the declaration ID.
Pointer stripBaseCasts() const
Strip base casts from this Pointer.
bool isVolatile() const
Checks if an object or a subfield is volatile.
bool isInitialized() const
Checks if an object was initialized.
bool isStatic() const
Checks if the storage is static.
bool isDynamic() const
Checks if the storage has been dynamically allocated.
bool isZeroSizeArray() const
Checks if the pointer is pointing to a zero-size array.
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
bool isDummy() const
Checks if the pointer points to a dummy value.
Pointer atFieldSub(unsigned Off) const
Subtract the given offset from the current Base and Offset of the pointer.
bool isExtern() const
Checks if the storage is extern.
int64_t getIndex() const
Returns the index into an array.
bool isActive() const
Checks if the object is active.
bool isConst() const
Checks if an object or a subfield is mutable.
Pointer atField(unsigned Off) const
Creates a pointer to a field.
bool isMutable() const
Checks if the field is mutable.
bool isConstInMutable() const
unsigned getNumElems() const
Returns the number of elements.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
const TypeidPointer & asTypeidPointer() const
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 pointsToStringLiteral() const
void initialize() const
Initializes a field.
bool isArrayRoot() const
Whether this array refers to an array, but not to the first element.
bool isLive() const
Checks if the pointer is live.
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
uint64_t getByteOffset() const
Returns the byte offset from the start.
bool isTypeidPointer() const
std::string toDiagnosticString(const ASTContext &Ctx) const
Converts the pointer to a string usable in diagnostics.
bool isZero() const
Checks if the pointer is null.
bool isConstexprUnknown() const
const IntPointer & asIntPointer() const
bool isRoot() const
Pointer points directly to a block.
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
void activate() const
Activates a field.
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
bool isPastEnd() const
Checks if the pointer points past the end of the object.
const FieldDecl * getField() const
Returns the field information.
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
void startLifetime() const
Start the lifetime of this pointer.
bool isBlockPointer() const
const FunctionPointer & asFunctionPointer() const
const Block * block() const
bool isFunctionPointer() const
Pointer getDeclPtr() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
Lifetime getLifetime() const
bool isField() const
Checks if the item is a field in an object.
const Record * getRecord() const
Returns the record descriptor of a class.
UnsignedOrNone getCurrentDecl() const
Returns the current declaration ID.
Structure/Class descriptor.
const RecordDecl * getDecl() const
Returns the underlying declaration.
unsigned getNumVirtualBases() const
llvm::iterator_range< LocalVectorTy::const_reverse_iterator > locals_reverse() const
Describes the statement/declaration an opcode was generated from.
bool checkingForUndefinedBehavior() const
Are we checking an expression for overflow?
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
ASTContext & getASTContext() const
bool noteUndefinedBehavior() const
Note that we hit something that was technically undefined behavior, but that we can evaluate past it ...
OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation does not produce a C++11 core constant expression.
const LangOptions & getLangOpts() const
bool checkingPotentialConstantExpression() const
Are we checking whether the expression is a potential constant expression?
Defines the clang::TargetInfo interface.
bool arePotentiallyOverlappingStringLiterals(const Pointer &LHS, const Pointer &RHS)
bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off)
bool GetMemberPtrBase(InterpState &S)
bool PseudoDtor(InterpState &S, CodePtr OpPC)
Ends the lifetime of the pop'd pointer.
static bool CheckCallDepth(InterpState &S, CodePtr OpPC)
static constexpr bool OpReturns(Opcode Op)
const InterpFn InterpFunctions[]
static bool diagnoseCallableDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *DiagDecl)
bool GetTypeid(InterpState &S, const Type *TypePtr, const Type *TypeInfoType)
Typeid support.
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.
bool CheckFunctionDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *FD)
Opcode. Check if the function decl can be called at compile time.
bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue)
static bool appendToMemberPointer(InterpState &S, const MemberPointer &MemberPtr, int32_t BaseOffset, const RecordDecl *BaseDecl, bool IsDerivedMember)
static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
bool StartThisLifetime(InterpState &S)
void cleanupAfterFunctionCall(InterpState &S, const Function *Func)
static bool runRecordDestructor(InterpState &S, CodePtr OpPC, const Pointer &BasePtr, const Descriptor *Desc)
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc, AccessKinds AK)
Checks if the Descriptor is of a constexpr or const global variable.
bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType)
bool LT(InterpState &S, CodePtr OpPC)
bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t Offset)
Checks if the dowcast using the given offset is possible with the given pointer.
bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC, DynamicAllocator::Form AllocForm, DynamicAllocator::Form DeleteForm, const Descriptor *D, const Expr *NewExpr)
Diagnose mismatched new[]/delete or new/delete[] pairs.
static void setLifeStateRecurse(PtrView Ptr, Lifetime L)
bool PushIgnoreDiags(InterpState &S)
bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B)
Checks a direct load of a primitive value from a global or local variable.
bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR)
We aleady know the given DeclRefExpr is invalid for some reason, now figure out why and print appropr...
bool EndLifetime(InterpState &S, CodePtr OpPC)
Ends the lifetime of the peek'd pointer.
static bool getDynamicDecl(InterpState &S, CodePtr OpPC, PtrView TypePtr, const CXXRecordDecl *&DynamicDecl)
bool CastMemberPtrDerivedPop(InterpState &S, int32_t Off, const RecordDecl *BaseDecl)
BaseToDerivedMemberPointer.
static DynamicCastResult findRecordBase(const ASTContext &Ctx, const Record *R, QualType Needle)
static bool CheckWeak(InterpState &S, CodePtr OpPC, const Block *B)
static void copyPrimitiveMemory(InterpState &S, PtrView Ptr, PrimType T)
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 CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK, bool WillActivate)
static bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *CE, unsigned ArgSize)
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)
bool PopIgnoreDiags(InterpState &S)
bool GetMemberPtrDecl(InterpState &S)
bool handleReference(InterpState &S, CodePtr OpPC, Block *B)
bool CheckBitCast(InterpState &S, CodePtr OpPC, const Type *TargetType, bool SrcIsVoidPtr)
bool CopyMemberPtrPath(InterpState &S, const RecordDecl *Entry, bool IsDerived)
Just append the given Entry to the MemberPointer's path.
static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t Off)
static void startLifetimeRecurse(PtrView Ptr)
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.
static bool getBase(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t Off, bool NullOK)
static void finishGlobalRecurse(InterpState &S, PtrView Ptr)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
bool CheckBCPResult(InterpState &S, const Pointer &Ptr)
PRESERVE_NONE bool EndSpeculation(InterpState &S)
bool diagnoseShiftFailure(InterpState &S, CodePtr OpPC, ShiftFailure Failure, const APSInt *Value, unsigned Bits)
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 GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK, const Type *TargetType)
bool DiagTypeid(InterpState &S, CodePtr OpPC)
bool diagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
This is not used by any of the opcodes directly.
static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func, const Pointer &ThisPtr)
void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED, const APSInt &Value)
bool isConstexprUnknown(const Block *B)
bool StartThisLifetime1(InterpState &S)
bool RVOPtr(InterpState &S)
bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR, bool InitializerFailed)
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source, const Pointer &Ptr)
Check the source of the pointer passed to delete/delete[] has actually been heap allocated by us.
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result, APFloat::opStatus Status, FPOptions FPO)
Checks if the result of a floating-point operation is valid in the current context.
PrimType
Enumeration of the primitive types of the VM.
static bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr, bool IsCtor, bool IsDtor)
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, uint32_t BuiltinID)
Interpret a builtin function.
bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
constexpr bool needsAlloc()
bool(*)(InterpState &) PRESERVE_NONE InterpFn
bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index)
bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK)
Checks if a pointer is a dummy pointer.
static bool diagnoseOutOfLifetimeDestroy(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
static bool floatAPCast(InterpState &S, CodePtr OpPC, const Floating &F, uint32_t BitWidth, uint32_t FPOI)
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 checkDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
bool CheckRange(InterpState &S, CodePtr OpPC, PtrView Ptr, AccessKinds AK)
Checks if a pointer is in range.
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 CheckFloatStatus(InterpState &S, CodePtr OpPC, APFloat::opStatus Status, FPOptions FPO)
Check if the given floating-point evaluation status is allowed for compile-time constant folding duri...
bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off)
static void compileFunction(InterpState &S, const Function *Func)
bool CheckThis(InterpState &S, CodePtr OpPC)
Checks the 'this' pointer.
bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth, uint32_t FPOI)
bool CheckIntegralAddressCast(InterpState &S, CodePtr OpPC, unsigned BitWidth)
bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I)
bool CheckMutable(InterpState &S, CodePtr OpPC, PtrView Ptr, AccessKinds AK)
Checks if a pointer points to a mutable field.
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm, bool IsGlobalDelete)
bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E)
bool CallBI(InterpState &S, CodePtr OpPC, const CallExpr *CE, uint32_t BuiltinID)
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B)
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
static bool CheckLifetime(InterpState &S, CodePtr OpPC, Lifetime LT, const Block *B, AccessKinds AK)
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr, bool WillBeActivated)
Checks if a value can be stored in a block.
bool FinishInitGlobal(InterpState &S)
bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK)
llvm::BitVector collectNonNullArgs(const FunctionDecl *F, ArrayRef< const Expr * > Args)
static bool castBackMemberPointer(InterpState &S, const MemberPointer &MemberPtr, int32_t BaseOffset, const RecordDecl *BaseDecl)
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, const CallExpr *CE)
bool CastFloatingIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth, uint32_t FPOI)
bool MarkDestroyed(InterpState &S, CodePtr OpPC)
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 GetMemberPtr(InterpState &S, const ValueDecl *D)
static PRESERVE_NONE bool BCP(InterpState &S, CodePtr OpPC, int32_t Offset, PrimType PT)
This is used to implement speculative execution via __builtin_constant_p when we generate bytecode.
bool CastMemberPtrBasePop(InterpState &S, int32_t Off, const RecordDecl *BaseDecl)
DerivedToBaseMemberPointer.
bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, bool Fatal)
bool DynamicCast(InterpState &S, CodePtr OpPC, const Type *DestTypePtr, bool IsReferenceCast)
static bool diagnoseTypeIdField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, unsigned Offset)
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
@ Ambiguous
Name lookup results in an ambiguity; use getAmbiguityKind to figure out what kind of ambiguity we hav...
@ Success
Annotation was successful.
CheckSubobjectKind
The order of this enum is important for diagnostics.
@ Result
The result type of a method or function.
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
OptionalUnsigned< unsigned > UnsignedOrNone
const FunctionProtoType * T
@ Off
Never emit colors regardless of the output stream.
U cast(CodeGen::Address addr)
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
Describes a memory block created by an allocation site.
const bool IsConst
Flag indicating if the block is mutable.
unsigned getNumElems() const
Returns the number of elements stored in the block.
bool isPrimitive() const
Checks if the descriptor is of a primitive.
bool hasTrivialDtor() const
Whether variables of this descriptor need their destructor called or not.
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
const ValueDecl * asValueDecl() const
const Decl * asDecl() const
const Descriptor *const ElemDesc
Descriptor of the array element.
unsigned getMetadataSize() const
Returns the size of the metadata.
SourceLocation getLocation() const
QualType getDataType(const ASTContext &Ctx) const
unsigned getElemDataSize() const
Returns the element data size, i.e.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
const VarDecl * asVarDecl() const
PrimType getPrimType() const
bool isRecord() const
Checks if the descriptor is of a record.
const bool IsTemporary
Flag indicating if the block is a temporary.
const Record *const ElemRecord
Pointer to the record, if block contains records.
const Expr * asExpr() const
bool isArray() const
Checks if the descriptor is of an array.
Descriptor used for global variables.
Inline descriptor embedded in structures and arrays.
std::optional< IntPointer > atOffset(const Context &Ctx, unsigned Offset) const
PtrView atField(unsigned Offset) const
const Record * getRecord() const
const Descriptor * getFieldDesc() const
const FieldDecl * getField() const
PtrView atIndex(unsigned Idx) const
void startLifetime() const
const Block * block() const
bool isOnePastEnd() const
void setLifeState(Lifetime L) const
Lifetime getLifetime() const
bool isZeroSizeArray() const
PtrView stripBaseCasts() const
const Type * TypeInfoType