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))
45#if defined(_MSC_VER) || defined(__powerpc__) || !defined(MUSTTAIL) || \
46 defined(__i386__) || defined(__sparc__) || defined(__mips__)
49#define USE_TAILCALLS 0
51#define USE_TAILCALLS 1
58 return !
T->isDependentType() && !
T->isUndeducedAutoType() &&
59 !
T->isSpecificBuiltinType(BuiltinType::UnknownAny) &&
60 !
T->isIncompleteType();
64 llvm::report_fatal_error(
"Interpreter cannot return values");
95 S.
FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
119 S.
FFDiag(Loc, diag::note_constexpr_access_unknown_variable, 1)
121 S.
Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
123 S.
FFDiag(Loc, diag::note_constexpr_function_param_value_unknown, 1) << D;
133 }
else if (
const auto *VD = dyn_cast<VarDecl>(D)) {
134 if (!VD->getAnyInitializer()) {
138 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
139 S.
Note(VD->getLocation(), diag::note_declared_at);
161 if (
const auto *VarD = dyn_cast<VarDecl>(VD);
162 VarD && VarD->isCXXForRangeImplicitVar()) {
164 diag::note_constexpr_ltor_for_range_var)
169 if (
const auto *VarD = dyn_cast<VarDecl>(VD);
170 VarD && VarD->getType().isConstQualified() &&
171 (VarD->isConstexpr() || !VarD->getType()->isArrayType()) &&
172 !VarD->getAnyInitializer()) {
185 S.
FFDiag(Loc, diag::note_constexpr_modify_global);
187 S.
FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
194 S.
getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
195 : diag::note_constexpr_ltor_non_integral,
202 if (
auto ID = Ptr.getDeclID()) {
230 if (Ptr.isBlockPointer()) {
235 if (Ptr.isOpaquePointer())
236 S.
Note(Ptr.asOpaquePointer().Base.getLocation(), diag::note_declared_at);
238 if (Ptr.isStringPointer())
239 S.
Note(Ptr.asStringPointer().getLiteral(),
240 diag::note_constexpr_temporary_here);
249 const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
261 S.
FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
271 if (!Ptr.isBlockPointer())
290 S.
CCEDiag(E, diag::note_constexpr_large_shift)
307 std::optional<uint64_t> NumElems,
bool IsArray) {
312 << Index << !IsArray << NumElems.value_or(0u);
322 unsigned VariadicArgSize =
324 unsigned TargetStackSize = S.
Stk.
size() - VariadicArgSize;
325 while (S.
Stk.
size() != TargetStackSize) {
335 if (
Func->hasImplicitThisPointer())
356 if (Ptr.isFunctionPointer())
358 if (Ptr.isIntegralPointer())
360 if (Ptr.isTypeidPointer())
363 if (Ptr.getType()->isAnyComplexType())
366 if (
const Expr *
Base = Ptr.getRootExpr())
376 assert(Ptr.inUnion());
381 while (!
U.isRoot() && !
U.isActive()) {
386 if (
U.getRecord() &&
U.getRecord()->isAnonymousUnion())
393 assert(
C.getBase() ==
U);
407 if (!
U.getFieldDesc()->isUnion())
417 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(R->getDecl());
418 CXXRD && !CXXRD->hasTrivialDefaultConstructor()) {
430 assert(!
C.isActive());
431 const FieldDecl *InactiveField =
C.getField();
432 assert(InactiveField);
435 const Record *R =
U.getRecord();
436 assert(R && R->isUnion() &&
"Not a union");
439 for (
const Record::Field &F : R->fields()) {
440 PtrView Field =
U.atField(F.Offset);
441 if (Field.isActive()) {
442 ActiveField = Field.getField();
448 diag::note_constexpr_access_inactive_union_member)
449 << AK << InactiveField << !ActiveField << ActiveField;
455 if (!Ptr.isBlockPointer())
457 return CheckActive(S, OpPC, Ptr.view(), AK, WillActivate);
464 if (!Ptr.isPastEnd() &&
465 (Ptr.isInitialized() ||
473 const auto *VD = Ptr.getDeclDesc()->asValueDecl();
486 if (!Ptr.isUnknownSizeArray())
489 S.
FFDiag(E, diag::note_constexpr_unsized_array_indexed);
501 S.
FFDiag(Loc, diag::note_constexpr_access_null) << AK;
507 if (Ptr.isDynamic()) {
509 diag::note_constexpr_access_deleted_object)
531 if (D->getType().isConstQualified())
545 if (
T->isIntegralOrEnumerationType()) {
557 ? diag::note_constexpr_ltor_non_constexpr
558 : diag::note_constexpr_ltor_non_integral,
561 S.
Note(D->getLocation(), diag::note_declared_at);
568 if (
T->isPointerOrReferenceType()) {
586 if (!Ptr.isStatic() || !Ptr.isBlockPointer())
588 if (!Ptr.getDeclID())
598 if (!Ptr.block()->isStatic())
600 if (!Ptr.block()->getDeclID())
610 S.
FFDiag(Loc, diag::note_constexpr_null_subobject)
618 if (!Ptr.isElementPastEnd() && !Ptr.isZeroSizeArray())
621 S.
FFDiag(Loc, diag::note_constexpr_past_end_subobject)
628 if (!Ptr.isOnePastEnd())
632 S.
FFDiag(Loc, diag::note_constexpr_past_end_subobject)
638 assert(Ptr.isLive() &&
"Pointer is not live");
642 if (Ptr.isMutable() && !Ptr.isConstInMutable())
645 if (!Ptr.isBlockPointer())
651 if (
V.block() != Ptr.block())
653 if (!
V.getFieldDesc()->IsConst) {
668 bool FoundProblem =
false;
669 for (
PtrView P = Ptr.view(); P !=
V; P = P.getBase()) {
670 if (P.getFieldDesc()->IsConst) {
686 if (!Ptr.getFieldDesc()->IsConst)
689 S.
FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
695 assert(Ptr.isLive() &&
"Pointer is not live");
696 if (!Ptr.isMutable())
712 MutablePtr = MutablePtr.
getBase();
716 S.
FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK << Field;
717 S.
Note(Field->getLocation(), diag::note_declared_at);
723 assert(Ptr.isLive());
725 if (!Ptr.isVolatile())
749 Loc = F->getLocation();
753 Loc = VD->getLocation();
758 Loc = E->getExprLoc();
762 diag::note_constexpr_access_volatile_obj, 1)
763 << AK << DiagKind << ND;
764 S.
Note(Loc, diag::note_constexpr_volatile_here) << DiagKind;
770 assert(Ptr.isLive());
771 assert(!Ptr.isInitialized());
773 Ptr.getLifetime(), AK);
791 VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
794 !(S.
getLangOpts().CPlusPlus23 && VD->getType()->isReferenceType())) {
803 S.
Note(VD->getFirstDecl()->getLocation(), diag::note_declared_at);
808 if (VD->getAnyInitializer()) {
810 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
811 S.
Note(VD->getLocation(), diag::note_declared_at);
829 assert(Ptr.isLive());
830 assert(!Ptr.isInitialized());
832 Ptr.getLifetime(), AK);
849 if (!Ptr.isBlockPointer())
851 return CheckLifetime(S, OpPC, Ptr.getLifetime(), Ptr.block(), AK);
862 S.
Note(VD->getLocation(), diag::note_declared_at);
891 diag::note_constexpr_access_volatile_obj, 1)
904 if (!Desc.IsInitialized)
914 diag::note_constexpr_access_volatile_obj, 1)
938 S.
FFDiag(Loc, diag::note_constexpr_access_null) << AK;
942 if (!Ptr.block()->isAccessible()) {
944 if (Ptr.block()->isDynamic()) {
946 diag::note_constexpr_access_deleted_object)
967 if (!Ptr.isInitialized())
970 if (!
CheckLifetime(S, OpPC, Ptr.getLifetime(), Ptr.block(), AK))
982 if (!Ptr.isArrayRoot()) {
997 if (
const auto *CLE =
998 dyn_cast_if_present<CompoundLiteralExpr>(Desc->
asExpr())) {
999 if (
QualType CLETy = CLE->getType();
1002 diag::note_invalid_subexpr_in_const_expr)
1004 S.
Note(CLE->getExprLoc(), diag::note_declared_at);
1014 if (Ptr.isBlockPointer())
1015 return CheckLoad(S, OpPC, Ptr.view(), AK);
1022 S.
FFDiag(Loc, diag::note_constexpr_access_null) << AK;
1027 if (!Ptr.isReadablePointerType())
1030 assert(Ptr.isStringPointer());
1036 if (!Ptr.isInitialized())
1044 assert(!Ptr.isZero());
1045 if (!Ptr.isReadablePointerType())
1048 if (Ptr.isBlockPointer() && !Ptr.block()->isAccessible()) {
1056 if (Ptr.isPastEnd())
1064 if (!Ptr.isInitialized())
1067 if (Ptr.isBlockPointer()) {
1085 if (Ptr.isOpaquePointer())
1088 if (!Ptr.isBlockPointer())
1091 if (!Ptr.block()->isAccessible()) {
1100 if (!
CheckActive(S, OpPC, Ptr, AK, WillBeActivated))
1116 bool IsCtor,
bool IsDtor) {
1133 if (!Ptr.isBlockPointer())
1152 StringRef Name = DiagDecl->
getName();
1154 Name ==
"__assert_rtn" || Name ==
"__assert_fail" || Name ==
"_wassert";
1157 diag::note_constexpr_assert_failed);
1164 diag::note_invalid_subexpr_in_const_expr);
1170 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
1171 if (CD && CD->isInheritingConstructor()) {
1172 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
1173 if (!Inherited->isConstexpr())
1174 DiagDecl = CD = Inherited;
1179 if (CD && CD->getParent()->isInvalidDecl())
1185 if (CD && CD->isInheritingConstructor()) {
1188 << CD->getInheritedConstructor().getConstructor()->getParent();
1196 if (!IsDefined && !IsExtern && DiagDecl->
isConstexpr() &&
1206 diag::note_constexpr_invalid_function, 1)
1207 << DiagDecl->
isConstexpr() << (bool)CD << DiagDecl;
1223 S.
CCEDiag(Loc, diag::note_constexpr_virtual_call);
1247 diag::note_constexpr_depth_limit_exceeded)
1264 bool IsImplicit =
false;
1265 if (
const auto *TE = dyn_cast<CXXThisExpr>(E))
1266 IsImplicit = TE->isImplicit();
1267 S.
FFDiag(E, diag::note_constexpr_this) << IsImplicit;
1282 if ((Status & APFloat::opInexact) &&
1287 S.
FFDiag(E, diag::note_constexpr_dynamic_rounding);
1291 if ((Status != APFloat::opOK) &&
1294 FPO.getAllowFEnvAccess())) {
1296 S.
FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
1300 if ((Status & APFloat::opStatus::opInvalidOp) &&
1312 APFloat::opStatus Status,
FPOptions FPO) {
1323 S.
CCEDiag(E, diag::note_constexpr_float_arithmetic)
1336 S.
CCEDiag(E, diag::note_constexpr_new);
1343 const Expr *NewExpr) {
1344 if (AllocForm == DeleteForm)
1350 S.
FFDiag(E, diag::note_constexpr_new_delete_mismatch)
1351 <<
static_cast<int>(DeleteForm) <<
static_cast<int>(AllocForm)
1353 S.
Note(NewExpr->
getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
1359 if (Ptr.isBlockPointer() && Ptr.block()->isDynamic())
1364 S.
FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
1387 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
1388 S.
Note(VD->getLocation(), diag::note_declared_at);
1401 const VarDecl *D = Ptr.getRootVarDecl();
1420 const CallExpr *CE,
unsigned ArgSize) {
1423 unsigned Offset = 0;
1425 for (
const Expr *Arg : Args) {
1426 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
1430 S.
CCEDiag(Loc, diag::note_non_null_attribute_failed);
1452 S.
FFDiag(Loc, diag::note_constexpr_double_destroy);
1459 assert(!
Dtor->isTrivial());
1465 return Call(S, OpPC, DtorFunc, 0);
1488 for (
int I =
static_cast<int>(N) - 1; I >= 0; --I) {
1502 return DD->isVirtual();
1507 bool IsGlobalDelete) {
1513 const Expr *Source =
nullptr;
1514 const Block *BlockToDelete =
nullptr;
1524 if (!Ptr.isBlockPointer())
1528 QualType InitialType = Ptr.getType();
1529 Ptr = Ptr.expand().stripBaseCasts();
1531 Source = Ptr.getRootExpr();
1532 BlockToDelete = Ptr.block();
1536 if (std::optional<DynamicAllocator::Form> AllocForm =
1548 if (!DeleteIsArrayForm && Ptr.getType() != InitialType &&
1551 diag::note_constexpr_delete_base_nonvirt_dtor)
1552 << InitialType << Ptr.getType();
1556 if (!Ptr.isRoot() || (Ptr.isOnePastEnd() && !Ptr.isZeroSizeArray()) ||
1557 (Ptr.isArrayElement() && Ptr.getIndex() != 0)) {
1559 S.
FFDiag(Loc, diag::note_constexpr_delete_subobject)
1560 << Ptr.toDiagnosticString(S.
getASTContext()) << Ptr.isOnePastEnd();
1569 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1570 QualType AllocType = Ptr.getType();
1574 return DD->isVirtual() ? DD->getOperatorDelete() :
nullptr;
1584 diag::note_constexpr_new_non_replaceable)
1591 assert(BlockToDelete);
1597 if (!Allocator.
deallocate(Source, BlockToDelete)) {
1600 S.
FFDiag(Loc, diag::note_constexpr_double_delete);
1617 S.
CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1618 << llvm::toString(
Value, 10) <<
Min.getSExtValue() <<
Max.getSExtValue()
1622 S.
CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1623 << llvm::toString(
Value, 10) <<
Min.getZExtValue() <<
Max.getZExtValue()
1654 S.
FFDiag(E, diag::note_constexpr_nonliteral) << E->
getType();
1656 S.
FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
1661 const Pointer &Ptr,
unsigned Offset) {
1662 assert(Ptr.isTypeidPointer());
1664 Ptr.asTypeidPointer().TypeInfoType->getAsRecordDecl());
1667 const Record::Field *Field = R->findField(Offset);
1671 std::string TypeIdStr;
1672 llvm::raw_string_ostream SS(TypeIdStr);
1674 QualType(Ptr.asTypeidPointer().TypePtr, 0)
1677 SS << Field->Decl->getNameAsString();
1680 diag::note_constexpr_access_unreadable_object)
1687 diag::note_constexpr_null_subobject);
1703 if (Ptr.isIntegralPointer()) {
1704 if (std::optional<IntPointer> IntPtr =
1705 Ptr.asIntPointer().atOffset(S.
Ctx,
Off)) {
1712 if (Ptr.isOpaquePointer()) {
1721 const Record::Field *F = R->findField(
Off);
1729 F->Decl->getType().getTypePtr()),
1730 Ptr.getByteOffset());
1735 if (!Ptr.isBlockPointer()) {
1738 if (Ptr.isTypeidPointer())
1744 if (!Ptr.getFieldDesc()->isRecord())
1747 if ((Ptr.getByteOffset() +
Off) >= Ptr.block()->getSize())
1765 uint32_t
Off,
bool NullOK) {
1769 if (Ptr.isOpaquePointer()) {
1777 const Record::Base *B = R->findBase(
Off);
1788 Ptr.getByteOffset());
1792 if (!Ptr.isBlockPointer()) {
1793 if (!Ptr.isIntegralPointer())
1804 if (!Ptr.getFieldDesc()->isRecord()) {
1818 return getBase(S, OpPC, Ptr.narrow(),
Off,
true);
1822 return getBase(S, OpPC, Ptr.narrow(),
Off, NullOK);
1827 const Type *TargetType,
const Type *FinalType) {
1832 if (!Ptr.isBlockPointer()) {
1840 if (!Ptr.getFieldDesc()->isRecord()) {
1848 auto diagFailedCast = [&]() ->
bool {
1849 QualType MostDerivedType = Ptr.getDeclDesc()->getType();
1851 << MostDerivedType <<
QualType(FinalType, 0);
1858 return diagFailedCast();
1861 if (
T->isPointerOrReferenceType())
1862 return T->getPointeeType().getTypePtr();
1863 return T.getTypePtr();
1866 PtrView BasePtr = Ptr.view().getBase();
1867 const Type *BaseTy = unwrapPointerType(BasePtr.
getType());
1869 return diagFailedCast();
1877 assert(
Func->isConstructor());
1879 if (
Func->getParentDecl()->isInvalidDecl())
1895 <<
Func->getParentDecl();
1903 if (
const Decl *D = Ptr.getDeclDesc()->asDecl()) {
1905 S.
FFDiag(ND->getLocation(), diag::note_constexpr_destroy_out_of_lifetime)
1906 << ND->getNameAsString();
1908 S.
FFDiag(Ptr.getDeclDesc()->getLocation(),
1909 diag::note_constexpr_destroy_out_of_lifetime)
1934 if (Ptr.isStringPointer()) {
1936 diag::note_constexpr_access_unreadable_object)
1942 if (Ptr.isOpaquePointer() || Ptr.block()->isStatic()) {
1944 S.
FFDiag(E, diag::note_constexpr_modify_global);
1967 bool SrcIsVoidPtr) {
1971 if (!Ptr.isBlockPointer())
1978 bool HasValidResult = !Ptr.isZero();
1980 if (HasValidResult) {
1990 S.
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
1991 << E->getSubExpr()->getType() << S.
getLangOpts().CPlusPlus26
1992 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
1995 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
1996 << diag::ConstexprInvalidCastKind::CastFrom <<
"'void *'"
2005 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2012 const Type *TargetType) {
2016 bool HasValidResult = !Ptr.isZero();
2018 if (HasValidResult) {
2028 S.
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
2029 << E->getSubExpr()->getType() << S.
getLangOpts().CPlusPlus26
2030 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
2033 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
2034 << diag::ConstexprInvalidCastKind::CastFrom <<
"'void *'"
2039 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
2040 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2045 if (Ptr.isOpaquePointer()) {
2070 uint32_t VarArgSize) {
2071 if (
Func->hasThisPointer()) {
2072 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2082 Func->isLambdaCallOperator())) {
2084 Func->isDestructor()))
2092 if (!
Func->isFullyCompiled())
2111 uint32_t VarArgSize) {
2118 auto cleanup = [&]() ->
bool {
2123 bool InstancePtrTracked =
false;
2124 if (
Func->hasThisPointer()) {
2125 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2142 Func->isLambdaCallOperator()) {
2143 assert(ThisPtr.
isZero());
2146 Func->isDestructor()))
2149 if (
Func->isCopyOrMoveOperator() ||
Func->isCopyOrMoveConstructor()) {
2156 if (!
Func->isConstructor() && !
Func->isDestructor() &&
2166 InstancePtrTracked = (
Func->isConstructor() ||
Func->isDestructor());
2167 if (InstancePtrTracked)
2171 if (!
Func->isFullyCompiled())
2192 if (InstancePtrTracked)
2202 auto diagUnknownDynamicType = [&](
const Pointer &P) ->
bool {
2206 diag::note_constexpr_polymorphic_unknown_dynamic_type)
2211 if (!Ptr.isBlockPointer())
2212 return diagUnknownDynamicType(Ptr);
2218 auto depth = [](
PtrView V) ->
unsigned {
2220 while (!
V.isRoot()) {
2237 assert(depth(TypePtr) >= depth(InitPtr));
2238 unsigned D = depth(TypePtr) - depth(InitPtr);
2239 for (
unsigned I = 0; I != D; ++I)
2247 return diagUnknownDynamicType(
Pointer(TypePtr));
2251 DynamicDecl =
DynamicType->getPointeeCXXRecordDecl();
2259 return DynamicDecl !=
nullptr;
2263struct DynamicCastResult {
2267 bool valid()
const {
return !
Ambiguous && Offset; }
2269 void setOffset(
unsigned O) {
2277 void merge(DynamicCastResult
C) {
2278 Ambiguous |=
C.Ambiguous;
2292 DynamicCastResult Res;
2297 for (
const Record::Base &B : R->bases()) {
2300 N.Offset = *N.Offset + B.Offset;
2308 bool IsReferenceCast) {
2312 if (Ptr.isConstexprUnknown() || Ptr.isOpaquePointer()) {
2317 S.
FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
2322 if (!Ptr.isBlockPointer() || !Ptr.getRecord())
2325 if (!Ptr.isInitialized())
2333 LimitedPtr = Ptr.stripBaseCasts().view();
2336 assert(LimitedPtr.
block() == Ptr.block());
2343 if (TargetType->isVoidType()) {
2348 assert(!TargetType.isNull());
2349 assert(!TargetType->isVoidType());
2350 assert(TargetType->isRecordType());
2357 assert(P.getRecord());
2361 auto baseIsPrivate = [&](
PtrView P) ->
bool {
2362 if (P.isRoot() || !P.isBaseClass())
2366 getRecord(P.getBase())->isDerivedFrom(getRecord(P), Paths);
2371 return llvm::all_of(Paths, [](
const CXXBasePath &P) ->
bool {
2377 DiagPrivateBase = 0,
2380 DiagPrivateSibling = 3
2383 auto diag = [&](
int DiagKind,
QualType ResultType) ->
bool {
2385 if (!IsReferenceCast) {
2391 diag::note_constexpr_dynamic_cast_to_reference_failed)
2392 << DiagKind << ResultType <<
DynamicType << TargetType;
2401 getRecord(LimitedPtr)
2402 ->isDerivedFrom(TargetType->getAsCXXRecordDecl(), Paths);
2403 if (std::distance(Paths.
begin(), Paths.
end()) == 0 &&
2404 !typesMatch(LimitedPtr.
getType(), TargetType)) {
2405 return diag(DiagNoBase, TargetType);
2410 if (baseIsPrivate(Ptr.view()))
2411 return diag(DiagPrivateBase, Ptr.getType());
2413 std::optional<PtrView>
Result;
2415 for (
PtrView Iter = Ptr.view();;) {
2416 if (Iter.isRoot() || !Iter.isBaseClass())
2419 if (typesMatch(TargetType, Iter.getType())) {
2424 Iter = Iter.getBase();
2430 if (baseIsPrivate(*
Result))
2431 return diag(DiagPrivateBase,
Result->getType());
2438 for (
PtrView Iter = LimitedPtr;;) {
2444 Result = Iter.atField(*R.Offset);
2452 if (Iter.isRoot() || !Iter.isBaseClass())
2455 Iter = Iter.getBase();
2459 return diag(DiagAmbiguous, TargetType);
2463 if (baseIsPrivate(*
Result))
2464 return diag(DiagPrivateSibling, TargetType);
2470 return diag(DiagNoBase, TargetType);
2474 uint32_t VarArgSize) {
2476 if (!
Func->hasThisPointer()) {
2477 assert(!
Func->isValid());
2481 assert(
Func->hasThisPointer());
2482 assert(
Func->isVirtual());
2483 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2495 assert(DynamicDecl);
2497 const auto *StaticDecl =
Func->getParentDecl();
2501 if (StaticDecl != DynamicDecl) {
2508 Overrider = InitialFunction;
2518 S.
Note(Callee->getLocation(), diag::note_declared_at);
2522 if (Overrider != InitialFunction) {
2535 if (
Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
2543 if (!
Call(S, OpPC,
Func, VarArgSize))
2548 if (Overrider != InitialFunction &&
2550 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
2558 OverriderPointeeType))
2575 uint32_t BuiltinID) {
2578 if (BuiltinID == Builtin::BI__builtin_operator_new &&
2595 if (!Ptr.isFunctionPointer())
2598 const Function *F = Ptr.asFunctionPointer().Func;
2642 return CallVirt(S, OpPC, F, VarArgSize);
2644 return Call(S, OpPC, F, VarArgSize);
2648 if (
const Record *R = Ptr.getRecord()) {
2649 Ptr.startLifetime();
2651 for (
const Record::Field &Fi : R->fields()) {
2652 PtrView FP = Ptr.atField(Fi.Offset);
2659 if (
const Descriptor *FieldDesc = Ptr.getFieldDesc();
2660 FieldDesc->isCompositeArray()) {
2661 for (
unsigned I = 0; I != FieldDesc->getNumElems(); ++I) {
2662 PtrView EP = Ptr.atIndex(I).narrow();
2669 Ptr.startLifetime();
2677 if (!Ptr.isBlockPointer())
2688 if (!Ptr.isBlockPointer())
2690 Ptr.startLifetime();
2697 if (
const Record *R = Ptr.getRecord()) {
2698 Ptr.setLifeState(L);
2699 for (
const Record::Field &Fi : R->fields())
2704 if (
const Descriptor *FieldDesc = Ptr.getFieldDesc();
2705 FieldDesc->isCompositeArray()) {
2707 if (Ptr.getFieldDesc()->isPrimitiveArray())
2709 for (
unsigned I = 0; I != FieldDesc->getNumElems(); ++I)
2714 Ptr.setLifeState(L);
2748 assert(Ptr.getRecord());
2750 const Record *R = Ptr.getRecord();
2751 for (
const Record::Base &B : R->bases()) {
2752 PtrView BasePtr = Ptr.atField(B.Offset);
2758 for (
const Record::Field &F : R->fields()) {
2759 PtrView FieldPtr = Ptr.atField(F.Offset);
2765 for (
const Record::Base &B : R->virtual_bases()) {
2766 PtrView BasePtr = Ptr.atField(B.Offset);
2776 if (!Ptr.isBlockPointer())
2778 const Record *R = Ptr.getRecord();
2790 diag::note_constexpr_invalid_function, 1)
2795 diag::note_invalid_subexpr_in_const_expr);
2799 Ptr.startLifetime();
2809 std::optional<uint64_t> ArraySize) {
2813 auto directBaseIsUnion = [](
const Pointer &Ptr) ->
bool {
2814 if (Ptr.isArrayElement())
2816 const Record *R = Ptr.getBase().getRecord();
2817 return R && R->isUnion();
2820 if (Ptr.inUnion() && directBaseIsUnion(Ptr))
2831 if (!Ptr.isBlockPointer())
2841 if (!Ptr.block()->isAccessible()) {
2852 for (
PtrView P = Ptr.view();;) {
2872 QualType StorageType = Ptr.getType();
2876 NewExpr->getAllocatedType(),
2877 APInt(64,
static_cast<uint64_t
>(*ArraySize),
false),
nullptr,
2880 AllocType = NewExpr->getAllocatedType();
2883 if (AllocType->
isArrayType() && Ptr.isArrayElement() &&
2884 Ptr.expand().getIndex() == 0) {
2892 StorageType = Ptr.expand().getArray().getType();
2899 diag::note_constexpr_placement_new_wrong_type)
2900 << StorageType << AllocType;
2905 if (Ptr.inUnion() && !Ptr.isActive() && !directBaseIsUnion(Ptr))
2915 if (
const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
2916 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
2920 bool IsNothrowForm = NewExpr->getNumPlacementArgs() == 1 &&
2922 if (NewExpr->getNumPlacementArgs() > 0 && !IsNothrowForm) {
2923 S.
FFDiag(Loc, diag::note_constexpr_new_placement)
2929 !OperatorNew->isUsableAsGlobalAllocationFunctionInConstantEvaluation());
2930 S.
FFDiag(Loc, diag::note_constexpr_new_non_replaceable)
2936 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
2937 assert(!OperatorDelete
2938 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation());
2939 S.
FFDiag(Loc, diag::note_constexpr_new_non_replaceable)
2961 E->
getExprLoc(), diag::warn_fixedpoint_constant_overflow)
2964 S.
CCEDiag(E, diag::note_constexpr_overflow)
2972 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
2978 const Pointer &Ptr,
unsigned BitWidth) {
2981 S.
CCEDiag(E, diag::note_constexpr_invalid_cast_ptrtoint)
2982 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2984 if (Ptr.isBlockPointer() && !Ptr.isZero())
2986 if (Ptr.isIntegralPointer())
2989 if (Ptr.isOpaquePointer()) {
2992 return Ptr.isRoot();
2995 if (!Ptr.isZero()) {
3015 Result.copy(
APInt(BitWidth, Ptr.getIntegerRepresentation()));
3028 Result.copy(
APInt(BitWidth, Ptr.getIntegerRepresentation()));
3035 bool TargetIsUCharOrByte) {
3037 if (!HasIndeterminateBits)
3041 if (TargetIsUCharOrByte)
3046 S.
FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
3058 if (!ID.IsInitialized) {
3061 diag::note_constexpr_use_uninit_reference);
3078 if (!P.isBlockPointer() && !P.isOpaquePointer())
3081 if (P.isConstexprUnknown()) {
3086 S.
FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
3093 if (P.isBlockPointer())
3094 T = P.stripBaseCasts().getType()->getCanonicalTypeUnqualified();
3096 T = P.getType()->getCanonicalTypeUnqualified();
3103 Func && (
Func->isConstructor() ||
Func->isDestructor()) &&
3104 P.block() ==
Frame->getThis().block()) {
3106 Func->getParentDecl());
3118 S.
CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
3119 << E->getExprOperand()->getType()
3120 << E->getExprOperand()->getSourceRange();
3134 StringRef LHSStr(LHSLit->getBytes());
3135 unsigned LHSLength = LHSStr.size();
3136 StringRef RHSStr(RHSLit->getBytes());
3137 unsigned RHSLength = RHSStr.size();
3139 int32_t IndexDiff = RHSOffset - LHSOffset;
3140 if (IndexDiff < 0) {
3141 if (
static_cast<int32_t
>(LHSLength) < -IndexDiff)
3143 LHSStr = LHSStr.drop_front(-IndexDiff);
3145 if (
static_cast<int32_t
>(RHSLength) < IndexDiff)
3147 RHSStr = RHSStr.drop_front(IndexDiff);
3150 unsigned ShorterCharWidth;
3153 if (LHSLength < RHSLength) {
3154 ShorterCharWidth = LHSLit->getCharByteWidth();
3158 ShorterCharWidth = RHSLit->getCharByteWidth();
3166 for (
unsigned NullByte : llvm::seq(ShorterCharWidth)) {
3167 if (Shorter.size() + NullByte >= Longer.size())
3169 if (Longer[Shorter.size() + NullByte])
3172 return Shorter == Longer.take_front(Shorter.size());
3178 if (!Val.singleWord()) {
3179 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
3180 Val.take(NewMemory);
3184 if (!Val.singleWord()) {
3185 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
3186 Val.take(NewMemory);
3190 if (!Val.singleWord()) {
3191 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
3192 Val.take(NewMemory);
3198 std::copy_n(Val.path(), PathLength, NewPath);
3199 Val.takePath(NewPath);
3201 auto &Val = Ptr.deref<
Pointer>();
3202 if (Val.isOpaquePointer() && Val.asOpaquePointer().PathLength != 0) {
3209 Val.getByteOffset());
3214template <
typename T>
3217 if constexpr (std::is_same_v<T, MemberPointer>) {
3221 std::copy_n(Val.path(), PathLength, NewPath);
3222 Val.takePath(NewPath);
3223 }
else if constexpr (std::is_same_v<T, Pointer>) {
3224 auto &Val = Ptr.deref<
Pointer>();
3225 if (Val.isOpaquePointer() && Val.asOpaquePointer().PathLength != 0) {
3232 Val.getByteOffset());
3235 auto &Val = Ptr.deref<
T>();
3236 if (!Val.singleWord()) {
3237 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
3238 Val.take(NewMemory);
3244 if (
const Record *R = Ptr.getRecord()) {
3245 for (
const Record::Field &Fi : R->fields()) {
3246 if (Fi.Desc->isPrimitive()) {
3248 copyPrimitiveMemory<T>(S, Ptr.atField(Fi.Offset));
3257 if (
const Descriptor *D = Ptr.getFieldDesc(); D && D->isArray()) {
3258 unsigned NumElems = D->getNumElems();
3262 if (D->isPrimitiveArray()) {
3266 assert(NumElems >= 1);
3268 bool AllSingleWord =
true;
3270 if (!EP.
deref<
T>().singleWord()) {
3272 AllSingleWord =
false;
3277 for (
unsigned I = 1; I != D->getNumElems(); ++I) {
3282 assert(D->isCompositeArray());
3283 for (
unsigned I = 0; I != D->getNumElems(); ++I) {
3284 PtrView EP = Ptr.atIndex(I).narrow();
3293 if (!Ptr.isBlockPointer())
3297 if (Ptr.canBeInitialized()) {
3310 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3311 << diag::ConstexprInvalidCastKind::Reinterpret
3320 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3321 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3327 const auto *CE = dyn_cast<CastExpr>(E);
3329 S.
FFDiag(E, diag::note_constexpr_access_volatile_type)
3330 <<
AK_Read << CE->getSubExpr()->getType();
3338 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3339 << diag::ConstexprInvalidCastKind::Dynamic;
3342 llvm_unreachable(
"Unhandled CastKind");
3374 if (!MemberPtr.getDecl()) {
3380 if (MemberPtr.getPathLength() >= 2)
3381 Expected = MemberPtr.getPathEntry(MemberPtr.getPathLength() - 2);
3383 Expected = MemberPtr.getRecordDecl();
3396 unsigned OldPathLength = MemberPtr.getPathLength();
3397 unsigned NewPathLength = OldPathLength - 1;
3398 bool IsDerivedMember = NewPathLength != 0;
3400 std::copy_n(MemberPtr.path(), NewPathLength, NewPath);
3403 NewPath, IsDerivedMember));
3411 bool IsDerivedMember) {
3412 unsigned OldPathLength = MemberPtr.getPathLength();
3413 unsigned NewPathLength = OldPathLength + 1;
3416 std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
3420 NewPath, IsDerivedMember));
3429 if (!Ptr.isDerivedMember() && Ptr.hasPath())
3432 bool IsDerivedMember = Ptr.isDerivedMember() || !Ptr.hasPath();
3441 if (!Ptr.isDerivedMember()) {
3458 if (!MP.isBaseCastPossible())
3469 const auto *FD = dyn_cast_if_present<FunctionDecl>(D);
3473 const auto *
Method = dyn_cast<CXXMethodDecl>(FD);
3480 if (!
Base.getRecord() ||
Base.getRecord()->getDecl() != MethodParent)
3497 unsigned NewPathLength = OldPathLength + 1;
3500 std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
3504 MemberPtr.withPath(NewPathLength, NewPath, IsDerived));
3508template <
bool Signed>
3510 uint32_t BitWidth, uint32_t FPOI) {
3515 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite() &&
3542 APSInt &&Index,
bool AllowReplace) {
3551 ElemType = AT->getElementType();
3556 unsigned IndexBits = std::max(Index.getBitWidth(), 32u) + 1;
3558 Index.extend(IndexBits) +
3559 APSInt(
APInt(IndexBits, Ptr.getIndex()), Index.isUnsigned());
3561 if (NewIndex > Ptr.getNumElems() || NewIndex.isNegative())
3565 if (NewIndex.getActiveBits() > 64)
3568 unsigned NewPathLength;
3579 if (Index.isNonNegative())
3588 Ptr.getByteOffset());
3591 unsigned IndexBits = std::max(Index.getBitWidth(), 64u) + 1;
3592 size_t CurrentIndex = Ptr.getByteOffset();
3594 Index.extend(IndexBits) +
3595 APSInt(
APInt(IndexBits, CurrentIndex), Index.isUnsigned());
3596 if (NewOffset > 1 || NewOffset.isNegative())
3599 if (NewOffset.getActiveBits() > 64)
3602 size_t NewByteOffset = CurrentIndex + Index.getZExtValue();
3603 bool PastEnd = NewByteOffset != 0;
3613 assert(Ptr.isOpaquePointer());
3614 if (Offset.isZero())
3620 unsigned NumElems = 1;
3625 NumElems = CAT->getZExtSize();
3632 S.
FFDiag(E, diag::note_constexpr_unsized_array_indexed);
3633 return std::nullopt;
3638 return std::nullopt;
3644 NewIndex = Ptr.getIndex() + (Offset.extend(Offset.getBitWidth() + 2));
3647 (Ptr.getByteOffset()) + (Offset.extend(Offset.getBitWidth() + 2));
3651 NewIndex = Ptr.getIndex() - (Offset.extend(Offset.getBitWidth() + 2));
3654 (Ptr.getByteOffset()) - (Offset.extend(Offset.getBitWidth() + 2));
3658 if (NewIndex > NumElems || NewIndex < 0)
3661 if (NewIndex.getActiveBits() > 64)
3662 return std::nullopt;
3670 NewPath[NewPathLength - 1].
Index += Offset.getZExtValue();
3672 NewPath[NewPathLength - 1].
Index -= Offset.getZExtValue();
3681 if (Ptr.isOpaquePointer()) {
3695 Ptr.getByteOffset());
3699 if (!Ptr.isBlockPointer())
3701 if (!Ptr.getFieldDesc()->isRecord())
3704 const Record::Base *VirtBase =
Base.getRecord()->findVirtualBase(
Decl);
3717 if (!Dest.isBlockPointer())
3727 return DoMemcpy(S, OpPC, Src, Dest);
3737 if (!Dest.isBlockPointer() || Dest.isDummy() || Dest.isConstexprUnknown())
3771 return Op == OP_RetVoid || Op == OP_RetValue || Op == OP_NoRet ||
3772 Op == OP_RetSint8 || Op == OP_RetUint8 || Op == OP_RetSint16 ||
3773 Op == OP_RetUint16 || Op == OP_RetSint32 || Op == OP_RetUint32 ||
3774 Op == OP_RetSint64 || Op == OP_RetUint64 || Op == OP_RetIntAP ||
3775 Op == OP_RetIntAPS || Op == OP_RetBool || Op == OP_RetFixedPoint ||
3776 Op == OP_RetPtr || Op == OP_RetMemberPtr || Op == OP_RetFloat ||
3777 Op == OP_RetReflect || Op == OP_EndSpeculation;
3786#define GET_INTERPFN_DISPATCHERS
3787#include "Opcodes.inc"
3788#undef GET_INTERPFN_DISPATCHERS
3793#define GET_INTERPFN_LIST
3794#include "Opcodes.inc"
3795#undef GET_INTERPFN_LIST
3813 return InterpNext(S);
3841 [[maybe_unused]]
CodePtr PCBefore = S.
PC;
3842 size_t StackSizeBefore = S.
Stk.
size();
3848 assert(DepthBefore >= 1);
3851 auto SpeculativeInterp = [&S]() ->
bool {
3874 if (SpeculativeInterp()) {
3879 assert(S.
Stk.
size() == StackSizeBefore);
3885 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 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.
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.
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 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 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 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 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)
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 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.
const bool IsConst
Flag indicating if the block is mutable.
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 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