26#include "llvm/ADT/ScopeExit.h"
27#include "llvm/ADT/StringExtras.h"
32#if __has_cpp_attribute(clang::musttail)
33#define MUSTTAIL [[clang::musttail]]
34#elif __has_cpp_attribute(msvc::musttail)
35#define MUSTTAIL [[msvc::musttail]]
36#elif __has_attribute(musttail)
37#define MUSTTAIL __attribute__((musttail))
44#if defined(_MSC_VER) || defined(__powerpc__) || !defined(MUSTTAIL) || \
45 defined(__i386__) || defined(__sparc__)
48#define USE_TAILCALLS 0
50#define USE_TAILCALLS 1
54 llvm::report_fatal_error(
"Interpreter cannot return values");
85 S.
FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
121 S.
FFDiag(Loc, diag::note_constexpr_access_unknown_variable, 1)
123 S.
Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
125 S.
FFDiag(Loc, diag::note_constexpr_function_param_value_unknown, 1) << D;
135 }
else if (
const auto *VD = dyn_cast<VarDecl>(D)) {
136 if (!VD->getAnyInitializer()) {
140 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
141 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()) {
179 S.
FFDiag(Loc, diag::note_constexpr_modify_global);
181 S.
FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
188 S.
getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
189 : diag::note_constexpr_ltor_non_integral,
201 const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
213 S.
FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
223 if (
auto ID = Ptr.getDeclID()) {
252 S.
CCEDiag(E, diag::note_constexpr_large_shift)
274 unsigned VariadicArgSize =
276 unsigned TargetStackSize = S.
Stk.
size() - VariadicArgSize;
277 while (S.
Stk.
size() != TargetStackSize) {
287 if (
Func->hasImplicitThisPointer())
310 if (Ptr.isFunctionPointer())
312 if (Ptr.isIntegralPointer())
314 if (Ptr.isTypeidPointer())
317 if (Ptr.getType()->isAnyComplexType())
320 if (
const Expr *
Base = Ptr.getRootExpr())
330 assert(Ptr.inUnion());
335 while (!
U.isRoot() && !
U.isActive()) {
340 if (
U.getRecord() &&
U.getRecord()->isAnonymousUnion())
347 assert(
C.getBase() ==
U);
361 if (!
U.getFieldDesc()->isUnion())
371 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(R->getDecl());
372 CXXRD && !CXXRD->hasTrivialDefaultConstructor()) {
384 assert(!
C.isActive());
385 const FieldDecl *InactiveField =
C.getField();
386 assert(InactiveField);
389 const Record *R =
U.getRecord();
390 assert(R && R->isUnion() &&
"Not a union");
393 for (
const Record::Field &F : R->fields()) {
394 PtrView Field =
U.atField(F.Offset);
395 if (Field.isActive()) {
396 ActiveField = Field.getField();
402 diag::note_constexpr_access_inactive_union_member)
403 << AK << InactiveField << !ActiveField << ActiveField;
411 if (!Ptr.isPastEnd() &&
412 (Ptr.isInitialized() ||
420 const auto *VD = Ptr.getDeclDesc()->asValueDecl();
427 if (!Ptr.isUnknownSizeArray())
430 S.
FFDiag(E, diag::note_constexpr_unsized_array_indexed);
442 S.
FFDiag(Src, diag::note_constexpr_access_null) << AK;
450 if (Ptr.isDynamic()) {
451 S.
FFDiag(Src, diag::note_constexpr_access_deleted_object) << AK;
453 S.
FFDiag(Src, diag::note_constexpr_access_uninit)
472 if (D->getType().isConstQualified())
486 if (
T->isIntegralOrEnumerationType()) {
498 ? diag::note_constexpr_ltor_non_constexpr
499 : diag::note_constexpr_ltor_non_integral,
502 S.
Note(D->getLocation(), diag::note_declared_at);
509 if (
T->isPointerOrReferenceType()) {
527 if (!Ptr.isStatic() || !Ptr.isBlockPointer())
529 if (!Ptr.getDeclID())
539 S.
FFDiag(Loc, diag::note_constexpr_null_subobject)
547 if (!Ptr.isElementPastEnd() && !Ptr.isZeroSizeArray())
550 S.
FFDiag(Loc, diag::note_constexpr_past_end_subobject)
557 if (!Ptr.isOnePastEnd())
561 S.
FFDiag(Loc, diag::note_constexpr_past_end_subobject)
568 uint32_t MinOffset = Ptr.block()->getMetadataSize();
569 uint32_t PtrOffset = Ptr.getByteOffset();
573 if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
582 QualType MostDerivedQT = Ptr.getDeclPtr().getType();
587 S.
CCEDiag(E, diag::note_constexpr_invalid_downcast)
588 << MostDerivedQT << TargetQT;
594 assert(Ptr.isLive() &&
"Pointer is not live");
598 if (Ptr.isMutable() && !Ptr.isConstInMutable())
601 if (!Ptr.isBlockPointer())
607 if (
V.block() != Ptr.block())
609 if (!
V.getFieldDesc()->IsConst) {
624 bool FoundProblem =
false;
625 for (
PtrView P = Ptr.view(); P !=
V; P = P.getBase()) {
626 if (P.getFieldDesc()->IsConst) {
642 if (!Ptr.getFieldDesc()->IsConst)
645 S.
FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
651 assert(Ptr.isLive() &&
"Pointer is not live");
652 if (!Ptr.isMutable())
668 MutablePtr = MutablePtr.
getBase();
672 S.
FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK << Field;
673 S.
Note(Field->getLocation(), diag::note_declared_at);
679 assert(Ptr.isLive());
681 if (!Ptr.isVolatile())
705 Loc = F->getLocation();
709 Loc = VD->getLocation();
714 Loc = E->getExprLoc();
718 diag::note_constexpr_access_volatile_obj, 1)
719 << AK << DiagKind << ND;
720 S.
Note(Loc, diag::note_constexpr_volatile_here) << DiagKind;
726 assert(Ptr.isLive());
727 assert(!Ptr.isInitialized());
729 Ptr.getLifetime(), AK);
747 VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
750 !(S.
getLangOpts().CPlusPlus23 && VD->getType()->isReferenceType())) {
759 S.
Note(VD->getFirstDecl()->getLocation(), diag::note_declared_at);
764 if (VD->getAnyInitializer()) {
766 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
767 S.
Note(VD->getLocation(), diag::note_declared_at);
797 return CheckLifetime(S, OpPC, Ptr.getLifetime(), Ptr.block(), AK);
808 S.
Note(VD->getLocation(), diag::note_declared_at);
839 diag::note_constexpr_access_volatile_obj, 1)
852 if (!Desc.IsInitialized)
862 diag::note_constexpr_access_volatile_obj, 1)
887 S.
FFDiag(Src, diag::note_constexpr_access_null) << AK;
891 if (!Ptr.isReadablePointerType())
894 if (Ptr.isBlockPointer() && !Ptr.block()->isAccessible()) {
910 if (!Ptr.isInitialized())
914 if (Ptr.isBlockPointer() && !
CheckTemporary(S, OpPC, Ptr.block(), AK))
924 if (Ptr.isBlockPointer() && !Ptr.isArrayRoot()) {
939 if (
const auto *CLE =
940 dyn_cast_if_present<CompoundLiteralExpr>(Desc->
asExpr())) {
941 if (
QualType CLETy = CLE->getType();
944 diag::note_invalid_subexpr_in_const_expr)
946 S.
Note(CLE->getExprLoc(), diag::note_declared_at);
957 assert(!Ptr.isZero());
958 if (!Ptr.isReadablePointerType())
961 if (Ptr.isBlockPointer() && !Ptr.block()->isAccessible()) {
978 if (!Ptr.isInitialized())
984 if (Ptr.isConstexprUnknown())
990 bool WillBeActivated) {
991 if (!Ptr.isBlockPointer() || Ptr.isZero())
994 if (!Ptr.block()->isAccessible()) {
1021 bool IsCtor,
bool IsDtor) {
1053 StringRef Name = DiagDecl->
getName();
1055 Name ==
"__assert_rtn" || Name ==
"__assert_fail" || Name ==
"_wassert";
1058 diag::note_constexpr_assert_failed);
1065 diag::note_invalid_subexpr_in_const_expr);
1071 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
1072 if (CD && CD->isInheritingConstructor()) {
1073 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
1074 if (!Inherited->isConstexpr())
1075 DiagDecl = CD = Inherited;
1080 if (CD && CD->getParent()->isInvalidDecl())
1086 if (CD && CD->isInheritingConstructor()) {
1089 << CD->getInheritedConstructor().getConstructor()->getParent();
1097 if (!IsDefined && !IsExtern && DiagDecl->
isConstexpr() &&
1107 diag::note_constexpr_invalid_function, 1)
1108 << DiagDecl->
isConstexpr() << (bool)CD << DiagDecl;
1124 S.
CCEDiag(Loc, diag::note_constexpr_virtual_call);
1148 diag::note_constexpr_depth_limit_exceeded)
1162 bool IsImplicit =
false;
1163 if (
const auto *TE = dyn_cast<CXXThisExpr>(E))
1164 IsImplicit = TE->isImplicit();
1165 S.
FFDiag(E, diag::note_constexpr_this) << IsImplicit;
1180 if ((Status & APFloat::opInexact) &&
1185 S.
FFDiag(E, diag::note_constexpr_dynamic_rounding);
1189 if ((Status != APFloat::opOK) &&
1192 FPO.getAllowFEnvAccess())) {
1194 S.
FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
1198 if ((Status & APFloat::opStatus::opInvalidOp) &&
1210 APFloat::opStatus Status,
FPOptions FPO) {
1221 S.
CCEDiag(E, diag::note_constexpr_float_arithmetic)
1234 S.
CCEDiag(E, diag::note_constexpr_new);
1241 const Expr *NewExpr) {
1242 if (AllocForm == DeleteForm)
1248 S.
FFDiag(E, diag::note_constexpr_new_delete_mismatch)
1249 <<
static_cast<int>(DeleteForm) <<
static_cast<int>(AllocForm)
1251 S.
Note(NewExpr->
getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
1259 if (isa_and_nonnull<CXXNewExpr>(Source))
1262 if (
const auto *CE = dyn_cast_if_present<CallExpr>(Source);
1263 CE && CE->getBuiltinCallee() == Builtin::BI__builtin_operator_new)
1266 if (
const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(Source);
1267 MCE && MCE->getMethodDecl()->
getIdentifier()->isStr(
"allocate"))
1272 S.
FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
1292 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
1293 S.
Note(VD->getLocation(), diag::note_declared_at);
1313 S.
FFDiag(E, diag::note_constexpr_modify_global);
1319 const CallExpr *CE,
unsigned ArgSize) {
1322 unsigned Offset = 0;
1324 for (
const Expr *Arg : Args) {
1325 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
1329 S.
CCEDiag(Loc, diag::note_non_null_attribute_failed);
1351 S.
FFDiag(Loc, diag::note_constexpr_double_destroy);
1358 assert(!
Dtor->isTrivial());
1364 return Call(S, OpPC, DtorFunc, 0);
1387 for (
int I =
static_cast<int>(N) - 1; I >= 0; --I) {
1401 return DD->isVirtual();
1406 bool IsGlobalDelete) {
1412 const Expr *Source =
nullptr;
1413 const Block *BlockToDelete =
nullptr;
1423 if (!Ptr.isBlockPointer())
1427 QualType InitialType = Ptr.getType();
1428 Ptr = Ptr.expand().stripBaseCasts();
1430 Source = Ptr.getRootExpr();
1431 BlockToDelete = Ptr.block();
1435 if (std::optional<DynamicAllocator::Form> AllocForm =
1447 if (!DeleteIsArrayForm && Ptr.getType() != InitialType &&
1450 diag::note_constexpr_delete_base_nonvirt_dtor)
1451 << InitialType << Ptr.getType();
1455 if (!Ptr.isRoot() || (Ptr.isOnePastEnd() && !Ptr.isZeroSizeArray()) ||
1456 (Ptr.isArrayElement() && Ptr.getIndex() != 0)) {
1458 S.
FFDiag(Loc, diag::note_constexpr_delete_subobject)
1459 << Ptr.toDiagnosticString(S.
getASTContext()) << Ptr.isOnePastEnd();
1468 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1469 QualType AllocType = Ptr.getType();
1473 return DD->isVirtual() ? DD->getOperatorDelete() :
nullptr;
1483 diag::note_constexpr_new_non_replaceable)
1490 assert(BlockToDelete);
1496 if (!Allocator.
deallocate(Source, BlockToDelete)) {
1499 S.
FFDiag(Loc, diag::note_constexpr_double_delete);
1516 S.
CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1517 << llvm::toString(
Value, 10) <<
Min.getSExtValue() <<
Max.getSExtValue()
1521 S.
CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1522 << llvm::toString(
Value, 10) <<
Min.getZExtValue() <<
Max.getZExtValue()
1553 S.
FFDiag(E, diag::note_constexpr_nonliteral) << E->
getType();
1555 S.
FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
1560 const Pointer &Ptr,
unsigned Offset) {
1561 assert(Ptr.isTypeidPointer());
1563 Ptr.asTypeidPointer().TypeInfoType->getAsRecordDecl());
1566 const Record::Field *Field = R->findField(Offset);
1570 std::string TypeIdStr;
1571 llvm::raw_string_ostream SS(TypeIdStr);
1573 QualType(Ptr.asTypeidPointer().TypePtr, 0)
1576 SS << Field->Decl->getNameAsString();
1579 diag::note_constexpr_access_unreadable_object)
1586 diag::note_constexpr_null_subobject);
1602 if (Ptr.isIntegralPointer()) {
1603 if (std::optional<IntPointer> IntPtr =
1604 Ptr.asIntPointer().atOffset(S.
Ctx,
Off)) {
1611 if (Ptr.isOpaquePointer()) {
1620 const Record::Field *F = R->findField(
Off);
1628 F->Decl->getType().getTypePtr()),
1629 Ptr.getByteOffset());
1634 if (!Ptr.isBlockPointer()) {
1637 if (Ptr.isTypeidPointer())
1643 if (!Ptr.getFieldDesc()->isRecord())
1646 if ((Ptr.getByteOffset() +
Off) >= Ptr.block()->getSize())
1664 uint32_t
Off,
bool NullOK) {
1668 if (Ptr.isOpaquePointer()) {
1676 const Record::Base *B = R->findBase(
Off);
1687 Ptr.getByteOffset());
1691 if (!Ptr.isBlockPointer()) {
1692 if (!Ptr.isIntegralPointer())
1703 if (!Ptr.getFieldDesc()->isRecord()) {
1717 return getBase(S, OpPC, Ptr.narrow(),
Off,
true);
1721 return getBase(S, OpPC, Ptr.narrow(),
Off, NullOK);
1725 const Type *TargetType) {
1730 if (!Ptr.isBlockPointer()) {
1738 if (!Ptr.getFieldDesc()->isRecord()) {
1748 const Record *TargetRecord = Ptr.atFieldSub(
Off).getRecord();
1749 assert(TargetRecord);
1753 QualType MostDerivedType = Ptr.getDeclDesc()->getType();
1755 << MostDerivedType <<
QualType(TargetType, 0);
1765 assert(
Func->isConstructor());
1767 if (
Func->getParentDecl()->isInvalidDecl())
1783 <<
Func->getParentDecl();
1791 if (
const Decl *D = Ptr.getDeclDesc()->asDecl()) {
1793 S.
FFDiag(ND->getLocation(), diag::note_constexpr_destroy_out_of_lifetime)
1794 << ND->getNameAsString();
1796 S.
FFDiag(Ptr.getDeclDesc()->getLocation(),
1797 diag::note_constexpr_destroy_out_of_lifetime)
1822 if (Ptr.block()->isStatic()) {
1824 S.
FFDiag(E, diag::note_constexpr_modify_global);
1847 bool SrcIsVoidPtr) {
1851 if (!Ptr.isBlockPointer())
1858 bool HasValidResult = !Ptr.isZero();
1860 if (HasValidResult) {
1870 S.
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
1871 << E->getSubExpr()->getType() << S.
getLangOpts().CPlusPlus26
1872 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
1875 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
1876 << diag::ConstexprInvalidCastKind::CastFrom <<
"'void *'"
1885 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
1903 uint32_t VarArgSize) {
1904 if (
Func->hasThisPointer()) {
1905 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1915 Func->isLambdaCallOperator())) {
1917 Func->isDestructor()))
1925 if (!
Func->isFullyCompiled())
1941 assert(S.
Current == FrameBefore);
1953 uint32_t VarArgSize) {
1960 auto cleanup = [&]() ->
bool {
1965 bool InstancePtrTracked =
false;
1966 if (
Func->hasThisPointer()) {
1967 size_t ArgSize =
Func->getArgSize() + VarArgSize;
1984 Func->isLambdaCallOperator()) {
1985 assert(ThisPtr.
isZero());
1988 Func->isDestructor()))
1991 if (
Func->isCopyOrMoveOperator() ||
Func->isCopyOrMoveConstructor()) {
1998 if (!
Func->isConstructor() && !
Func->isDestructor() &&
2008 InstancePtrTracked = (
Func->isConstructor() ||
Func->isDestructor());
2009 if (InstancePtrTracked)
2013 if (!
Func->isFullyCompiled())
2036 if (InstancePtrTracked)
2047 assert(S.
Current == FrameBefore);
2057 auto depth = [](
PtrView V) ->
unsigned {
2059 while (!
V.isRoot()) {
2076 assert(depth(TypePtr) >= depth(InitPtr));
2077 unsigned D = depth(TypePtr) - depth(InitPtr);
2078 for (
unsigned I = 0; I != D; ++I)
2089 S.
FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
2096 DynamicDecl =
DynamicType->getPointeeCXXRecordDecl();
2104 return DynamicDecl !=
nullptr;
2108struct DynamicCastResult {
2112 bool valid()
const {
return !
Ambiguous && Offset; }
2114 void setOffset(
unsigned O) {
2122 void merge(DynamicCastResult
C) {
2123 Ambiguous |=
C.Ambiguous;
2137 DynamicCastResult Res;
2142 for (
const Record::Base &B : R->bases()) {
2145 N.Offset = *N.Offset + B.Offset;
2153 bool IsReferenceCast) {
2157 if (Ptr.isConstexprUnknown()) {
2162 S.
FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
2167 if (!Ptr.isBlockPointer() || !Ptr.getRecord())
2170 if (!Ptr.isInitialized())
2178 LimitedPtr = Ptr.stripBaseCasts().view();
2181 assert(LimitedPtr.
block() == Ptr.block());
2188 if (TargetType->isVoidType()) {
2193 assert(!TargetType.isNull());
2194 assert(!TargetType->isVoidType());
2195 assert(TargetType->isRecordType());
2202 assert(P.getRecord());
2206 auto baseIsPrivate = [&](
PtrView P) ->
bool {
2207 if (P.isRoot() || !P.isBaseClass())
2211 getRecord(P.getBase())->isDerivedFrom(getRecord(P), Paths);
2216 return llvm::all_of(Paths, [](
const CXXBasePath &P) ->
bool {
2222 DiagPrivateBase = 0,
2225 DiagPrivateSibling = 3
2228 auto diag = [&](
int DiagKind,
QualType ResultType) ->
bool {
2230 if (!IsReferenceCast) {
2236 diag::note_constexpr_dynamic_cast_to_reference_failed)
2237 << DiagKind << ResultType <<
DynamicType << TargetType;
2246 getRecord(LimitedPtr)
2247 ->isDerivedFrom(TargetType->getAsCXXRecordDecl(), Paths);
2248 if (std::distance(Paths.
begin(), Paths.
end()) == 0 &&
2249 !typesMatch(LimitedPtr.
getType(), TargetType)) {
2250 return diag(DiagNoBase, TargetType);
2255 if (baseIsPrivate(Ptr.view()))
2256 return diag(DiagPrivateBase, Ptr.getType());
2258 std::optional<PtrView>
Result;
2260 for (
PtrView Iter = Ptr.view();;) {
2261 if (Iter.isRoot() || !Iter.isBaseClass())
2264 if (typesMatch(TargetType, Iter.getType())) {
2269 Iter = Iter.getBase();
2275 if (baseIsPrivate(*
Result))
2276 return diag(DiagPrivateBase,
Result->getType());
2283 for (
PtrView Iter = LimitedPtr;;) {
2289 Result = Iter.atField(*R.Offset);
2297 if (Iter.isRoot() || !Iter.isBaseClass())
2300 Iter = Iter.getBase();
2304 return diag(DiagAmbiguous, TargetType);
2308 if (baseIsPrivate(*
Result))
2309 return diag(DiagPrivateSibling, TargetType);
2315 return diag(DiagNoBase, TargetType);
2319 uint32_t VarArgSize) {
2320 assert(
Func->hasThisPointer());
2321 assert(
Func->isVirtual());
2322 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2334 assert(DynamicDecl);
2336 const auto *StaticDecl =
Func->getParentDecl();
2340 if (StaticDecl != DynamicDecl) {
2347 Overrider = InitialFunction;
2357 S.
Note(Callee->getLocation(), diag::note_declared_at);
2361 if (Overrider != InitialFunction) {
2374 if (
Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
2382 if (!
Call(S, OpPC,
Func, VarArgSize))
2387 if (Overrider != InitialFunction &&
2389 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
2397 OverriderPointeeType))
2414 uint32_t BuiltinID) {
2417 if (BuiltinID == Builtin::BI__builtin_operator_new &&
2434 if (!Ptr.isFunctionPointer())
2437 const Function *F = Ptr.asFunctionPointer().Func;
2481 return CallVirt(S, OpPC, F, VarArgSize);
2483 return Call(S, OpPC, F, VarArgSize);
2487 if (
const Record *R = Ptr.getRecord()) {
2488 Ptr.startLifetime();
2490 for (
const Record::Field &Fi : R->fields()) {
2491 PtrView FP = Ptr.atField(Fi.Offset);
2498 if (
const Descriptor *FieldDesc = Ptr.getFieldDesc();
2499 FieldDesc->isCompositeArray()) {
2500 for (
unsigned I = 0; I != FieldDesc->getNumElems(); ++I) {
2501 PtrView EP = Ptr.atIndex(I).narrow();
2508 Ptr.startLifetime();
2516 if (!Ptr.isBlockPointer())
2527 if (!Ptr.isBlockPointer())
2529 Ptr.startLifetime();
2536 if (
const Record *R = Ptr.getRecord()) {
2537 Ptr.setLifeState(L);
2538 for (
const Record::Field &Fi : R->fields())
2543 if (
const Descriptor *FieldDesc = Ptr.getFieldDesc();
2544 FieldDesc->isCompositeArray()) {
2546 if (Ptr.getFieldDesc()->isPrimitiveArray())
2548 for (
unsigned I = 0; I != FieldDesc->getNumElems(); ++I)
2553 Ptr.setLifeState(L);
2585 std::optional<uint64_t> ArraySize) {
2589 auto directBaseIsUnion = [](
const Pointer &Ptr) ->
bool {
2590 if (Ptr.isArrayElement())
2592 const Record *R = Ptr.getBase().getRecord();
2593 return R && R->isUnion();
2596 if (Ptr.inUnion() && directBaseIsUnion(Ptr))
2605 if (!Ptr.isBlockPointer())
2615 if (!Ptr.block()->isAccessible()) {
2626 for (
PtrView P = Ptr.view();;) {
2649 QualType StorageType = Ptr.getType();
2653 NewExpr->getAllocatedType(),
2654 APInt(64,
static_cast<uint64_t
>(*ArraySize),
false),
nullptr,
2657 AllocType = NewExpr->getAllocatedType();
2660 if (AllocType->
isArrayType() && Ptr.isArrayElement() &&
2661 Ptr.expand().getIndex() == 0) {
2669 StorageType = Ptr.expand().getArray().getType();
2676 diag::note_constexpr_placement_new_wrong_type)
2677 << StorageType << AllocType;
2682 if (Ptr.inUnion() && !Ptr.isActive() && !directBaseIsUnion(Ptr))
2691 if (
const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
2692 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
2694 if (NewExpr->getNumPlacementArgs() > 0) {
2705 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
2707 diag::note_constexpr_new_non_replaceable)
2711 NewExpr->getNumPlacementArgs() == 1 &&
2712 !OperatorNew->isReservedGlobalPlacementOperator()) {
2722 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
2724 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
2726 diag::note_constexpr_new_non_replaceable)
2740 E->
getExprLoc(), diag::warn_fixedpoint_constant_overflow)
2743 S.
CCEDiag(E, diag::note_constexpr_overflow)
2751 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
2757 const Pointer &Ptr,
unsigned BitWidth) {
2760 S.
CCEDiag(E, diag::note_constexpr_invalid_cast_ptrtoint)
2761 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2763 if (Ptr.isBlockPointer() && !Ptr.isZero())
2765 if (Ptr.isIntegralPointer())
2768 if (Ptr.isDummy()) {
2771 return Ptr.getIndex() == 0;
2774 if (!Ptr.isZero()) {
2794 Result.copy(
APInt(BitWidth, Ptr.getIntegerRepresentation()));
2807 Result.copy(
APInt(BitWidth, Ptr.getIntegerRepresentation()));
2814 bool TargetIsUCharOrByte) {
2816 if (!HasIndeterminateBits)
2820 if (TargetIsUCharOrByte)
2825 S.
FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
2837 if (!ID.IsInitialized) {
2840 diag::note_constexpr_use_uninit_reference);
2857 if (!P.isBlockPointer())
2860 if (P.isConstexprUnknown()) {
2865 S.
FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
2871 CanQualType T = P.stripBaseCasts().getType()->getCanonicalTypeUnqualified();
2877 Func && (
Func->isConstructor() ||
Func->isDestructor()) &&
2878 P.block() ==
Frame->getThis().block()) {
2880 Func->getParentDecl());
2892 S.
CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
2893 << E->getExprOperand()->getType()
2894 << E->getExprOperand()->getSourceRange();
2908 StringRef LHSStr(LHSLit->getBytes());
2909 unsigned LHSLength = LHSStr.size();
2910 StringRef RHSStr(RHSLit->getBytes());
2911 unsigned RHSLength = RHSStr.size();
2913 int32_t IndexDiff = RHSOffset - LHSOffset;
2914 if (IndexDiff < 0) {
2915 if (
static_cast<int32_t
>(LHSLength) < -IndexDiff)
2917 LHSStr = LHSStr.drop_front(-IndexDiff);
2919 if (
static_cast<int32_t
>(RHSLength) < IndexDiff)
2921 RHSStr = RHSStr.drop_front(IndexDiff);
2924 unsigned ShorterCharWidth;
2927 if (LHSLength < RHSLength) {
2928 ShorterCharWidth = LHSLit->getCharByteWidth();
2932 ShorterCharWidth = RHSLit->getCharByteWidth();
2940 for (
unsigned NullByte : llvm::seq(ShorterCharWidth)) {
2941 if (Shorter.size() + NullByte >= Longer.size())
2943 if (Longer[Shorter.size() + NullByte])
2946 return Shorter == Longer.take_front(Shorter.size());
2952 if (!Val.singleWord()) {
2953 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
2954 Val.take(NewMemory);
2958 if (!Val.singleWord()) {
2959 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
2960 Val.take(NewMemory);
2964 if (!Val.singleWord()) {
2965 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
2966 Val.take(NewMemory);
2972 std::copy_n(Val.path(), PathLength, NewPath);
2973 Val.takePath(NewPath);
2977template <
typename T>
2980 if constexpr (std::is_same_v<T, MemberPointer>) {
2984 std::copy_n(Val.path(), PathLength, NewPath);
2985 Val.takePath(NewPath);
2987 auto &Val = Ptr.deref<
T>();
2988 if (!Val.singleWord()) {
2989 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
2990 Val.take(NewMemory);
2996 if (
const Record *R = Ptr.getRecord()) {
2997 for (
const Record::Field &Fi : R->fields()) {
2998 if (Fi.Desc->isPrimitive()) {
3000 copyPrimitiveMemory<T>(S, Ptr.atField(Fi.Offset));
3009 if (
const Descriptor *D = Ptr.getFieldDesc(); D && D->isArray()) {
3010 unsigned NumElems = D->getNumElems();
3014 if (D->isPrimitiveArray()) {
3018 assert(NumElems >= 1);
3020 bool AllSingleWord =
true;
3022 if (!EP.
deref<
T>().singleWord()) {
3024 AllSingleWord =
false;
3029 for (
unsigned I = 1; I != D->getNumElems(); ++I) {
3034 assert(D->isCompositeArray());
3035 for (
unsigned I = 0; I != D->getNumElems(); ++I) {
3036 PtrView EP = Ptr.atIndex(I).narrow();
3047 if (Ptr.canBeInitialized()) {
3060 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3061 << diag::ConstexprInvalidCastKind::Reinterpret
3070 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3071 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3078 S.
FFDiag(E, diag::note_constexpr_access_volatile_type)
3079 <<
AK_Read << E->getSubExpr()->getType();
3087 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3088 << diag::ConstexprInvalidCastKind::Dynamic;
3091 llvm_unreachable(
"Unhandled CastKind");
3124 if (MemberPtr.getPathLength() >= 2)
3125 Expected = MemberPtr.getPathEntry(MemberPtr.getPathLength() - 2);
3127 Expected = MemberPtr.getRecordDecl();
3140 unsigned OldPathLength = MemberPtr.getPathLength();
3141 unsigned NewPathLength = OldPathLength - 1;
3142 bool IsDerivedMember = NewPathLength != 0;
3144 std::copy_n(MemberPtr.path(), NewPathLength, NewPath);
3147 NewPath, IsDerivedMember));
3155 bool IsDerivedMember) {
3156 unsigned OldPathLength = MemberPtr.getPathLength();
3157 unsigned NewPathLength = OldPathLength + 1;
3160 std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
3164 NewPath, IsDerivedMember));
3173 if (!Ptr.isDerivedMember() && Ptr.hasPath())
3176 bool IsDerivedMember = Ptr.isDerivedMember() || !Ptr.hasPath();
3185 if (!Ptr.isDerivedMember()) {
3202 if (!MP.isBaseCastPossible())
3213 const auto *FD = dyn_cast_if_present<FunctionDecl>(D);
3217 const auto *
Method = dyn_cast<CXXMethodDecl>(FD);
3224 if (!
Base.getRecord() ||
Base.getRecord()->getDecl() != MethodParent)
3241 unsigned NewPathLength = OldPathLength + 1;
3244 std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
3248 MemberPtr.withPath(NewPathLength, NewPath, IsDerived));
3252template <
bool Signed>
3254 uint32_t BitWidth, uint32_t FPOI) {
3259 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite() &&
3292 APSInt &&Index,
bool AllowReplace) {
3301 ElemType = AT->getElementType();
3306 unsigned NewPathLength;
3317 if (Index.isNonNegative())
3326 Ptr.getByteOffset());
3333 size_t NewOffset = Ptr.getByteOffset() + (Index.getZExtValue() * ElemSize);
3334 bool PastEnd = Index != 0;
3345 assert(Ptr.isOpaquePointer());
3346 if (Offset.isZero())
3352 unsigned NumElems = 1;
3354 ElemTy = AT->getElementType();
3355 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
3356 NumElems = CAT->getZExtSize();
3361 S.
FFDiag(E, diag::note_constexpr_unsized_array_indexed);
3362 return std::nullopt;
3365 if (Offset > NumElems) {
3376 return std::nullopt;
3379 if (Offset.getActiveBits() > 64)
3380 return std::nullopt;
3388 NewPath[NewPathLength - 1].
Index += Offset.getZExtValue();
3390 NewPath[NewPathLength - 1].
Index -= Offset.getZExtValue();
3398 NewOffset = Ptr.getByteOffset() + (ElemSize * Offset.getZExtValue());
3400 NewOffset = Ptr.getByteOffset() - (ElemSize * Offset.getZExtValue());
3409 return Op == OP_RetVoid || Op == OP_RetValue || Op == OP_NoRet ||
3410 Op == OP_RetSint8 || Op == OP_RetUint8 || Op == OP_RetSint16 ||
3411 Op == OP_RetUint16 || Op == OP_RetSint32 || Op == OP_RetUint32 ||
3412 Op == OP_RetSint64 || Op == OP_RetUint64 || Op == OP_RetIntAP ||
3413 Op == OP_RetIntAPS || Op == OP_RetBool || Op == OP_RetFixedPoint ||
3414 Op == OP_RetPtr || Op == OP_RetMemberPtr || Op == OP_RetFloat ||
3415 Op == OP_EndSpeculation;
3424#define GET_INTERPFN_DISPATCHERS
3425#include "Opcodes.inc"
3426#undef GET_INTERPFN_DISPATCHERS
3431#define GET_INTERPFN_LIST
3432#include "Opcodes.inc"
3433#undef GET_INTERPFN_LIST
3455 return InterpNext(S);
3483 [[maybe_unused]]
CodePtr PCBefore = S.
PC;
3484 size_t StackSizeBefore = S.
Stk.
size();
3490 assert(DepthBefore >= 1);
3493 auto SpeculativeInterp = [&S]() ->
bool {
3516 if (SpeculativeInterp()) {
3521 assert(S.
Stk.
size() == StackSizeBefore);
3527 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.
static bool hasLayout(const RecordDecl *D)
Whether layout (offset and size) information can be queried for D.
const clang::PrintingPolicy & getPrintingPolicy() const
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
bool hasSimilarType(QualType T1, QualType T2) const
Determine if two types are similar, according to the C++ rules.
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
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.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
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.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
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.
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
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.
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.
SourceLocation getLocation(CodePtr PC) const
static void free(InterpFrame *F)
InterpFrame * Caller
The frame of the previous function.
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
SourceRange getRange(CodePtr PC) const
Block * getLocalBlock(unsigned Offset) const
const Pointer & getThis() const
Returns the 'this' pointer.
unsigned MSVCConstexprAllowed
const Function * getFunction() const
Returns the current function.
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.
const Expr * getExpr(CodePtr PC) const
unsigned getDepth() const
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.
const unsigned EvalID
ID identifying this evaluation.
bool noteStep(CodePtr OpPC)
Note that a step has been executed.
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.
PointerPathEntry * allocPointerPath(unsigned Length, const PointerPathEntry *OldPP)
const CXXRecordDecl ** allocMemberPointerPath(unsigned Length)
void deallocate(Block *B)
Deallocates a pointer.
PointerPathEntry * extendPointerPath(unsigned NewLength, const PointerPathEntry *OldPP, PointerPathEntry NewEntry)
Allocate a new pointer path of Length NewLength.
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.
Pointer stripBaseCasts() const
Strip base casts from this Pointer.
const Expr * getRootExpr() const
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
bool isDummy() const
Checks if the pointer points to a dummy value.
int64_t getIndex() const
Returns the index into an array.
bool isStringPointer() const
unsigned getNumElems() const
Returns the number of elements.
QualType getType() const
Returns the type of the innermost field.
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
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.
const FieldDecl * getField() const
Returns the field information.
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
bool isBlockPointer() const
const Block * block() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
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.
SourceLocation getLoc() const
bool checkingForUndefinedBehavior() const
Are we checking an expression for overflow?
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
bool emitRelaxedDiag(SourceLocation Loc, diag::kind DiagId)
If DiagId should be relaxed as per the current evaluation settings, emit it as a warning instead of a...
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 CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a field from which a pointer is going to be derived is valid.
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 arrayElemPtrOpaque(InterpState &S, CodePtr OpPC, const Pointer &Ptr, APSInt &&Index, bool AllowReplace)
bool CheckFunctionDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *FD)
Opcode. Check if the function decl can be called at compile time.
std::optional< Pointer > addSubOffsetOpaque(InterpState &S, CodePtr OpPC, const Pointer &Ptr, APSInt &&Offset, ArithOp Op)
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 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.
static bool allowNullSubObj(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
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)
static bool validType(QualType T)
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.
SourceLocation getLocation() const
QualType getDataType(const ASTContext &Ctx) const
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
const VarDecl * asVarDecl() const
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
Descriptor used for global variables.
Inline descriptor embedded in structures and arrays.
OpaquePointer withFieldType(const Type *FieldTy, std::optional< bool > PastEnd=std::nullopt) const
llvm::PointerIntPair< const Type *, 2, unsigned > FieldType
OpaquePointer withPastEnd(bool PastEnd) const
QualType getSurroundingArray() const
If this is pointing to an array element, return the array.
const PointerPathEntry * Path
bool isArrayElement() const
QualType getFieldType() const
OpaquePointer withPath(const PointerPathEntry *Path, unsigned PathLength, const Type *FieldTy, std::optional< bool > PastEnd=std::nullopt) const
static PointerPathEntry array(int64_t Index)
static PointerPathEntry field(const FieldDecl *FD)
static PointerPathEntry negativeArray(int64_t Index)
static PointerPathEntry base(const CXXRecordDecl *RD, bool Virtual=false)
const Record * getRecord() const
const FieldDecl * getField() const
const Block * block() const
Lifetime getLifetime() const
PtrView stripBaseCasts() const