27#include "llvm/ADT/ScopeExit.h"
28#include "llvm/ADT/StringExtras.h"
33#if __has_cpp_attribute(clang::musttail)
34#define MUSTTAIL [[clang::musttail]]
35#elif __has_cpp_attribute(msvc::musttail)
36#define MUSTTAIL [[msvc::musttail]]
37#elif __has_attribute(musttail)
38#define MUSTTAIL __attribute__((musttail))
46#if defined(_MSC_VER) || defined(__powerpc__) || !defined(MUSTTAIL) || \
47 defined(__i386__) || defined(__sparc__) || defined(__mips__)
50#define USE_TAILCALLS 0
52#define USE_TAILCALLS 1
59 return !
T->isDependentType() && !
T->isUndeducedAutoType() &&
60 !
T->isSpecificBuiltinType(BuiltinType::UnknownAny) &&
61 !
T->isIncompleteType();
65 llvm::report_fatal_error(
"Interpreter cannot return values");
96 S.
FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
120 S.
FFDiag(Loc, diag::note_constexpr_access_unknown_variable, 1)
122 S.
Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
124 S.
FFDiag(Loc, diag::note_constexpr_function_param_value_unknown, 1) << D;
134 }
else if (
const auto *VD = dyn_cast<VarDecl>(D)) {
135 if (!VD->getAnyInitializer()) {
139 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
140 S.
Note(VD->getLocation(), diag::note_declared_at);
162 if (
const auto *VarD = dyn_cast<VarDecl>(VD);
163 VarD && VarD->isCXXForRangeImplicitVar()) {
165 diag::note_constexpr_ltor_for_range_var)
170 if (
const auto *VarD = dyn_cast<VarDecl>(VD);
171 VarD && VarD->getType().isConstQualified() &&
172 (VarD->isConstexpr() || !VarD->getType()->isArrayType()) &&
173 !VarD->getAnyInitializer()) {
186 S.
FFDiag(Loc, diag::note_constexpr_modify_global);
188 S.
FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
195 S.
getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
196 : diag::note_constexpr_ltor_non_integral,
203 if (
auto ID = Ptr.getDeclID()) {
231 if (Ptr.isBlockPointer()) {
236 if (Ptr.isOpaquePointer())
237 S.
Note(Ptr.asOpaquePointer().Base.getLocation(), diag::note_declared_at);
239 if (Ptr.isStringPointer())
240 S.
Note(Ptr.asStringPointer().getLiteral(),
241 diag::note_constexpr_temporary_here);
250 const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
262 S.
FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
272 if (!Ptr.isBlockPointer())
291 S.
CCEDiag(E, diag::note_constexpr_large_shift)
308 std::optional<uint64_t> NumElems,
bool IsArray) {
313 << Index << !IsArray << NumElems.value_or(0u);
323 unsigned VariadicArgSize =
325 unsigned TargetStackSize = S.
Stk.
size() - VariadicArgSize;
326 while (S.
Stk.
size() != TargetStackSize) {
336 if (
Func->hasImplicitThisPointer())
347 if (Ptr.isFunctionPointer())
349 if (Ptr.isIntegralPointer())
351 if (Ptr.isTypeidPointer())
354 if (Ptr.getType()->isAnyComplexType())
357 if (
const Expr *
Base = Ptr.getRootExpr())
367 assert(Ptr.inUnion());
372 while (!
U.isRoot() && !
U.isActive()) {
377 if (
U.getRecord() &&
U.getRecord()->isAnonymousUnion())
384 assert(
C.getBase() ==
U);
398 if (!
U.getFieldDesc()->isUnion())
408 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(R->getDecl());
409 CXXRD && !CXXRD->hasTrivialDefaultConstructor()) {
421 assert(!
C.isActive());
422 const FieldDecl *InactiveField =
C.getField();
423 assert(InactiveField);
426 const Record *R =
U.getRecord();
427 assert(R && R->isUnion() &&
"Not a union");
430 for (
const Record::Field &F : R->fields()) {
431 PtrView Field =
U.atField(F.Offset);
432 if (Field.isActive()) {
433 ActiveField = Field.getField();
439 diag::note_constexpr_access_inactive_union_member)
440 << AK << InactiveField << !ActiveField << ActiveField;
446 if (!Ptr.isBlockPointer())
448 return CheckActive(S, OpPC, Ptr.view(), AK, WillActivate);
455 if (!Ptr.isPastEnd() &&
456 (Ptr.isInitialized() ||
464 const auto *VD = Ptr.getDeclDesc()->asValueDecl();
477 if (!Ptr.isUnknownSizeArray())
480 S.
FFDiag(E, diag::note_constexpr_unsized_array_indexed);
492 S.
FFDiag(Loc, diag::note_constexpr_access_null) << AK;
498 if (Ptr.isDynamic()) {
500 diag::note_constexpr_access_deleted_object)
522 if (D->getType().isConstQualified())
536 if (
T->isIntegralOrEnumerationType()) {
548 ? diag::note_constexpr_ltor_non_constexpr
549 : diag::note_constexpr_ltor_non_integral,
552 S.
Note(D->getLocation(), diag::note_declared_at);
559 if (
T->isPointerOrReferenceType()) {
577 if (!Ptr.isStatic() || !Ptr.isBlockPointer())
579 if (!Ptr.getDeclID())
589 if (!Ptr.block()->isGlobal())
591 if (!Ptr.block()->getDeclID())
601 S.
FFDiag(Loc, diag::note_constexpr_null_subobject)
609 if (!Ptr.isElementPastEnd() && !Ptr.isZeroSizeArray())
612 S.
FFDiag(Loc, diag::note_constexpr_past_end_subobject)
619 if (!Ptr.isOnePastEnd())
623 S.
FFDiag(Loc, diag::note_constexpr_past_end_subobject)
629 assert(Ptr.isLive() &&
"Pointer is not live");
633 if (Ptr.isMutable() && !Ptr.isConstInMutable())
636 if (!Ptr.isBlockPointer())
642 if (
V.block() != Ptr.block())
644 if (!
V.getFieldDesc()->IsConst) {
659 bool FoundProblem =
false;
660 for (
PtrView P = Ptr.view(); P !=
V; P = P.getBase()) {
661 if (P.getFieldDesc()->IsConst) {
677 if (!Ptr.getFieldDesc()->IsConst)
680 S.
FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
686 assert(Ptr.isLive() &&
"Pointer is not live");
687 if (!Ptr.isMutable())
703 MutablePtr = MutablePtr.
getBase();
707 S.
FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK << Field;
708 S.
Note(Field->getLocation(), diag::note_declared_at);
714 assert(Ptr.isLive());
716 if (!Ptr.isVolatile())
740 Loc = F->getLocation();
744 Loc = VD->getLocation();
749 Loc = E->getExprLoc();
753 diag::note_constexpr_access_volatile_obj, 1)
754 << AK << DiagKind << ND;
755 S.
Note(Loc, diag::note_constexpr_volatile_here) << DiagKind;
761 assert(Ptr.isLive());
762 assert(!Ptr.isInitialized());
764 Ptr.getLifetime(), AK);
782 VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
785 !(S.
getLangOpts().CPlusPlus23 && VD->getType()->isReferenceType())) {
794 S.
Note(VD->getFirstDecl()->getLocation(), diag::note_declared_at);
799 if (VD->getAnyInitializer()) {
801 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
802 S.
Note(VD->getLocation(), diag::note_declared_at);
820 assert(Ptr.isLive());
821 assert(!Ptr.isInitialized());
823 Ptr.getLifetime(), AK);
840 if (!Ptr.isBlockPointer())
842 return CheckLifetime(S, OpPC, Ptr.getLifetime(), Ptr.block(), AK);
853 S.
Note(VD->getLocation(), diag::note_declared_at);
884 diag::note_constexpr_access_volatile_obj, 1)
897 if (!Desc.IsInitialized)
902 if (BlockDesc->IsVolatile) {
906 const ValueDecl *D = BlockDesc->asValueDecl();
908 diag::note_constexpr_access_volatile_obj, 1)
918 if (
const ValueDecl *VD = BlockDesc->asValueDecl())
932 S.
FFDiag(Loc, diag::note_constexpr_access_null) << AK;
936 if (!Ptr.block()->isAccessible()) {
938 if (Ptr.block()->isDynamic()) {
940 diag::note_constexpr_access_deleted_object)
963 if (!Ptr.isInitialized())
966 if (!
CheckLifetime(S, OpPC, Ptr.getLifetime(), Ptr.block(), AK))
976 if (!Ptr.isArrayRoot()) {
991 if (
const auto *CLE =
992 dyn_cast_if_present<CompoundLiteralExpr>(Desc->
asExpr())) {
993 if (
QualType CLETy = CLE->getType();
996 diag::note_invalid_subexpr_in_const_expr)
998 S.
Note(CLE->getExprLoc(), diag::note_declared_at);
1008 if (Ptr.isBlockPointer())
1009 return CheckLoad(S, OpPC, Ptr.view(), AK);
1016 S.
FFDiag(Loc, diag::note_constexpr_access_null) << AK;
1021 if (!Ptr.isStringPointer())
1024 assert(Ptr.isStringPointer());
1030 if (!Ptr.isInitialized())
1038 assert(!Ptr.isZero());
1039 if (!Ptr.isReadablePointerType())
1042 if (Ptr.isBlockPointer() && !Ptr.block()->isAccessible()) {
1052 if (Ptr.isPastEnd())
1060 if (!Ptr.isInitialized())
1063 if (Ptr.isBlockPointer()) {
1079 if (Ptr.isOpaquePointer())
1082 if (!Ptr.isBlockPointer())
1085 if (!Ptr.block()->isAccessible()) {
1096 if (!
CheckActive(S, OpPC, Ptr, AK, WillBeActivated))
1110 bool IsCtor,
bool IsDtor) {
1111 if (!Ptr.isDummy() && !Ptr.isConstexprUnknown()) {
1127 if (!Ptr.isBlockPointer())
1146 StringRef Name = DiagDecl->
getName();
1148 Name ==
"__assert_rtn" || Name ==
"__assert_fail" || Name ==
"_wassert";
1151 diag::note_constexpr_assert_failed);
1158 diag::note_invalid_subexpr_in_const_expr);
1164 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
1165 if (CD && CD->isInheritingConstructor()) {
1166 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
1167 if (!Inherited->isConstexpr())
1168 DiagDecl = CD = Inherited;
1173 if (CD && CD->getParent()->isInvalidDecl())
1179 if (CD && CD->isInheritingConstructor()) {
1182 << CD->getInheritedConstructor().getConstructor()->getParent();
1190 if (!IsDefined && !IsExtern && DiagDecl->
isConstexpr() &&
1200 diag::note_constexpr_invalid_function, 1)
1201 << DiagDecl->
isConstexpr() << (bool)CD << DiagDecl;
1217 S.
CCEDiag(Loc, diag::note_constexpr_virtual_call);
1241 diag::note_constexpr_depth_limit_exceeded)
1258 bool IsImplicit =
false;
1259 if (
const auto *TE = dyn_cast<CXXThisExpr>(E))
1260 IsImplicit = TE->isImplicit();
1261 S.
FFDiag(E, diag::note_constexpr_this) << IsImplicit;
1276 if ((Status & APFloat::opInexact) &&
1281 S.
FFDiag(E, diag::note_constexpr_dynamic_rounding);
1285 if ((Status != APFloat::opOK) &&
1288 FPO.getAllowFEnvAccess())) {
1290 S.
FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
1294 if ((Status & APFloat::opStatus::opInvalidOp) &&
1306 APFloat::opStatus Status,
FPOptions FPO) {
1317 S.
CCEDiag(E, diag::note_constexpr_float_arithmetic)
1330 S.
CCEDiag(E, diag::note_constexpr_new);
1337 const Expr *NewExpr) {
1338 if (AllocForm == DeleteForm)
1344 S.
FFDiag(E, diag::note_constexpr_new_delete_mismatch)
1345 <<
static_cast<int>(DeleteForm) <<
static_cast<int>(AllocForm)
1347 S.
Note(NewExpr->
getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
1353 if (Ptr.isBlockPointer() && Ptr.block()->isDynamic())
1358 S.
FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
1381 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
1382 S.
Note(VD->getLocation(), diag::note_declared_at);
1395 const VarDecl *D = Ptr.getRootVarDecl();
1414 const CallExpr *CE,
unsigned ArgSize) {
1417 unsigned Offset = 0;
1419 for (
const Expr *Arg : Args) {
1420 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
1424 S.
CCEDiag(Loc, diag::note_non_null_attribute_failed);
1446 S.
FFDiag(Loc, diag::note_constexpr_double_destroy);
1453 assert(!
Dtor->isTrivial());
1459 return Call(S, OpPC, DtorFunc, 0);
1482 for (
int I =
static_cast<int>(N) - 1; I >= 0; --I) {
1496 return DD->isVirtual();
1501 bool IsGlobalDelete) {
1507 const Expr *Source =
nullptr;
1508 const Block *BlockToDelete =
nullptr;
1518 if (!Ptr.isBlockPointer())
1522 QualType InitialType = Ptr.getType();
1523 Ptr = Ptr.expand().stripBaseCasts();
1525 Source = Ptr.getRootExpr();
1526 BlockToDelete = Ptr.block();
1530 if (std::optional<DynamicAllocator::Form> AllocForm =
1542 if (!DeleteIsArrayForm && Ptr.getType() != InitialType &&
1545 diag::note_constexpr_delete_base_nonvirt_dtor)
1546 << InitialType << Ptr.getType();
1550 if (!Ptr.isRoot() || (Ptr.isOnePastEnd() && !Ptr.isZeroSizeArray()) ||
1551 (Ptr.isArrayElement() && Ptr.getIndex() != 0)) {
1553 S.
FFDiag(Loc, diag::note_constexpr_delete_subobject)
1554 << Ptr.toDiagnosticString(S.
getASTContext()) << Ptr.isOnePastEnd();
1563 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1564 QualType AllocType = Ptr.getType();
1568 return DD->isVirtual() ? DD->getOperatorDelete() :
nullptr;
1578 diag::note_constexpr_new_non_replaceable)
1585 assert(BlockToDelete);
1591 if (!Allocator.
deallocate(Source, BlockToDelete)) {
1594 S.
FFDiag(Loc, diag::note_constexpr_double_delete);
1611 S.
CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1612 << llvm::toString(
Value, 10) <<
Min.getSExtValue() <<
Max.getSExtValue()
1616 S.
CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1617 << llvm::toString(
Value, 10) <<
Min.getZExtValue() <<
Max.getZExtValue()
1648 S.
FFDiag(E, diag::note_constexpr_nonliteral) << E->
getType();
1650 S.
FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
1655 const Pointer &Ptr,
unsigned Offset) {
1656 assert(Ptr.isTypeidPointer());
1658 Ptr.asTypeidPointer().TypeInfoType->getAsRecordDecl());
1661 const Record::Field *Field = R->findField(Offset);
1665 std::string TypeIdStr;
1666 llvm::raw_string_ostream SS(TypeIdStr);
1668 QualType(Ptr.asTypeidPointer().TypePtr, 0)
1671 SS << Field->Decl->getNameAsString();
1674 diag::note_constexpr_access_unreadable_object)
1681 diag::note_constexpr_null_subobject);
1697 if (Ptr.isIntegralPointer()) {
1698 if (std::optional<IntPointer> IntPtr =
1699 Ptr.asIntPointer().atOffset(S.
Ctx,
Off)) {
1706 if (Ptr.isOpaquePointer()) {
1715 const Record::Field *F = R->findField(
Off);
1723 F->Decl->getType().getTypePtr()),
1724 Ptr.getByteOffset());
1729 if (!Ptr.isBlockPointer()) {
1732 if (Ptr.isTypeidPointer())
1738 if (!Ptr.getFieldDesc()->isRecord())
1741 if ((Ptr.getByteOffset() +
Off) >= Ptr.block()->getSize())
1759 uint32_t
Off,
bool NullOK) {
1763 if (Ptr.isOpaquePointer()) {
1771 const Record::Base *B = R->findBase(
Off);
1782 Ptr.getByteOffset());
1786 if (!Ptr.isBlockPointer()) {
1787 if (!Ptr.isIntegralPointer())
1798 if (!Ptr.getFieldDesc()->isRecord()) {
1812 return getBase(S, OpPC, Ptr.narrow(),
Off,
true);
1816 return getBase(S, OpPC, Ptr.narrow(),
Off, NullOK);
1821 const Type *TargetType,
const Type *FinalType) {
1826 if (!Ptr.isBlockPointer()) {
1834 if (!Ptr.getFieldDesc()->isRecord()) {
1842 auto diagFailedCast = [&]() ->
bool {
1843 QualType MostDerivedType = Ptr.getDeclDesc()->getType();
1845 << MostDerivedType <<
QualType(FinalType, 0);
1852 return diagFailedCast();
1855 if (
T->isPointerOrReferenceType())
1856 return T->getPointeeType().getTypePtr();
1857 return T.getTypePtr();
1860 PtrView BasePtr = Ptr.view().getBase();
1861 const Type *BaseTy = unwrapPointerType(BasePtr.
getType());
1863 return diagFailedCast();
1871 assert(
Func->isConstructor());
1873 if (
Func->getParentDecl()->isInvalidDecl())
1889 <<
Func->getParentDecl();
1897 if (
const Decl *D = Ptr.getDeclDesc()->asDecl()) {
1899 S.
FFDiag(ND->getLocation(), diag::note_constexpr_destroy_out_of_lifetime)
1900 << ND->getNameAsString();
1902 S.
FFDiag(Ptr.getDeclDesc()->getLocation(),
1903 diag::note_constexpr_destroy_out_of_lifetime)
1928 if (Ptr.isStringPointer()) {
1930 diag::note_constexpr_access_unreadable_object)
1936 if (Ptr.isOpaquePointer() || Ptr.block()->isGlobal()) {
1938 S.
FFDiag(E, diag::note_constexpr_modify_global);
1961 bool SrcIsVoidPtr) {
1965 if (!Ptr.isBlockPointer())
1972 bool HasValidResult = !Ptr.isZero();
1974 if (HasValidResult) {
1984 S.
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
1985 << E->getSubExpr()->getType() << S.
getLangOpts().CPlusPlus26
1986 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
1989 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
1990 << diag::ConstexprInvalidCastKind::CastFrom <<
"'void *'"
1999 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2006 const Type *TargetType) {
2010 bool HasValidResult = !Ptr.isZero();
2012 if (HasValidResult) {
2022 S.
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
2023 << E->getSubExpr()->getType() << S.
getLangOpts().CPlusPlus26
2024 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
2027 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
2028 << diag::ConstexprInvalidCastKind::CastFrom <<
"'void *'"
2033 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
2034 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2039 if (Ptr.isOpaquePointer()) {
2080 uint32_t VarArgSize) {
2081 if (
Func->hasThisPointer()) {
2082 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2092 Func->isLambdaCallOperator())) {
2094 Func->isDestructor()))
2102 if (!
Func->isFullyCompiled())
2121 uint32_t VarArgSize) {
2128 auto cleanup = [&]() ->
bool {
2133 bool InstancePtrTracked =
false;
2134 if (
Func->hasThisPointer()) {
2135 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2152 Func->isLambdaCallOperator()) {
2153 assert(ThisPtr.
isZero());
2156 Func->isDestructor()))
2159 if (
Func->isCopyOrMoveOperator() ||
Func->isCopyOrMoveConstructor()) {
2166 if (!
Func->isConstructor() && !
Func->isDestructor() &&
2176 InstancePtrTracked = (
Func->isConstructor() ||
Func->isDestructor());
2177 if (InstancePtrTracked)
2181 if (!
Func->isFullyCompiled())
2202 if (InstancePtrTracked)
2212 auto diagUnknownDynamicType = [&](
const Pointer &P) ->
bool {
2216 diag::note_constexpr_polymorphic_unknown_dynamic_type)
2221 if (!Ptr.isBlockPointer())
2222 return diagUnknownDynamicType(Ptr);
2228 auto depth = [](
PtrView V) ->
unsigned {
2230 while (!
V.isRoot()) {
2247 assert(depth(TypePtr) >= depth(InitPtr));
2248 unsigned D = depth(TypePtr) - depth(InitPtr);
2249 for (
unsigned I = 0; I != D; ++I)
2257 return diagUnknownDynamicType(
Pointer(TypePtr));
2261 DynamicDecl =
DynamicType->getPointeeCXXRecordDecl();
2269 return DynamicDecl !=
nullptr;
2273struct DynamicCastResult {
2277 bool valid()
const {
return !
Ambiguous && Offset; }
2279 void setOffset(
unsigned O) {
2287 void merge(DynamicCastResult
C) {
2288 Ambiguous |=
C.Ambiguous;
2302 DynamicCastResult Res;
2307 for (
const Record::Base &B : R->bases()) {
2310 N.Offset = *N.Offset + B.Offset;
2318 bool IsReferenceCast) {
2322 if (Ptr.isConstexprUnknown() || Ptr.isOpaquePointer()) {
2327 S.
FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
2332 if (!Ptr.isBlockPointer() || !Ptr.getRecord())
2335 if (!Ptr.isInitialized())
2343 LimitedPtr = Ptr.stripBaseCasts().view();
2346 assert(LimitedPtr.
block() == Ptr.block());
2353 if (TargetType->isVoidType()) {
2358 assert(!TargetType.isNull());
2359 assert(!TargetType->isVoidType());
2360 assert(TargetType->isRecordType());
2367 assert(P.getRecord());
2371 auto baseIsPrivate = [&](
PtrView P) ->
bool {
2372 if (P.isRoot() || !P.isBaseClass())
2376 getRecord(P.getBase())->isDerivedFrom(getRecord(P), Paths);
2381 return llvm::all_of(Paths, [](
const CXXBasePath &P) ->
bool {
2387 DiagPrivateBase = 0,
2390 DiagPrivateSibling = 3
2393 auto diag = [&](
int DiagKind,
QualType ResultType) ->
bool {
2395 if (!IsReferenceCast) {
2401 diag::note_constexpr_dynamic_cast_to_reference_failed)
2402 << DiagKind << ResultType <<
DynamicType << TargetType;
2411 getRecord(LimitedPtr)
2412 ->isDerivedFrom(TargetType->castAsCXXRecordDecl(), Paths);
2413 if (std::distance(Paths.
begin(), Paths.
end()) == 0 &&
2414 !typesMatch(LimitedPtr.
getType(), TargetType)) {
2415 return diag(DiagNoBase, TargetType);
2420 if (baseIsPrivate(Ptr.view()))
2421 return diag(DiagPrivateBase, Ptr.getType());
2423 std::optional<PtrView>
Result;
2425 for (
PtrView Iter = Ptr.view();;) {
2426 if (Iter.isRoot() || !Iter.isBaseClass())
2429 if (typesMatch(TargetType, Iter.getType())) {
2434 Iter = Iter.getBase();
2440 if (baseIsPrivate(*
Result))
2441 return diag(DiagPrivateBase,
Result->getType());
2448 for (
PtrView Iter = LimitedPtr;;) {
2454 Result = Iter.atField(*R.Offset);
2462 if (Iter.isRoot() || !Iter.isBaseClass())
2465 Iter = Iter.getBase();
2469 return diag(DiagAmbiguous, TargetType);
2473 if (baseIsPrivate(*
Result))
2474 return diag(DiagPrivateSibling, TargetType);
2480 return diag(DiagNoBase, TargetType);
2484 uint32_t VarArgSize) {
2486 if (!
Func->hasThisPointer()) {
2487 assert(!
Func->isValid());
2491 assert(
Func->hasThisPointer());
2492 assert(
Func->isVirtual());
2493 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2505 assert(DynamicDecl);
2507 const auto *StaticDecl =
Func->getParentDecl();
2511 if (StaticDecl != DynamicDecl) {
2518 Overrider = InitialFunction;
2528 S.
Note(Callee->getLocation(), diag::note_declared_at);
2532 if (Overrider != InitialFunction) {
2545 if (
Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
2553 if (!
Call(S, OpPC,
Func, VarArgSize))
2558 if (Overrider != InitialFunction &&
2560 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
2568 OverriderPointeeType))
2585 uint32_t BuiltinID) {
2588 if (BuiltinID == Builtin::BI__builtin_operator_new &&
2605 if (!Ptr.isFunctionPointer())
2608 const Function *F = Ptr.asFunctionPointer().Func;
2652 return CallVirt(S, OpPC, F, VarArgSize);
2654 return Call(S, OpPC, F, VarArgSize);
2658 if (
const Record *R = Ptr.getRecord()) {
2659 Ptr.startLifetime();
2661 for (
const Record::Field &Fi : R->fields()) {
2662 PtrView FP = Ptr.atField(Fi.Offset);
2669 if (
const Descriptor *FieldDesc = Ptr.getFieldDesc();
2670 FieldDesc->isCompositeArray()) {
2671 for (
unsigned I = 0; I != FieldDesc->getNumElems(); ++I) {
2672 PtrView EP = Ptr.atIndex(I).narrow();
2679 Ptr.startLifetime();
2687 if (!Ptr.isBlockPointer())
2698 if (!Ptr.isBlockPointer())
2700 Ptr.startLifetime();
2707 if (
const Record *R = Ptr.getRecord()) {
2708 Ptr.setLifeState(L);
2709 for (
const Record::Field &Fi : R->fields())
2714 if (
const Descriptor *FieldDesc = Ptr.getFieldDesc();
2715 FieldDesc->isCompositeArray()) {
2717 if (Ptr.getFieldDesc()->isPrimitiveArray())
2719 for (
unsigned I = 0; I != FieldDesc->getNumElems(); ++I)
2724 Ptr.setLifeState(L);
2758 assert(Ptr.getRecord());
2760 const Record *R = Ptr.getRecord();
2761 for (
const Record::Base &B : R->bases()) {
2762 PtrView BasePtr = Ptr.atField(B.Offset);
2768 for (
const Record::Field &F : R->fields()) {
2769 PtrView FieldPtr = Ptr.atField(F.Offset);
2775 for (
const Record::Base &B : R->virtual_bases()) {
2776 PtrView BasePtr = Ptr.atField(B.Offset);
2786 if (!Ptr.isBlockPointer())
2788 const Record *R = Ptr.getRecord();
2800 diag::note_constexpr_invalid_function, 1)
2805 diag::note_invalid_subexpr_in_const_expr);
2809 Ptr.startLifetime();
2819 std::optional<uint64_t> ArraySize) {
2823 auto directBaseIsUnion = [](
const Pointer &Ptr) ->
bool {
2824 if (Ptr.isArrayElement())
2826 const Record *R = Ptr.getBase().getRecord();
2827 return R && R->isUnion();
2830 if (Ptr.inUnion() && directBaseIsUnion(Ptr))
2841 if (!Ptr.isBlockPointer())
2851 if (!Ptr.block()->isAccessible()) {
2862 for (
PtrView P = Ptr.view();;) {
2880 QualType StorageType = Ptr.getType();
2884 NewExpr->getAllocatedType(),
2885 APInt(64,
static_cast<uint64_t
>(*ArraySize),
false),
nullptr,
2888 AllocType = NewExpr->getAllocatedType();
2891 if (AllocType->
isArrayType() && Ptr.isArrayElement() &&
2892 Ptr.expand().getIndex() == 0) {
2900 StorageType = Ptr.expand().getArray().getType();
2907 diag::note_constexpr_placement_new_wrong_type)
2908 << StorageType << AllocType;
2913 if (Ptr.inUnion() && !Ptr.isActive() && !directBaseIsUnion(Ptr))
2923 if (
const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
2924 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
2928 bool IsNothrowForm = NewExpr->getNumPlacementArgs() == 1 &&
2930 if (NewExpr->getNumPlacementArgs() > 0 && !IsNothrowForm) {
2931 S.
FFDiag(Loc, diag::note_constexpr_new_placement)
2937 !OperatorNew->isUsableAsGlobalAllocationFunctionInConstantEvaluation());
2938 S.
FFDiag(Loc, diag::note_constexpr_new_non_replaceable)
2944 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
2945 assert(!OperatorDelete
2946 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation());
2947 S.
FFDiag(Loc, diag::note_constexpr_new_non_replaceable)
2969 E->
getExprLoc(), diag::warn_fixedpoint_constant_overflow)
2972 S.
CCEDiag(E, diag::note_constexpr_overflow)
2980 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
2986 const Pointer &Ptr,
unsigned BitWidth) {
2989 S.
CCEDiag(E, diag::note_constexpr_invalid_cast_ptrtoint)
2990 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2992 if ((Ptr.isBlockPointer() && !Ptr.isZero()) || Ptr.isOpaquePointer())
2994 if (Ptr.isIntegralPointer())
2997 if (Ptr.isOpaquePointer()) {
3000 return Ptr.isRoot();
3003 if (!Ptr.isZero()) {
3023 Result.copy(
APInt(BitWidth, Ptr.getIntegerRepresentation()));
3036 Result.copy(
APInt(BitWidth, Ptr.getIntegerRepresentation()));
3043 bool TargetIsUCharOrByte) {
3045 if (!HasIndeterminateBits)
3049 if (TargetIsUCharOrByte)
3054 S.
FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
3066 if (!ID.IsInitialized) {
3069 diag::note_constexpr_use_uninit_reference);
3086 if (!P.isBlockPointer() && !P.isOpaquePointer())
3089 if (P.isConstexprUnknown()) {
3094 S.
FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
3101 if (P.isBlockPointer())
3102 T = P.stripBaseCasts().getType()->getCanonicalTypeUnqualified();
3104 T = P.getType()->getCanonicalTypeUnqualified();
3111 Func && (
Func->isConstructor() ||
Func->isDestructor()) &&
3112 P.block() ==
Frame->getThis().block()) {
3114 Func->getParentDecl());
3126 S.
CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
3127 << E->getExprOperand()->getType()
3128 << E->getExprOperand()->getSourceRange();
3142 StringRef LHSStr(LHSLit->getBytes());
3143 unsigned LHSLength = LHSStr.size();
3144 StringRef RHSStr(RHSLit->getBytes());
3145 unsigned RHSLength = RHSStr.size();
3147 int32_t IndexDiff = RHSOffset - LHSOffset;
3148 if (IndexDiff < 0) {
3149 if (
static_cast<int32_t
>(LHSLength) < -IndexDiff)
3151 LHSStr = LHSStr.drop_front(-IndexDiff);
3153 if (
static_cast<int32_t
>(RHSLength) < IndexDiff)
3155 RHSStr = RHSStr.drop_front(IndexDiff);
3158 unsigned ShorterCharWidth;
3161 if (LHSLength < RHSLength) {
3162 ShorterCharWidth = LHSLit->getCharByteWidth();
3166 ShorterCharWidth = RHSLit->getCharByteWidth();
3174 for (
unsigned NullByte : llvm::seq(ShorterCharWidth)) {
3175 if (Shorter.size() + NullByte >= Longer.size())
3177 if (Longer[Shorter.size() + NullByte])
3180 return Shorter == Longer.take_front(Shorter.size());
3186 if (!Val.singleWord()) {
3187 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
3188 Val.take(NewMemory);
3192 if (!Val.singleWord()) {
3193 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
3194 Val.take(NewMemory);
3198 if (!Val.singleWord()) {
3199 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
3200 Val.take(NewMemory);
3206 std::copy_n(Val.path(), PathLength, NewPath);
3207 Val.takePath(NewPath);
3209 auto &Val = Ptr.deref<
Pointer>();
3210 if (Val.isOpaquePointer() && Val.asOpaquePointer().PathLength != 0) {
3217 Val.getByteOffset());
3222template <
typename T>
3225 if constexpr (std::is_same_v<T, MemberPointer>) {
3229 std::copy_n(Val.path(), PathLength, NewPath);
3230 Val.takePath(NewPath);
3231 }
else if constexpr (std::is_same_v<T, Pointer>) {
3232 auto &Val = Ptr.deref<
Pointer>();
3233 if (Val.isOpaquePointer() && Val.asOpaquePointer().PathLength != 0) {
3240 Val.getByteOffset());
3243 auto &Val = Ptr.deref<
T>();
3244 if (!Val.singleWord()) {
3245 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
3246 Val.take(NewMemory);
3252 if (
const Record *R = Ptr.getRecord()) {
3253 for (
const Record::Field &Fi : R->fields()) {
3254 if (Fi.Desc->isPrimitive()) {
3256 copyPrimitiveMemory<T>(S, Ptr.atField(Fi.Offset));
3265 if (
const Descriptor *D = Ptr.getFieldDesc(); D && D->isArray()) {
3266 unsigned NumElems = D->getNumElems();
3270 if (D->isPrimitiveArray()) {
3274 assert(NumElems >= 1);
3276 bool AllSingleWord =
true;
3278 if (!EP.
deref<
T>().singleWord()) {
3280 AllSingleWord =
false;
3285 for (
unsigned I = 1; I != D->getNumElems(); ++I) {
3290 assert(D->isCompositeArray());
3291 for (
unsigned I = 0; I != D->getNumElems(); ++I) {
3292 PtrView EP = Ptr.atIndex(I).narrow();
3301 if (!Ptr.isBlockPointer())
3316 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3317 << diag::ConstexprInvalidCastKind::Reinterpret
3326 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3327 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3333 const auto *CE = dyn_cast<CastExpr>(E);
3335 S.
FFDiag(E, diag::note_constexpr_access_volatile_type)
3336 <<
AK_Read << CE->getSubExpr()->getType();
3344 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3345 << diag::ConstexprInvalidCastKind::Dynamic;
3348 llvm_unreachable(
"Unhandled CastKind");
3380 if (!MemberPtr.getDecl()) {
3386 if (MemberPtr.getPathLength() >= 2)
3387 Expected = MemberPtr.getPathEntry(MemberPtr.getPathLength() - 2);
3389 Expected = MemberPtr.getRecordDecl();
3402 unsigned OldPathLength = MemberPtr.getPathLength();
3403 unsigned NewPathLength = OldPathLength - 1;
3404 bool IsDerivedMember = NewPathLength != 0;
3406 std::copy_n(MemberPtr.path(), NewPathLength, NewPath);
3409 NewPath, IsDerivedMember));
3417 bool IsDerivedMember) {
3418 unsigned OldPathLength = MemberPtr.getPathLength();
3419 unsigned NewPathLength = OldPathLength + 1;
3422 std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
3426 NewPath, IsDerivedMember));
3435 if (!Ptr.isDerivedMember() && Ptr.hasPath())
3438 bool IsDerivedMember = Ptr.isDerivedMember() || !Ptr.hasPath();
3447 if (!Ptr.isDerivedMember()) {
3464 if (!MP.isBaseCastPossible())
3475 const auto *FD = dyn_cast_if_present<FunctionDecl>(D);
3479 const auto *
Method = dyn_cast<CXXMethodDecl>(FD);
3486 if (!
Base.getRecord() ||
Base.getRecord()->getDecl() != MethodParent)
3503 unsigned NewPathLength = OldPathLength + 1;
3506 std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
3510 MemberPtr.withPath(NewPathLength, NewPath, IsDerived));
3514template <
bool Signed>
3516 uint32_t BitWidth, uint32_t FPOI) {
3521 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite() &&
3548 APSInt &&Index,
bool AllowReplace) {
3557 ElemType = AT->getElementType();
3562 unsigned IndexBits = std::max(Index.getBitWidth(), 32u) + 1;
3564 Index.extend(IndexBits) +
3565 APSInt(
APInt(IndexBits, Ptr.getIndex()), Index.isUnsigned());
3567 if (NewIndex > Ptr.getNumElems() || NewIndex.isNegative())
3571 if (NewIndex.getActiveBits() > 64)
3574 unsigned NewPathLength;
3585 if (Index.isNonNegative())
3594 Ptr.getByteOffset());
3597 unsigned IndexBits = std::max(Index.getBitWidth(), 64u) + 1;
3598 size_t CurrentIndex = Ptr.getByteOffset();
3600 Index.extend(IndexBits) +
3601 APSInt(
APInt(IndexBits, CurrentIndex), Index.isUnsigned());
3602 if (NewOffset > 1 || NewOffset.isNegative())
3605 if (NewOffset.getActiveBits() > 64)
3608 size_t NewByteOffset = CurrentIndex + Index.getZExtValue();
3609 bool PastEnd = NewByteOffset != 0;
3619 assert(Ptr.isOpaquePointer());
3620 if (Offset.isZero())
3626 unsigned NumElems = 1;
3631 NumElems = CAT->getZExtSize();
3638 S.
FFDiag(E, diag::note_constexpr_unsized_array_indexed);
3639 return std::nullopt;
3644 return std::nullopt;
3650 NewIndex = Ptr.getIndex() + (Offset.extend(Offset.getBitWidth() + 2));
3653 (Ptr.getByteOffset()) + (Offset.extend(Offset.getBitWidth() + 2));
3657 NewIndex = Ptr.getIndex() - (Offset.extend(Offset.getBitWidth() + 2));
3660 (Ptr.getByteOffset()) - (Offset.extend(Offset.getBitWidth() + 2));
3664 if (NewIndex > NumElems || NewIndex < 0)
3667 if (NewIndex.getActiveBits() > 64)
3668 return std::nullopt;
3676 NewPath[NewPathLength - 1].
Index += Offset.getZExtValue();
3678 NewPath[NewPathLength - 1].
Index -= Offset.getZExtValue();
3687 if (Ptr.isOpaquePointer()) {
3701 Ptr.getByteOffset());
3705 if (!Ptr.isBlockPointer())
3707 if (!Ptr.getFieldDesc()->isRecord())
3710 const Record::Base *VirtBase =
Base.getRecord()->findVirtualBase(
Decl);
3723 if (!Dest.isBlockPointer())
3729 return DoMemcpy(S, OpPC, Src, Dest);
3739 if (!Dest.isBlockPointer() || Dest.isDummy() || Dest.isConstexprUnknown())
3773 return Op == OP_RetVoid || Op == OP_RetValue || Op == OP_NoRet ||
3774 Op == OP_RetSint8 || Op == OP_RetUint8 || Op == OP_RetSint16 ||
3775 Op == OP_RetUint16 || Op == OP_RetSint32 || Op == OP_RetUint32 ||
3776 Op == OP_RetSint64 || Op == OP_RetUint64 || Op == OP_RetIntAP ||
3777 Op == OP_RetIntAPS || Op == OP_RetBool || Op == OP_RetFixedPoint ||
3778 Op == OP_RetPtr || Op == OP_RetMemberPtr || Op == OP_RetFloat ||
3779 Op == OP_RetReflect || Op == OP_EndSpeculation;
3788#define GET_INTERPFN_DISPATCHERS
3789#include "Opcodes.inc"
3790#undef GET_INTERPFN_DISPATCHERS
3795#define GET_INTERPFN_LIST
3796#include "Opcodes.inc"
3797#undef GET_INTERPFN_LIST
3815 return InterpNext(S);
3843 [[maybe_unused]]
CodePtr PCBefore = S.
PC;
3844 size_t StackSizeBefore = S.
Stk.
size();
3850 assert(DepthBefore >= 1);
3853 auto SpeculativeInterp = [&S]() ->
bool {
3876 if (SpeculativeInterp()) {
3881 assert(S.
Stk.
size() == StackSizeBefore);
3887 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)
bool FunctionDefinitionCanBeLazilyInstantiated(const FunctionDecl *FD)
Whether we can instantiate FD during constant evaluation.
static PRESERVE_NONE bool RetValue(InterpState &S)
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 diagnoseMissingInitializer(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
static bool Jt(InterpState &S, CodePtr OpPC, int32_t Offset)
#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.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
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.
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.
Classes implementing SemaProxy present a restricted view of the (possibly mutating) actions and queri...
virtual void instantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function)=0
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.
CXXRecordDecl * castAsCXXRecordDecl() const
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 isConstexprUnknown() const
bool isTemporary() const
Checks if the block is temporary.
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.
Pointer getLocalPointer(unsigned Offset) const
Returns a pointer to a local variables.
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
SourceRange getRange(CodePtr PC) 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
Block * getLocalBlock(unsigned Offset) const
bool hasThisPointer() const
const Expr * getExpr(CodePtr PC) 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.
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.
void enterFrame(InterpFrame *F)
Set the given frame as the current one.
PointerPathEntry * allocPointerPath(unsigned Length, const PointerPathEntry *OldPP)
const CXXRecordDecl ** allocMemberPointerPath(unsigned Length)
void deallocate(Block *B)
Deallocates a pointer.
void exitFrame()
Free resources associated with the current frame and set the caller to be the new current frame.
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 Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
UnsignedOrNone getCurrentDecl() const
Returns the current declaration ID.
Structure/Class descriptor.
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)
SemaProxy * getSemaProxy() const
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 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 CheckDeleteSource(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Check the source of the pointer passed to delete/delete[] has actually been heap allocated by us.
bool CastMemberPtrDerivedPop(InterpState &S, int32_t Off, const RecordDecl *BaseDecl)
BaseToDerivedMemberPointer.
static DynamicCastResult findRecordBase(const ASTContext &Ctx, const Record *R, QualType Needle)
static void compileFunction(InterpState &S, const Function *Func, CodePtr OpPC)
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 GetPtrDerivedPop(InterpState &S, CodePtr OpPC, bool NullOK, const Type *TargetType, const Type *FinalType)
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 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 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 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 void noteValueLocation(InterpState &S, const Block *B)
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)
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 CheckPlacementNew(InterpState &S, CodePtr OpPC, const Expr *E)
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)
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK)
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)
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t
Describes a memory block created by an allocation site.
unsigned getNumElems() const
Returns the number of elements stored in the block.
SourceLocation getLocation() const
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.
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 Record *const ElemRecord
Pointer to the record, if block contains records.
const Expr * asExpr() const
Descriptor used for global variables.
Lifetime getLifetime() const
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