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
57 return !
T->isDependentType() && !
T->isUndeducedAutoType() &&
58 !
T->isSpecificBuiltinType(BuiltinType::UnknownAny) &&
59 !
T->isIncompleteType();
63 llvm::report_fatal_error(
"Interpreter cannot return values");
94 S.
FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
110 if (Ptr.isBlockPointer()) {
111 const Block *B = Ptr.block();
122 if (Ptr.isOpaquePointer())
123 S.
Note(Ptr.asOpaquePointer().Base.getLocation(), diag::note_declared_at);
146 S.
FFDiag(Loc, diag::note_constexpr_access_unknown_variable, 1)
148 S.
Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
150 S.
FFDiag(Loc, diag::note_constexpr_function_param_value_unknown, 1) << D;
160 }
else if (
const auto *VD = dyn_cast<VarDecl>(D)) {
161 if (!VD->getAnyInitializer()) {
165 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
166 S.
Note(VD->getLocation(), diag::note_declared_at);
188 if (
const auto *VarD = dyn_cast<VarDecl>(VD);
189 VarD && VarD->isCXXForRangeImplicitVar()) {
191 diag::note_constexpr_ltor_for_range_var)
196 if (
const auto *VarD = dyn_cast<VarDecl>(VD);
197 VarD && VarD->getType().isConstQualified() &&
198 (VarD->isConstexpr() || !VarD->getType()->isArrayType()) &&
199 !VarD->getAnyInitializer()) {
212 S.
FFDiag(Loc, diag::note_constexpr_modify_global);
214 S.
FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
221 S.
getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
222 : diag::note_constexpr_ltor_non_integral,
234 const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
246 S.
FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
257 if (!Ptr.isBlockPointer())
263 if (
auto ID = Ptr.getDeclID()) {
292 S.
CCEDiag(E, diag::note_constexpr_large_shift)
309 std::optional<uint64_t> NumElems,
bool IsArray) {
314 << Index << !IsArray << NumElems.value_or(0u);
324 unsigned VariadicArgSize =
326 unsigned TargetStackSize = S.
Stk.
size() - VariadicArgSize;
327 while (S.
Stk.
size() != TargetStackSize) {
337 if (
Func->hasImplicitThisPointer())
358 if (Ptr.isFunctionPointer())
360 if (Ptr.isIntegralPointer())
362 if (Ptr.isTypeidPointer())
365 if (Ptr.getType()->isAnyComplexType())
368 if (
const Expr *
Base = Ptr.getRootExpr())
378 assert(Ptr.inUnion());
383 while (!
U.isRoot() && !
U.isActive()) {
388 if (
U.getRecord() &&
U.getRecord()->isAnonymousUnion())
395 assert(
C.getBase() ==
U);
409 if (!
U.getFieldDesc()->isUnion())
419 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(R->getDecl());
420 CXXRD && !CXXRD->hasTrivialDefaultConstructor()) {
432 assert(!
C.isActive());
433 const FieldDecl *InactiveField =
C.getField();
434 assert(InactiveField);
437 const Record *R =
U.getRecord();
438 assert(R && R->isUnion() &&
"Not a union");
441 for (
const Record::Field &F : R->fields()) {
442 PtrView Field =
U.atField(F.Offset);
443 if (Field.isActive()) {
444 ActiveField = Field.getField();
450 diag::note_constexpr_access_inactive_union_member)
451 << AK << InactiveField << !ActiveField << ActiveField;
457 if (!Ptr.isBlockPointer())
459 return CheckActive(S, OpPC, Ptr.view(), AK, WillActivate);
466 if (!Ptr.isPastEnd() &&
467 (Ptr.isInitialized() ||
475 const auto *VD = Ptr.getDeclDesc()->asValueDecl();
488 if (!Ptr.isUnknownSizeArray())
491 S.
FFDiag(E, diag::note_constexpr_unsized_array_indexed);
503 S.
FFDiag(Loc, diag::note_constexpr_access_null) << AK;
509 if (Ptr.isDynamic()) {
511 diag::note_constexpr_access_deleted_object)
533 if (D->getType().isConstQualified())
547 if (
T->isIntegralOrEnumerationType()) {
559 ? diag::note_constexpr_ltor_non_constexpr
560 : diag::note_constexpr_ltor_non_integral,
563 S.
Note(D->getLocation(), diag::note_declared_at);
570 if (
T->isPointerOrReferenceType()) {
588 if (!Ptr.isStatic() || !Ptr.isBlockPointer())
590 if (!Ptr.getDeclID())
600 if (!Ptr.block()->isStatic())
602 if (!Ptr.block()->getDeclID())
612 S.
FFDiag(Loc, diag::note_constexpr_null_subobject)
620 if (!Ptr.isElementPastEnd() && !Ptr.isZeroSizeArray())
623 S.
FFDiag(Loc, diag::note_constexpr_past_end_subobject)
630 if (!Ptr.isOnePastEnd())
634 S.
FFDiag(Loc, diag::note_constexpr_past_end_subobject)
641 uint32_t MinOffset = Ptr.block()->getMetadataSize();
642 uint32_t PtrOffset = Ptr.getByteOffset();
646 if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
655 QualType MostDerivedQT = Ptr.getDeclPtr().getType();
660 S.
CCEDiag(E, diag::note_constexpr_invalid_downcast)
661 << MostDerivedQT << TargetQT;
667 assert(Ptr.isLive() &&
"Pointer is not live");
671 if (Ptr.isMutable() && !Ptr.isConstInMutable())
674 if (!Ptr.isBlockPointer())
680 if (
V.block() != Ptr.block())
682 if (!
V.getFieldDesc()->IsConst) {
697 bool FoundProblem =
false;
698 for (
PtrView P = Ptr.view(); P !=
V; P = P.getBase()) {
699 if (P.getFieldDesc()->IsConst) {
715 if (!Ptr.getFieldDesc()->IsConst)
718 S.
FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
724 assert(Ptr.isLive() &&
"Pointer is not live");
725 if (!Ptr.isMutable())
741 MutablePtr = MutablePtr.
getBase();
745 S.
FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK << Field;
746 S.
Note(Field->getLocation(), diag::note_declared_at);
752 assert(Ptr.isLive());
754 if (!Ptr.isVolatile())
778 Loc = F->getLocation();
782 Loc = VD->getLocation();
787 Loc = E->getExprLoc();
791 diag::note_constexpr_access_volatile_obj, 1)
792 << AK << DiagKind << ND;
793 S.
Note(Loc, diag::note_constexpr_volatile_here) << DiagKind;
799 assert(Ptr.isLive());
800 assert(!Ptr.isInitialized());
802 Ptr.getLifetime(), AK);
820 VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
823 !(S.
getLangOpts().CPlusPlus23 && VD->getType()->isReferenceType())) {
832 S.
Note(VD->getFirstDecl()->getLocation(), diag::note_declared_at);
837 if (VD->getAnyInitializer()) {
839 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
840 S.
Note(VD->getLocation(), diag::note_declared_at);
858 assert(Ptr.isLive());
859 assert(!Ptr.isInitialized());
861 Ptr.getLifetime(), AK);
878 return CheckLifetime(S, OpPC, Ptr.getLifetime(), Ptr.block(), AK);
889 S.
Note(VD->getLocation(), diag::note_declared_at);
918 diag::note_constexpr_access_volatile_obj, 1)
931 if (!Desc.IsInitialized)
941 diag::note_constexpr_access_volatile_obj, 1)
965 S.
FFDiag(Loc, diag::note_constexpr_access_null) << AK;
969 if (!Ptr.block()->isAccessible()) {
971 if (Ptr.block()->isDynamic()) {
973 diag::note_constexpr_access_deleted_object)
994 if (!Ptr.isInitialized())
997 if (!
CheckLifetime(S, OpPC, Ptr.getLifetime(), Ptr.block(), AK))
1009 if (!Ptr.isArrayRoot()) {
1024 if (
const auto *CLE =
1025 dyn_cast_if_present<CompoundLiteralExpr>(Desc->
asExpr())) {
1026 if (
QualType CLETy = CLE->getType();
1029 diag::note_invalid_subexpr_in_const_expr)
1031 S.
Note(CLE->getExprLoc(), diag::note_declared_at);
1041 if (Ptr.isBlockPointer())
1042 return CheckLoad(S, OpPC, Ptr.view(), AK);
1049 S.
FFDiag(Loc, diag::note_constexpr_access_null) << AK;
1054 if (!Ptr.isReadablePointerType())
1057 assert(Ptr.isStringPointer());
1063 if (!Ptr.isInitialized())
1071 assert(!Ptr.isZero());
1072 if (!Ptr.isReadablePointerType())
1075 if (Ptr.isBlockPointer() && !Ptr.block()->isAccessible()) {
1088 if (!Ptr.isInitialized())
1091 if (Ptr.isBlockPointer()) {
1099 if (Ptr.isConstexprUnknown())
1109 if (Ptr.isOpaquePointer())
1112 if (!Ptr.isBlockPointer())
1115 if (!Ptr.block()->isAccessible()) {
1124 if (!
CheckActive(S, OpPC, Ptr, AK, WillBeActivated))
1140 bool IsCtor,
bool IsDtor) {
1157 if (!Ptr.isBlockPointer())
1176 StringRef Name = DiagDecl->
getName();
1178 Name ==
"__assert_rtn" || Name ==
"__assert_fail" || Name ==
"_wassert";
1181 diag::note_constexpr_assert_failed);
1188 diag::note_invalid_subexpr_in_const_expr);
1194 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
1195 if (CD && CD->isInheritingConstructor()) {
1196 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
1197 if (!Inherited->isConstexpr())
1198 DiagDecl = CD = Inherited;
1203 if (CD && CD->getParent()->isInvalidDecl())
1209 if (CD && CD->isInheritingConstructor()) {
1212 << CD->getInheritedConstructor().getConstructor()->getParent();
1220 if (!IsDefined && !IsExtern && DiagDecl->
isConstexpr() &&
1230 diag::note_constexpr_invalid_function, 1)
1231 << DiagDecl->
isConstexpr() << (bool)CD << DiagDecl;
1247 S.
CCEDiag(Loc, diag::note_constexpr_virtual_call);
1271 diag::note_constexpr_depth_limit_exceeded)
1288 bool IsImplicit =
false;
1289 if (
const auto *TE = dyn_cast<CXXThisExpr>(E))
1290 IsImplicit = TE->isImplicit();
1291 S.
FFDiag(E, diag::note_constexpr_this) << IsImplicit;
1306 if ((Status & APFloat::opInexact) &&
1311 S.
FFDiag(E, diag::note_constexpr_dynamic_rounding);
1315 if ((Status != APFloat::opOK) &&
1318 FPO.getAllowFEnvAccess())) {
1320 S.
FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
1324 if ((Status & APFloat::opStatus::opInvalidOp) &&
1336 APFloat::opStatus Status,
FPOptions FPO) {
1347 S.
CCEDiag(E, diag::note_constexpr_float_arithmetic)
1360 S.
CCEDiag(E, diag::note_constexpr_new);
1367 const Expr *NewExpr) {
1368 if (AllocForm == DeleteForm)
1374 S.
FFDiag(E, diag::note_constexpr_new_delete_mismatch)
1375 <<
static_cast<int>(DeleteForm) <<
static_cast<int>(AllocForm)
1377 S.
Note(NewExpr->
getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
1384 if (!Ptr.isBlockPointer() && !Ptr.isOpaquePointer())
1387 if (isa_and_nonnull<CXXNewExpr>(Source))
1390 if (
const auto *CE = dyn_cast_if_present<CallExpr>(Source);
1391 CE && CE->getBuiltinCallee() == Builtin::BI__builtin_operator_new)
1394 if (
const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(Source);
1395 MCE && MCE->getMethodDecl()->
getIdentifier()->isStr(
"allocate"))
1400 S.
FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
1423 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
1424 S.
Note(VD->getLocation(), diag::note_declared_at);
1437 const VarDecl *D = Ptr.getRootVarDecl();
1456 const CallExpr *CE,
unsigned ArgSize) {
1459 unsigned Offset = 0;
1461 for (
const Expr *Arg : Args) {
1462 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
1466 S.
CCEDiag(Loc, diag::note_non_null_attribute_failed);
1488 S.
FFDiag(Loc, diag::note_constexpr_double_destroy);
1495 assert(!
Dtor->isTrivial());
1501 return Call(S, OpPC, DtorFunc, 0);
1524 for (
int I =
static_cast<int>(N) - 1; I >= 0; --I) {
1538 return DD->isVirtual();
1543 bool IsGlobalDelete) {
1549 const Expr *Source =
nullptr;
1550 const Block *BlockToDelete =
nullptr;
1560 if (!Ptr.isBlockPointer())
1564 QualType InitialType = Ptr.getType();
1565 Ptr = Ptr.expand().stripBaseCasts();
1567 Source = Ptr.getRootExpr();
1568 BlockToDelete = Ptr.block();
1572 if (std::optional<DynamicAllocator::Form> AllocForm =
1584 if (!DeleteIsArrayForm && Ptr.getType() != InitialType &&
1587 diag::note_constexpr_delete_base_nonvirt_dtor)
1588 << InitialType << Ptr.getType();
1592 if (!Ptr.isRoot() || (Ptr.isOnePastEnd() && !Ptr.isZeroSizeArray()) ||
1593 (Ptr.isArrayElement() && Ptr.getIndex() != 0)) {
1595 S.
FFDiag(Loc, diag::note_constexpr_delete_subobject)
1596 << Ptr.toDiagnosticString(S.
getASTContext()) << Ptr.isOnePastEnd();
1605 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1606 QualType AllocType = Ptr.getType();
1610 return DD->isVirtual() ? DD->getOperatorDelete() :
nullptr;
1620 diag::note_constexpr_new_non_replaceable)
1627 assert(BlockToDelete);
1633 if (!Allocator.
deallocate(Source, BlockToDelete)) {
1636 S.
FFDiag(Loc, diag::note_constexpr_double_delete);
1653 S.
CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1654 << llvm::toString(
Value, 10) <<
Min.getSExtValue() <<
Max.getSExtValue()
1658 S.
CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1659 << llvm::toString(
Value, 10) <<
Min.getZExtValue() <<
Max.getZExtValue()
1690 S.
FFDiag(E, diag::note_constexpr_nonliteral) << E->
getType();
1692 S.
FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
1697 const Pointer &Ptr,
unsigned Offset) {
1698 assert(Ptr.isTypeidPointer());
1700 Ptr.asTypeidPointer().TypeInfoType->getAsRecordDecl());
1703 const Record::Field *Field = R->findField(Offset);
1707 std::string TypeIdStr;
1708 llvm::raw_string_ostream SS(TypeIdStr);
1710 QualType(Ptr.asTypeidPointer().TypePtr, 0)
1713 SS << Field->Decl->getNameAsString();
1716 diag::note_constexpr_access_unreadable_object)
1723 diag::note_constexpr_null_subobject);
1739 if (Ptr.isIntegralPointer()) {
1740 if (std::optional<IntPointer> IntPtr =
1741 Ptr.asIntPointer().atOffset(S.
Ctx,
Off)) {
1748 if (Ptr.isOpaquePointer()) {
1757 const Record::Field *F = R->findField(
Off);
1765 F->Decl->getType().getTypePtr()),
1766 Ptr.getByteOffset());
1771 if (!Ptr.isBlockPointer()) {
1774 if (Ptr.isTypeidPointer())
1780 if (!Ptr.getFieldDesc()->isRecord())
1783 if ((Ptr.getByteOffset() +
Off) >= Ptr.block()->getSize())
1801 uint32_t
Off,
bool NullOK) {
1805 if (Ptr.isOpaquePointer()) {
1813 const Record::Base *B = R->findBase(
Off);
1824 Ptr.getByteOffset());
1828 if (!Ptr.isBlockPointer()) {
1829 if (!Ptr.isIntegralPointer())
1840 if (!Ptr.getFieldDesc()->isRecord()) {
1854 return getBase(S, OpPC, Ptr.narrow(),
Off,
true);
1858 return getBase(S, OpPC, Ptr.narrow(),
Off, NullOK);
1862 const Type *TargetType) {
1867 if (!Ptr.isBlockPointer()) {
1875 if (!Ptr.getFieldDesc()->isRecord()) {
1885 const Record *TargetRecord = Ptr.atFieldSub(
Off).getRecord();
1886 assert(TargetRecord);
1890 QualType MostDerivedType = Ptr.getDeclDesc()->getType();
1892 << MostDerivedType <<
QualType(TargetType, 0);
1902 assert(
Func->isConstructor());
1904 if (
Func->getParentDecl()->isInvalidDecl())
1920 <<
Func->getParentDecl();
1928 if (
const Decl *D = Ptr.getDeclDesc()->asDecl()) {
1930 S.
FFDiag(ND->getLocation(), diag::note_constexpr_destroy_out_of_lifetime)
1931 << ND->getNameAsString();
1933 S.
FFDiag(Ptr.getDeclDesc()->getLocation(),
1934 diag::note_constexpr_destroy_out_of_lifetime)
1959 if (Ptr.isOpaquePointer() || Ptr.block()->isStatic()) {
1961 S.
FFDiag(E, diag::note_constexpr_modify_global);
1984 bool SrcIsVoidPtr) {
1988 if (!Ptr.isBlockPointer())
1995 bool HasValidResult = !Ptr.isZero();
1997 if (HasValidResult) {
2007 S.
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
2008 << E->getSubExpr()->getType() << S.
getLangOpts().CPlusPlus26
2009 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
2012 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
2013 << diag::ConstexprInvalidCastKind::CastFrom <<
"'void *'"
2022 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2029 const Type *TargetType) {
2033 bool HasValidResult = !Ptr.isZero();
2035 if (HasValidResult) {
2045 S.
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
2046 << E->getSubExpr()->getType() << S.
getLangOpts().CPlusPlus26
2047 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
2050 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
2051 << diag::ConstexprInvalidCastKind::CastFrom <<
"'void *'"
2056 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
2057 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2062 if (Ptr.isOpaquePointer()) {
2087 uint32_t VarArgSize) {
2088 if (
Func->hasThisPointer()) {
2089 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2099 Func->isLambdaCallOperator())) {
2101 Func->isDestructor()))
2109 if (!
Func->isFullyCompiled())
2128 uint32_t VarArgSize) {
2135 auto cleanup = [&]() ->
bool {
2140 bool InstancePtrTracked =
false;
2141 if (
Func->hasThisPointer()) {
2142 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2159 Func->isLambdaCallOperator()) {
2160 assert(ThisPtr.
isZero());
2163 Func->isDestructor()))
2166 if (
Func->isCopyOrMoveOperator() ||
Func->isCopyOrMoveConstructor()) {
2173 if (!
Func->isConstructor() && !
Func->isDestructor() &&
2183 InstancePtrTracked = (
Func->isConstructor() ||
Func->isDestructor());
2184 if (InstancePtrTracked)
2188 if (!
Func->isFullyCompiled())
2209 if (InstancePtrTracked)
2219 auto diagUnknownDynamicType = [&](
const Pointer &P) ->
bool {
2223 diag::note_constexpr_polymorphic_unknown_dynamic_type)
2228 if (!Ptr.isBlockPointer())
2229 return diagUnknownDynamicType(Ptr);
2235 auto depth = [](
PtrView V) ->
unsigned {
2237 while (!
V.isRoot()) {
2254 assert(depth(TypePtr) >= depth(InitPtr));
2255 unsigned D = depth(TypePtr) - depth(InitPtr);
2256 for (
unsigned I = 0; I != D; ++I)
2264 return diagUnknownDynamicType(
Pointer(TypePtr));
2268 DynamicDecl =
DynamicType->getPointeeCXXRecordDecl();
2276 return DynamicDecl !=
nullptr;
2280struct DynamicCastResult {
2284 bool valid()
const {
return !
Ambiguous && Offset; }
2286 void setOffset(
unsigned O) {
2294 void merge(DynamicCastResult
C) {
2295 Ambiguous |=
C.Ambiguous;
2309 DynamicCastResult Res;
2314 for (
const Record::Base &B : R->bases()) {
2317 N.Offset = *N.Offset + B.Offset;
2325 bool IsReferenceCast) {
2329 if (Ptr.isConstexprUnknown() || Ptr.isOpaquePointer()) {
2334 S.
FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
2339 if (!Ptr.isBlockPointer() || !Ptr.getRecord())
2342 if (!Ptr.isInitialized())
2350 LimitedPtr = Ptr.stripBaseCasts().view();
2353 assert(LimitedPtr.
block() == Ptr.block());
2360 if (TargetType->isVoidType()) {
2365 assert(!TargetType.isNull());
2366 assert(!TargetType->isVoidType());
2367 assert(TargetType->isRecordType());
2374 assert(P.getRecord());
2378 auto baseIsPrivate = [&](
PtrView P) ->
bool {
2379 if (P.isRoot() || !P.isBaseClass())
2383 getRecord(P.getBase())->isDerivedFrom(getRecord(P), Paths);
2388 return llvm::all_of(Paths, [](
const CXXBasePath &P) ->
bool {
2394 DiagPrivateBase = 0,
2397 DiagPrivateSibling = 3
2400 auto diag = [&](
int DiagKind,
QualType ResultType) ->
bool {
2402 if (!IsReferenceCast) {
2408 diag::note_constexpr_dynamic_cast_to_reference_failed)
2409 << DiagKind << ResultType <<
DynamicType << TargetType;
2418 getRecord(LimitedPtr)
2419 ->isDerivedFrom(TargetType->getAsCXXRecordDecl(), Paths);
2420 if (std::distance(Paths.
begin(), Paths.
end()) == 0 &&
2421 !typesMatch(LimitedPtr.
getType(), TargetType)) {
2422 return diag(DiagNoBase, TargetType);
2427 if (baseIsPrivate(Ptr.view()))
2428 return diag(DiagPrivateBase, Ptr.getType());
2430 std::optional<PtrView>
Result;
2432 for (
PtrView Iter = Ptr.view();;) {
2433 if (Iter.isRoot() || !Iter.isBaseClass())
2436 if (typesMatch(TargetType, Iter.getType())) {
2441 Iter = Iter.getBase();
2447 if (baseIsPrivate(*
Result))
2448 return diag(DiagPrivateBase,
Result->getType());
2455 for (
PtrView Iter = LimitedPtr;;) {
2461 Result = Iter.atField(*R.Offset);
2469 if (Iter.isRoot() || !Iter.isBaseClass())
2472 Iter = Iter.getBase();
2476 return diag(DiagAmbiguous, TargetType);
2480 if (baseIsPrivate(*
Result))
2481 return diag(DiagPrivateSibling, TargetType);
2487 return diag(DiagNoBase, TargetType);
2491 uint32_t VarArgSize) {
2493 if (!
Func->hasThisPointer()) {
2494 assert(!
Func->isValid());
2498 assert(
Func->hasThisPointer());
2499 assert(
Func->isVirtual());
2500 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2512 assert(DynamicDecl);
2514 const auto *StaticDecl =
Func->getParentDecl();
2518 if (StaticDecl != DynamicDecl) {
2525 Overrider = InitialFunction;
2535 S.
Note(Callee->getLocation(), diag::note_declared_at);
2539 if (Overrider != InitialFunction) {
2552 if (
Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
2560 if (!
Call(S, OpPC,
Func, VarArgSize))
2565 if (Overrider != InitialFunction &&
2567 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
2575 OverriderPointeeType))
2592 uint32_t BuiltinID) {
2595 if (BuiltinID == Builtin::BI__builtin_operator_new &&
2612 if (!Ptr.isFunctionPointer())
2615 const Function *F = Ptr.asFunctionPointer().Func;
2659 return CallVirt(S, OpPC, F, VarArgSize);
2661 return Call(S, OpPC, F, VarArgSize);
2665 if (
const Record *R = Ptr.getRecord()) {
2666 Ptr.startLifetime();
2668 for (
const Record::Field &Fi : R->fields()) {
2669 PtrView FP = Ptr.atField(Fi.Offset);
2676 if (
const Descriptor *FieldDesc = Ptr.getFieldDesc();
2677 FieldDesc->isCompositeArray()) {
2678 for (
unsigned I = 0; I != FieldDesc->getNumElems(); ++I) {
2679 PtrView EP = Ptr.atIndex(I).narrow();
2686 Ptr.startLifetime();
2694 if (!Ptr.isBlockPointer())
2705 if (!Ptr.isBlockPointer())
2707 Ptr.startLifetime();
2714 if (
const Record *R = Ptr.getRecord()) {
2715 Ptr.setLifeState(L);
2716 for (
const Record::Field &Fi : R->fields())
2721 if (
const Descriptor *FieldDesc = Ptr.getFieldDesc();
2722 FieldDesc->isCompositeArray()) {
2724 if (Ptr.getFieldDesc()->isPrimitiveArray())
2726 for (
unsigned I = 0; I != FieldDesc->getNumElems(); ++I)
2731 Ptr.setLifeState(L);
2765 assert(Ptr.getRecord());
2767 const Record *R = Ptr.getRecord();
2768 for (
const Record::Base &B : R->bases()) {
2769 PtrView BasePtr = Ptr.atField(B.Offset);
2775 for (
const Record::Field &F : R->fields()) {
2776 PtrView FieldPtr = Ptr.atField(F.Offset);
2782 for (
const Record::Base &B : R->virtual_bases()) {
2783 PtrView BasePtr = Ptr.atField(B.Offset);
2793 if (!Ptr.isBlockPointer())
2795 const Record *R = Ptr.getRecord();
2807 diag::note_constexpr_invalid_function, 1)
2812 diag::note_invalid_subexpr_in_const_expr);
2816 Ptr.startLifetime();
2826 std::optional<uint64_t> ArraySize) {
2830 auto directBaseIsUnion = [](
const Pointer &Ptr) ->
bool {
2831 if (Ptr.isArrayElement())
2833 const Record *R = Ptr.getBase().getRecord();
2834 return R && R->isUnion();
2837 if (Ptr.inUnion() && directBaseIsUnion(Ptr))
2848 if (!Ptr.isBlockPointer())
2858 if (!Ptr.block()->isAccessible()) {
2869 for (
PtrView P = Ptr.view();;) {
2892 QualType StorageType = Ptr.getType();
2896 NewExpr->getAllocatedType(),
2897 APInt(64,
static_cast<uint64_t
>(*ArraySize),
false),
nullptr,
2900 AllocType = NewExpr->getAllocatedType();
2903 if (AllocType->
isArrayType() && Ptr.isArrayElement() &&
2904 Ptr.expand().getIndex() == 0) {
2912 StorageType = Ptr.expand().getArray().getType();
2919 diag::note_constexpr_placement_new_wrong_type)
2920 << StorageType << AllocType;
2925 if (Ptr.inUnion() && !Ptr.isActive() && !directBaseIsUnion(Ptr))
2934 if (
const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
2935 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
2937 if (NewExpr->getNumPlacementArgs() > 0) {
2948 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
2950 diag::note_constexpr_new_non_replaceable)
2954 NewExpr->getNumPlacementArgs() == 1 &&
2955 !OperatorNew->isReservedGlobalPlacementOperator()) {
2965 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
2967 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
2969 diag::note_constexpr_new_non_replaceable)
2983 E->
getExprLoc(), diag::warn_fixedpoint_constant_overflow)
2986 S.
CCEDiag(E, diag::note_constexpr_overflow)
2994 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
3000 const Pointer &Ptr,
unsigned BitWidth) {
3003 S.
CCEDiag(E, diag::note_constexpr_invalid_cast_ptrtoint)
3004 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3006 if (Ptr.isBlockPointer() && !Ptr.isZero())
3008 if (Ptr.isIntegralPointer())
3011 if (Ptr.isOpaquePointer()) {
3014 return Ptr.isRoot();
3017 if (!Ptr.isZero()) {
3037 Result.copy(
APInt(BitWidth, Ptr.getIntegerRepresentation()));
3050 Result.copy(
APInt(BitWidth, Ptr.getIntegerRepresentation()));
3057 bool TargetIsUCharOrByte) {
3059 if (!HasIndeterminateBits)
3063 if (TargetIsUCharOrByte)
3068 S.
FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
3080 if (!ID.IsInitialized) {
3083 diag::note_constexpr_use_uninit_reference);
3100 if (!P.isBlockPointer() && !P.isOpaquePointer())
3103 if (P.isConstexprUnknown()) {
3108 S.
FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
3115 if (P.isBlockPointer())
3116 T = P.stripBaseCasts().getType()->getCanonicalTypeUnqualified();
3118 T = P.getType()->getCanonicalTypeUnqualified();
3125 Func && (
Func->isConstructor() ||
Func->isDestructor()) &&
3126 P.block() ==
Frame->getThis().block()) {
3128 Func->getParentDecl());
3140 S.
CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
3141 << E->getExprOperand()->getType()
3142 << E->getExprOperand()->getSourceRange();
3156 StringRef LHSStr(LHSLit->getBytes());
3157 unsigned LHSLength = LHSStr.size();
3158 StringRef RHSStr(RHSLit->getBytes());
3159 unsigned RHSLength = RHSStr.size();
3161 int32_t IndexDiff = RHSOffset - LHSOffset;
3162 if (IndexDiff < 0) {
3163 if (
static_cast<int32_t
>(LHSLength) < -IndexDiff)
3165 LHSStr = LHSStr.drop_front(-IndexDiff);
3167 if (
static_cast<int32_t
>(RHSLength) < IndexDiff)
3169 RHSStr = RHSStr.drop_front(IndexDiff);
3172 unsigned ShorterCharWidth;
3175 if (LHSLength < RHSLength) {
3176 ShorterCharWidth = LHSLit->getCharByteWidth();
3180 ShorterCharWidth = RHSLit->getCharByteWidth();
3188 for (
unsigned NullByte : llvm::seq(ShorterCharWidth)) {
3189 if (Shorter.size() + NullByte >= Longer.size())
3191 if (Longer[Shorter.size() + NullByte])
3194 return Shorter == Longer.take_front(Shorter.size());
3200 if (!Val.singleWord()) {
3201 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
3202 Val.take(NewMemory);
3206 if (!Val.singleWord()) {
3207 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
3208 Val.take(NewMemory);
3212 if (!Val.singleWord()) {
3213 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
3214 Val.take(NewMemory);
3220 std::copy_n(Val.path(), PathLength, NewPath);
3221 Val.takePath(NewPath);
3223 auto &Val = Ptr.deref<
Pointer>();
3224 if (Val.isOpaquePointer() && Val.asOpaquePointer().PathLength != 0) {
3231 Val.getByteOffset());
3236template <
typename T>
3239 if constexpr (std::is_same_v<T, MemberPointer>) {
3243 std::copy_n(Val.path(), PathLength, NewPath);
3244 Val.takePath(NewPath);
3245 }
else if constexpr (std::is_same_v<T, Pointer>) {
3246 auto &Val = Ptr.deref<
Pointer>();
3247 if (Val.isOpaquePointer() && Val.asOpaquePointer().PathLength != 0) {
3254 Val.getByteOffset());
3257 auto &Val = Ptr.deref<
T>();
3258 if (!Val.singleWord()) {
3259 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
3260 Val.take(NewMemory);
3266 if (
const Record *R = Ptr.getRecord()) {
3267 for (
const Record::Field &Fi : R->fields()) {
3268 if (Fi.Desc->isPrimitive()) {
3270 copyPrimitiveMemory<T>(S, Ptr.atField(Fi.Offset));
3279 if (
const Descriptor *D = Ptr.getFieldDesc(); D && D->isArray()) {
3280 unsigned NumElems = D->getNumElems();
3284 if (D->isPrimitiveArray()) {
3288 assert(NumElems >= 1);
3290 bool AllSingleWord =
true;
3292 if (!EP.
deref<
T>().singleWord()) {
3294 AllSingleWord =
false;
3299 for (
unsigned I = 1; I != D->getNumElems(); ++I) {
3304 assert(D->isCompositeArray());
3305 for (
unsigned I = 0; I != D->getNumElems(); ++I) {
3306 PtrView EP = Ptr.atIndex(I).narrow();
3315 if (!Ptr.isBlockPointer())
3319 if (Ptr.canBeInitialized()) {
3332 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3333 << diag::ConstexprInvalidCastKind::Reinterpret
3342 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3343 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3350 S.
FFDiag(E, diag::note_constexpr_access_volatile_type)
3351 <<
AK_Read << E->getSubExpr()->getType();
3359 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3360 << diag::ConstexprInvalidCastKind::Dynamic;
3363 llvm_unreachable(
"Unhandled CastKind");
3395 if (!MemberPtr.getDecl()) {
3401 if (MemberPtr.getPathLength() >= 2)
3402 Expected = MemberPtr.getPathEntry(MemberPtr.getPathLength() - 2);
3404 Expected = MemberPtr.getRecordDecl();
3417 unsigned OldPathLength = MemberPtr.getPathLength();
3418 unsigned NewPathLength = OldPathLength - 1;
3419 bool IsDerivedMember = NewPathLength != 0;
3421 std::copy_n(MemberPtr.path(), NewPathLength, NewPath);
3424 NewPath, IsDerivedMember));
3432 bool IsDerivedMember) {
3433 unsigned OldPathLength = MemberPtr.getPathLength();
3434 unsigned NewPathLength = OldPathLength + 1;
3437 std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
3441 NewPath, IsDerivedMember));
3450 if (!Ptr.isDerivedMember() && Ptr.hasPath())
3453 bool IsDerivedMember = Ptr.isDerivedMember() || !Ptr.hasPath();
3462 if (!Ptr.isDerivedMember()) {
3479 if (!MP.isBaseCastPossible())
3490 const auto *FD = dyn_cast_if_present<FunctionDecl>(D);
3494 const auto *
Method = dyn_cast<CXXMethodDecl>(FD);
3501 if (!
Base.getRecord() ||
Base.getRecord()->getDecl() != MethodParent)
3518 unsigned NewPathLength = OldPathLength + 1;
3521 std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
3525 MemberPtr.withPath(NewPathLength, NewPath, IsDerived));
3529template <
bool Signed>
3531 uint32_t BitWidth, uint32_t FPOI) {
3536 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite() &&
3563 APSInt &&Index,
bool AllowReplace) {
3572 ElemType = AT->getElementType();
3577 unsigned IndexBits = std::max(Index.getBitWidth(), 32u) + 1;
3579 Index.extend(IndexBits) +
3580 APSInt(
APInt(IndexBits, Ptr.getIndex()), Index.isUnsigned());
3582 if (NewIndex > Ptr.getNumElems() || NewIndex.isNegative())
3586 if (NewIndex.getActiveBits() > 64)
3589 unsigned NewPathLength;
3600 if (Index.isNonNegative())
3609 Ptr.getByteOffset());
3612 unsigned IndexBits = std::max(Index.getBitWidth(), 64u) + 1;
3613 size_t CurrentIndex = Ptr.getByteOffset();
3615 Index.extend(IndexBits) +
3616 APSInt(
APInt(IndexBits, CurrentIndex), Index.isUnsigned());
3617 if (NewOffset > 1 || NewOffset.isNegative())
3620 if (NewOffset.getActiveBits() > 64)
3623 size_t NewByteOffset = CurrentIndex + Index.getZExtValue();
3624 bool PastEnd = NewByteOffset != 0;
3634 assert(Ptr.isOpaquePointer());
3635 if (Offset.isZero())
3641 unsigned NumElems = 1;
3646 NumElems = CAT->getZExtSize();
3653 S.
FFDiag(E, diag::note_constexpr_unsized_array_indexed);
3654 return std::nullopt;
3659 return std::nullopt;
3665 NewIndex = Ptr.getIndex() + (Offset.extend(Offset.getBitWidth() + 2));
3668 (Ptr.getByteOffset()) + (Offset.extend(Offset.getBitWidth() + 2));
3672 NewIndex = Ptr.getIndex() - (Offset.extend(Offset.getBitWidth() + 2));
3675 (Ptr.getByteOffset()) - (Offset.extend(Offset.getBitWidth() + 2));
3679 if (NewIndex > NumElems || NewIndex < 0)
3682 if (NewIndex.getActiveBits() > 64)
3683 return std::nullopt;
3691 NewPath[NewPathLength - 1].
Index += Offset.getZExtValue();
3693 NewPath[NewPathLength - 1].
Index -= Offset.getZExtValue();
3702 if (Ptr.isOpaquePointer()) {
3716 Ptr.getByteOffset());
3720 if (!Ptr.isBlockPointer())
3722 if (!Ptr.getFieldDesc()->isRecord())
3725 const Record::Base *VirtBase =
Base.getRecord()->findVirtualBase(
Decl);
3738 if (!Dest.isBlockPointer())
3748 return DoMemcpy(S, OpPC, Src, Dest);
3758 if (!Dest.isBlockPointer() || Dest.isDummy() || Dest.isConstexprUnknown())
3792 return Op == OP_RetVoid || Op == OP_RetValue || Op == OP_NoRet ||
3793 Op == OP_RetSint8 || Op == OP_RetUint8 || Op == OP_RetSint16 ||
3794 Op == OP_RetUint16 || Op == OP_RetSint32 || Op == OP_RetUint32 ||
3795 Op == OP_RetSint64 || Op == OP_RetUint64 || Op == OP_RetIntAP ||
3796 Op == OP_RetIntAPS || Op == OP_RetBool || Op == OP_RetFixedPoint ||
3797 Op == OP_RetPtr || Op == OP_RetMemberPtr || Op == OP_RetFloat ||
3798 Op == OP_EndSpeculation;
3807#define GET_INTERPFN_DISPATCHERS
3808#include "Opcodes.inc"
3809#undef GET_INTERPFN_DISPATCHERS
3814#define GET_INTERPFN_LIST
3815#include "Opcodes.inc"
3816#undef GET_INTERPFN_LIST
3834 return InterpNext(S);
3862 [[maybe_unused]]
CodePtr PCBefore = S.
PC;
3863 size_t StackSizeBefore = S.
Stk.
size();
3869 assert(DepthBefore >= 1);
3872 auto SpeculativeInterp = [&S]() ->
bool {
3895 if (SpeculativeInterp()) {
3900 assert(S.
Stk.
size() == StackSizeBefore);
3906 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 validType(QualType T)
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)
static bool hasLayout(const RecordDecl *D)
Whether layout (offset and size) information can be queried for D.
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 ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
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
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++ constructor within a class.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
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.
Represents the canonical version of C arrays with a specified constant size.
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
QualType getCanonicalType() 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
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 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()
void resetCurrentFrame()
Free resources associated with the current frame and set the caller to be the new current frame.
Context & Ctx
Interpreter Context.
const unsigned EvalID
ID identifying this evaluation.
bool noteStep(CodePtr OpPC)
Note that a step has been executed.
InterpFrame * allocFrame(const Function *F, Ts &&...Args)
Allocate memory and create a new InterpFrame for the given function.
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 isOpaquePointer() const
bool isStringPointer() const
unsigned getNumElems() const
Returns the number of elements.
uint64_t getByteOffset() const
Returns the byte offset from the start.
bool isZero() const
Checks if the pointer is null.
bool isConstexprUnknown() const
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.
const OpaquePointer & asOpaquePointer() const
bool isOnePastEnd() const
Checks if the index is one past end.
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.
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.
bool isUnion() const
Checks if the record is a union.
unsigned getNumVirtualBases() const
bool isAnonymousUnion() const
Checks if the record is an anonymous union.
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)
static bool CheckActive(InterpState &S, CodePtr OpPC, PtrView Ptr, AccessKinds AK, bool WillActivate=false)
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)
bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr, const Type *TargetType)
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)
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 getDynamicDecl(InterpState &S, CodePtr OpPC, const Pointer &Ptr, const CXXRecordDecl *&DynamicDecl)
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 initBasesRecurse(PtrView Ptr)
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.
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
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)
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.
static bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
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.
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK, bool WillBeActivated)
Checks if a value can be stored in a block.
bool virtBaseHelper(InterpState &S, const CXXRecordDecl *Decl, const Pointer &Ptr)
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 diagnoseDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
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)
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 diagnoseArrayIndex(InterpState &S, CodePtr OpPC, const APSInt &Index, std::optional< uint64_t > NumElems, bool IsArray)
static bool Activate(InterpState &S)
static bool CheckVolatile(InterpState &S, CodePtr OpPC, PtrView Ptr, AccessKinds AK)
bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T)
bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest, bool Activate, bool Diagnose)
Copy the contents of Src into Dest.
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)
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is a dummy pointer.
bool DefaultInit(InterpState &S, CodePtr OpPC, const CXXConstructorDecl *Ctor)
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 CheckLoad(InterpState &S, CodePtr OpPC, PtrView Ptr, AccessKinds AK)
static bool CheckLifetime(InterpState &S, CodePtr OpPC, Lifetime LT, const Block *B, AccessKinds AK)
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 Memcpy(InterpState &S, CodePtr OpPC)
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, const CallExpr *CE)
bool TrivialCopy(InterpState &S, CodePtr OpPC, bool Activate, const Function *Func)
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)
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
bool isOnePastEnd() 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 Descriptor * getFieldDesc() const
const FieldDecl * getField() const
void startLifetime() const
const Block * block() const
Lifetime getLifetime() const
PtrView stripBaseCasts() const