13#ifndef LLVM_CLANG_AST_INTERP_INTERP_H
14#define LLVM_CLANG_AST_INTERP_INTERP_H
34#include "llvm/ADT/APFloat.h"
35#include "llvm/ADT/APSInt.h"
41using APSInt = llvm::APSInt;
79 bool WillBeActivated =
false);
105 uint32_t VarArgSize);
107 uint32_t VarArgSize);
109 uint32_t VarArgSize);
117 bool TargetIsUCharOrByte);
130template <ShiftDir Dir,
typename LT,
typename RT>
133 if (RHS.isNegative()) {
135 S.
CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
144 const APSInt Val = RHS.toAPSInt();
146 S.
CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty <<
Bits;
152 if (LHS.isSigned() && !S.
getLangOpts().CPlusPlus20) {
155 if (LHS.isNegative()) {
157 S.
CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
160 }
else if (LHS.toUnsigned().countLeadingZeros() <
161 static_cast<unsigned>(RHS)) {
163 S.
CCEDiag(E, diag::note_constexpr_lshift_discards);
181 if constexpr (std::is_same_v<T, Floating>) {
182 S.
CCEDiag(Op, diag::note_expr_divide_by_zero)
183 << Op->getRHS()->getSourceRange();
187 S.
FFDiag(Op, diag::note_expr_divide_by_zero)
188 << Op->getRHS()->getSourceRange();
192 if constexpr (!std::is_same_v<T, FixedPoint>) {
193 if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) {
194 APSInt LHSInt = LHS.toAPSInt();
196 (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10);
199 S.
CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->
getType();
209 APFloat::opStatus Status,
FPOptions FPO);
223template <PrimType Name, class T = typename PrimConv<Name>::T>
268 template <typename U>
class OpAP>
284 if constexpr (std::is_same_v<T, FixedPoint>)
296 .toString(Trunc, 10,
Result.isSigned(),
false,
309template <PrimType Name, class T = typename PrimConv<Name>::T>
313 const unsigned Bits = RHS.bitWidth() + 1;
329template <PrimType Name, class T = typename PrimConv<Name>::T>
333 const unsigned Bits = RHS.bitWidth() + 1;
349template <PrimType Name, class T = typename PrimConv<Name>::T>
353 const unsigned Bits = RHS.bitWidth() * 2;
371template <PrimType Name, class T = typename PrimConv<Name>::T>
377 if constexpr (std::is_same_v<T, Floating>) {
383 APFloat ResR(A.getSemantics());
384 APFloat ResI(A.getSemantics());
395 Result.initializeAllElements();
398 const T &LHSR = LHS.elem<
T>(0);
399 const T &LHSI = LHS.elem<
T>(1);
400 const T &RHSR = RHS.
elem<
T>(0);
401 const T &RHSI = RHS.
elem<
T>(1);
402 unsigned Bits = LHSR.bitWidth();
406 if (T::mul(LHSR, RHSR,
Bits, &A))
409 if (T::mul(LHSI, RHSI,
Bits, &B))
415 if (T::mul(LHSR, RHSI,
Bits, &A))
417 if (T::mul(LHSI, RHSR,
Bits, &B))
422 Result.initializeAllElements();
428template <PrimType Name, class T = typename PrimConv<Name>::T>
434 if constexpr (std::is_same_v<T, Floating>) {
440 APFloat ResR(A.getSemantics());
441 APFloat ResI(A.getSemantics());
453 Result.initializeAllElements();
456 const T &LHSR = LHS.elem<
T>(0);
457 const T &LHSI = LHS.elem<
T>(1);
458 const T &RHSR = RHS.
elem<
T>(0);
459 const T &RHSI = RHS.
elem<
T>(1);
460 unsigned Bits = LHSR.bitWidth();
466 S.
FFDiag(E, diag::note_expr_divide_by_zero);
472 if (T::mul(RHSR, RHSR,
Bits, &A) || T::mul(RHSI, RHSI,
Bits, &B)) {
476 if (T::add(A, B,
Bits, &Den))
481 S.
FFDiag(E, diag::note_expr_divide_by_zero);
489 if (T::mul(LHSR, RHSR,
Bits, &A) || T::mul(LHSI, RHSI,
Bits, &B))
491 if (T::add(A, B,
Bits, &ResultR))
493 if (T::div(ResultR, Den,
Bits, &ResultR))
497 if (T::mul(LHSI, RHSR,
Bits, &A) || T::mul(LHSR, RHSI,
Bits, &B))
499 if (T::sub(A, B,
Bits, &ResultI))
501 if (T::div(ResultI, Den,
Bits, &ResultI))
503 Result.initializeAllElements();
512template <PrimType Name, class T = typename PrimConv<Name>::T>
516 unsigned Bits = RHS.bitWidth();
532template <PrimType Name, class T = typename PrimConv<Name>::T>
536 unsigned Bits = RHS.bitWidth();
552template <PrimType Name, class T = typename PrimConv<Name>::T>
557 unsigned Bits = RHS.bitWidth();
573template <PrimType Name, class T = typename PrimConv<Name>::T>
577 const unsigned Bits = RHS.bitWidth() * 2;
596template <PrimType Name, class T = typename PrimConv<Name>::T>
600 const unsigned Bits = RHS.bitWidth() * 2;
614 if constexpr (std::is_same_v<T, FixedPoint>) {
653template <PrimType Name, class T = typename PrimConv<Name>::T>
657 if constexpr (std::is_same_v<T, Floating>) {
676 "don't expect other types to fail at constexpr negation");
684 NegatedValue.trunc(
Result.bitWidth())
685 .toString(Trunc, 10,
Result.isSigned(),
false,
705template <
typename T, IncDecOp Op, PushVal DoPush>
715 if constexpr (std::is_same_v<T, Boolean>) {
729 if (!T::increment(
Value, &
Result) || !CanOverflow) {
737 if (!T::decrement(
Value, &
Result) || !CanOverflow) {
761 APResult.trunc(
Result.bitWidth())
762 .toString(Trunc, 10,
Result.isSigned(),
false,
775template <PrimType Name, class T = typename PrimConv<Name>::T>
785template <PrimType Name, class T = typename PrimConv<Name>::T>
799template <PrimType Name, class T = typename PrimConv<Name>::T>
808template <PrimType Name, class T = typename PrimConv<Name>::T>
819template <PrimType Name, class T = typename PrimConv<Name>::T>
828template <PrimType Name, class T = typename PrimConv<Name>::T>
843template <PrimType Name, class T = typename PrimConv<Name>::T>
852template <PrimType Name, class T = typename PrimConv<Name>::T>
866template <PrimType Name, class T = typename PrimConv<Name>::T>
875template <PrimType Name, class T = typename PrimConv<Name>::T>
886template <PrimType Name, class T = typename PrimConv<Name>::T>
894template <PrimType Name, class T = typename PrimConv<Name>::T>
904template <IncDecOp Op, PushVal DoPush>
914 llvm::APFloat::opStatus Status;
959template <PrimType Name, class T = typename PrimConv<Name>::T>
967 if (!T::comp(Val, &
Result)) {
982 assert((!std::is_same_v<T, MemberPointer>) &&
983 "Non-equality comparisons on member pointer types should already be "
984 "rejected in Sema.");
988 S.
Stk.
push<BoolT>(BoolT::from(
Fn(LHS.compare(RHS))));
1007 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1015 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1022 if (std::optional<std::pair<Pointer, Pointer>> Split =
1024 const FieldDecl *LF = Split->first.getField();
1025 const FieldDecl *RF = Split->second.getField();
1029 diag::note_constexpr_pointer_comparison_differing_access)
1042 return (
Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
1043 Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
1044 Builtin == Builtin::BI__builtin_ptrauth_sign_constant ||
1045 Builtin == Builtin::BI__builtin_function_start);
1057 if (LHS.isZero() && RHS.
isZero()) {
1063 for (
const auto &P : {LHS, RHS}) {
1068 S.
FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison)
1090 S.
FFDiag(Loc, diag::note_constexpr_literal_comparison)
1098 size_t A = LHS.computeOffsetForComparison();
1108 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
1112 if (RHS.
isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() &&
1113 LHS.getOffset() == 0) {
1115 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
1122 for (
const auto &P : {LHS, RHS}) {
1125 if (BothNonNull && P.pointsToLiteral()) {
1126 const Expr *E = P.getDeclDesc()->asExpr();
1129 S.
FFDiag(Loc, diag::note_constexpr_literal_comparison);
1132 if (
const auto *CE = dyn_cast<CallExpr>(E);
1135 S.
FFDiag(Loc, diag::note_constexpr_opaque_call_comparison)
1139 }
else if (BothNonNull && P.isIntegralPointer()) {
1141 S.
FFDiag(Loc, diag::note_constexpr_pointer_constant_comparison)
1150 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_zero_sized)
1168 for (
const auto &MP : {LHS, RHS}) {
1171 S.
FFDiag(Loc, diag::note_constexpr_mem_pointer_weak_comparison)
1172 << MP.getMemberFunction();
1180 if (LHS.
isZero() && RHS.isZero()) {
1184 if (LHS.
isZero() || RHS.isZero()) {
1190 for (
const auto &MP : {LHS, RHS}) {
1194 S.
CCEDiag(Loc, diag::note_constexpr_compare_virtual_mem_ptr) << MD;
1202template <PrimType Name, class T = typename PrimConv<Name>::T>
1209template <PrimType Name, class T = typename PrimConv<Name>::T>
1216 if constexpr (std::is_same_v<T, Pointer>) {
1219 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1227 const auto *CmpValueInfo =
1229 assert(CmpValueInfo);
1230 assert(CmpValueInfo->hasValidIntValue());
1234template <PrimType Name, class T = typename PrimConv<Name>::T>
1241template <PrimType Name, class T = typename PrimConv<Name>::T>
1248template <PrimType Name, class T = typename PrimConv<Name>::T>
1256template <PrimType Name, class T = typename PrimConv<Name>::T>
1263template <PrimType Name, class T = typename PrimConv<Name>::T>
1275template <PrimType Name, class T = typename PrimConv<Name>::T>
1281template <PrimType Name, class T = typename PrimConv<Name>::T>
1288template <PrimType TopName, PrimType BottomName>
1293 const auto &Top = S.
Stk.
pop<TopT>();
1294 const auto &Bottom = S.
Stk.
pop<BottomT>();
1306template <PrimType Name, class T = typename PrimConv<Name>::T>
1310 Result.copy(Arg.toAPSInt());
1329template <PrimType Name, class T = typename PrimConv<Name>::T>
1345template <PrimType Name, class T = typename PrimConv<Name>::T>
1351template <PrimType Name, class T = typename PrimConv<Name>::T>
1360template <PrimType Name, class T = typename PrimConv<Name>::T>
1368template <PrimType Name, class T = typename PrimConv<Name>::T>
1382template <PrimType Name, class T = typename PrimConv<Name>::T>
1394 Field.deref<
T>() =
Value;
1400template <PrimType Name, class T = typename PrimConv<Name>::T>
1414template <PrimType Name, class T = typename PrimConv<Name>::T>
1428template <PrimType Name, class T = typename PrimConv<Name>::T>
1439 Field.deref<
T>() =
Value;
1443template <PrimType Name, class T = typename PrimConv<Name>::T>
1455template <PrimType Name, class T = typename PrimConv<Name>::T>
1468template <PrimType Name, class T = typename PrimConv<Name>::T>
1474template <PrimType Name, class T = typename PrimConv<Name>::T>
1480 if constexpr (std::is_same_v<T, Floating>) {
1482 if (!Val.singleWord()) {
1483 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
1484 Val.take(NewMemory);
1488 auto &Val = P.
deref<
T>();
1489 if (!Val.singleWord()) {
1490 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
1491 Val.take(NewMemory);
1502template <PrimType Name, class T = typename PrimConv<Name>::T>
1534template <PrimType Name, class T = typename PrimConv<Name>::T>
1542 assert(Field.canBeInitialized());
1548template <PrimType Name, class T = typename PrimConv<Name>::T>
1556 assert(Field.canBeInitialized());
1565template <PrimType Name, class T = typename PrimConv<Name>::T>
1567 uint32_t FieldOffset) {
1568 assert(F->isBitField());
1575 assert(Field.canBeInitialized());
1577 Field.deref<
T>() =
Value.truncate(F->Decl->getBitWidthValue());
1582template <PrimType Name, class T = typename PrimConv<Name>::T>
1584 const Record::Field *F, uint32_t FieldOffset) {
1585 assert(F->isBitField());
1592 assert(Field.canBeInitialized());
1594 Field.deref<
T>() =
Value.truncate(F->Decl->getBitWidthValue());
1603template <PrimType Name, class T = typename PrimConv<Name>::T>
1618template <PrimType Name, class T = typename PrimConv<Name>::T>
1634template <PrimType Name, class T = typename PrimConv<Name>::T>
1636 assert(F->isBitField());
1650 .trunc(F->Decl->getBitWidthValue())
1651 .sextOrTrunc(
Value.bitWidth()));
1654 .trunc(F->Decl->getBitWidthValue())
1655 .zextOrTrunc(
Value.bitWidth()));
1659 Field.deref<
T>() =
Value.truncate(F->Decl->getBitWidthValue());
1665template <PrimType Name, class T = typename PrimConv<Name>::T>
1667 const Record::Field *F) {
1668 assert(F->isBitField());
1682 .trunc(F->Decl->getBitWidthValue())
1683 .sextOrTrunc(
Value.bitWidth()));
1686 .trunc(F->Decl->getBitWidthValue())
1687 .zextOrTrunc(
Value.bitWidth()));
1691 Field.deref<
T>() =
Value.truncate(F->Decl->getBitWidthValue());
1721bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off);
1735 bool NullOK,
const Type *TargetType) {
1754 assert(TargetRecord);
1760 << MostDerivedType <<
QualType(TargetType, 0);
1871 diag::note_constexpr_dereferencing_null);
1880 while (
Base.isBaseClass())
1883 const Record::Base *VirtBase =
Base.getRecord()->getVirtualBase(
Decl);
1912template <PrimType Name, class T = typename PrimConv<Name>::T>
1920 !(D->isPrimitive() || D->isPrimitiveArray()) || D->
getPrimType() != Name)
1926template <PrimType Name, class T = typename PrimConv<Name>::T>
1934 !(D->isPrimitive() || D->isPrimitiveArray()) || D->
getPrimType() != Name)
1940template <PrimType Name, class T = typename PrimConv<Name>::T>
1946 if (Ptr.canBeInitialized())
1952template <PrimType Name, class T = typename PrimConv<Name>::T>
1958 if (Ptr.canBeInitialized())
1983template <PrimType Name, class T = typename PrimConv<Name>::T>
1990 if (Ptr.canBeInitialized()) {
1998template <PrimType Name, class T = typename PrimConv<Name>::T>
2005 if (Ptr.canBeInitialized()) {
2013template <PrimType Name, class T = typename PrimConv<Name>::T>
2020 if (Ptr.canBeInitialized())
2022 if (
const auto *FD = Ptr.getField())
2023 Ptr.deref<
T>() =
Value.truncate(FD->getBitWidthValue());
2029template <PrimType Name, class T = typename PrimConv<Name>::T>
2035 if (Ptr.canBeInitialized())
2037 if (
const auto *FD = Ptr.getField())
2038 Ptr.deref<
T>() =
Value.truncate(FD->getBitWidthValue());
2044template <PrimType Name, class T = typename PrimConv<Name>::T>
2051 if (Ptr.canBeInitialized()) {
2055 if (
const auto *FD = Ptr.getField())
2056 Ptr.
deref<
T>() =
Value.truncate(FD->getBitWidthValue());
2062template <PrimType Name, class T = typename PrimConv<Name>::T>
2069 if (Ptr.canBeInitialized()) {
2073 if (
const auto *FD = Ptr.getField())
2074 Ptr.
deref<
T>() =
Value.truncate(FD->getBitWidthValue());
2080template <PrimType Name, class T = typename PrimConv<Name>::T>
2087 new (&Ptr.deref<
T>())
T(
Value);
2091template <PrimType Name, class T = typename PrimConv<Name>::T>
2098 new (&Ptr.deref<
T>())
T(
Value);
2105template <PrimType Name, class T = typename PrimConv<Name>::T>
2111 if (Desc->isUnknownSizeArray())
2116 if (Idx == 0 && !Desc->isArray()) {
2118 new (&Ptr.deref<
T>())
T(
Value);
2124 if (Idx >= Desc->getNumElems()) {
2128 S.
FFDiag(Loc, diag::note_constexpr_access_past_end)
2133 Ptr.initializeElement(Idx);
2134 new (&Ptr.elem<
T>(Idx))
T(
Value);
2139template <PrimType Name, class T = typename PrimConv<Name>::T>
2145 if (Desc->isUnknownSizeArray())
2150 if (Idx == 0 && !Desc->isArray()) {
2152 new (&Ptr.deref<
T>())
T(
Value);
2158 if (Idx >= Desc->getNumElems()) {
2162 S.
FFDiag(Loc, diag::note_constexpr_access_past_end)
2167 Ptr.initializeElement(Idx);
2168 new (&Ptr.elem<
T>(Idx))
T(
Value);
2179 return DoMemcpy(S, OpPC, Src, Dest);
2193 if (std::optional<Pointer> Ptr = MP.toPointer(S.
Ctx)) {
2204template <
class T, ArithOp Op>
2206 const T &Offset,
const Pointer &Ptr,
2207 bool IsPointerArith =
false) {
2209 if (Offset.isZero())
2216 return std::nullopt;
2221 return std::nullopt;
2226 uint64_t O =
static_cast<uint64_t
>(Offset) * Ptr.
elemSize();
2232 uint64_t O =
static_cast<uint64_t
>(Offset);
2244 return std::nullopt;
2249 uint64_t MaxIndex =
static_cast<uint64_t
>(Ptr.
getNumElems());
2258 auto DiagInvalidOffset = [&]() ->
void {
2259 const unsigned Bits = Offset.bitWidth();
2260 APSInt APOffset(Offset.toAPSInt().extend(
Bits + 2),
false);
2264 (Op ==
ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
2266 << NewIndex <<
static_cast<int>(!Ptr.
inArray()) << MaxIndex;
2271 uint64_t IOffset =
static_cast<uint64_t
>(Offset);
2272 uint64_t MaxOffset = MaxIndex - Index;
2276 if (Offset.isNegative() && (Offset.isMin() || -IOffset > Index))
2277 DiagInvalidOffset();
2280 if (Offset.isPositive() && IOffset > MaxOffset)
2281 DiagInvalidOffset();
2284 if (Offset.isPositive() && Index < IOffset)
2285 DiagInvalidOffset();
2288 if (Offset.isNegative() && (Offset.isMin() || -IOffset > MaxOffset))
2289 DiagInvalidOffset();
2294 return std::nullopt;
2297 int64_t WideIndex =
static_cast<int64_t
>(Index);
2298 int64_t WideOffset =
static_cast<int64_t
>(Offset);
2301 Result = WideIndex + WideOffset;
2303 Result = WideIndex - WideOffset;
2317template <PrimType Name, class T = typename PrimConv<Name>::T>
2323 S, OpPC, Offset, Ptr,
true)) {
2330template <PrimType Name, class T = typename PrimConv<Name>::T>
2336 S, OpPC, Offset, Ptr,
true)) {
2343template <ArithOp Op>
2359 OneT One = OneT::from(1);
2360 if (std::optional<Pointer>
Result =
2390template <PrimType Name, class T = typename PrimConv<Name>::T>
2397 diag::note_constexpr_pointer_arith_unspecified)
2403 if (ElemSizeIsZero) {
2405 while (
auto *AT = dyn_cast<ArrayType>(PtrT))
2406 PtrT = AT->getElementType();
2411 diag::note_constexpr_pointer_subtraction_zero_size)
2432 int64_t R64 = A64 - B64;
2433 if (
static_cast<int64_t
>(T::from(R64)) != R64)
2456 S.
FFDiag(ND->getLocation(),
2457 diag::note_constexpr_destroy_out_of_lifetime)
2458 << ND->getNameAsString();
2461 diag::note_constexpr_destroy_out_of_lifetime)
2491 llvm::RoundingMode RM) {
2501 FixedPointSemantics::getFromOpaqueInt(FPS);
2516template <PrimType Name, class T = typename PrimConv<Name>::T>
2521 APInt Source = S.
Stk.
pop<
T>().toAPSInt().extOrTrunc(BitWidth);
2528template <PrimType Name, class T = typename PrimConv<Name>::T>
2533 APInt Source = S.
Stk.
pop<
T>().toAPSInt().extOrTrunc(BitWidth);
2540template <PrimType Name, class T = typename PrimConv<Name>::T>
2542 const llvm::fltSemantics *Sem, uint32_t FPOI) {
2544 APSInt FromAP = From.toAPSInt();
2555template <PrimType Name, class T = typename PrimConv<Name>::T>
2559 if constexpr (std::is_same_v<T, Boolean>) {
2568 if ((Status & APFloat::opStatus::opInvalidOp)) {
2587 uint32_t BitWidth, uint32_t FPOI) {
2594 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite())
2608 uint32_t BitWidth, uint32_t FPOI) {
2615 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite())
2629 const Pointer &Ptr,
unsigned BitWidth);
2633template <PrimType Name, class T = typename PrimConv<Name>::T>
2638 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2648template <PrimType Name, class T = typename PrimConv<Name>::T>
2682 const llvm::fltSemantics *Sem) {
2685 Result.copy(Fixed.toFloat(Sem));
2690template <PrimType Name, class T = typename PrimConv<Name>::T>
2695 APSInt Int = Fixed.toInt(T::bitWidth(), T::isSigned(), &Overflow);
2706 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
2707 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2716 bool HasValidResult = !Ptr.isZero();
2718 if (HasValidResult) {
2725 E->getType()->getPointeeType()))
2728 S.
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
2729 << E->getSubExpr()->getType() << S.
getLangOpts().CPlusPlus26
2730 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
2733 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
2734 << diag::ConstexprInvalidCastKind::CastFrom <<
"'void *'"
2739 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
2740 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2751template <PrimType Name, class T = typename PrimConv<Name>::T>
2759 if (!
Result.singleWord())
2760 std::memset(
Result.Memory, 0,
Result.numWords() *
sizeof(uint64_t));
2767 if (!
Result.singleWord())
2768 std::memset(
Result.Memory, 0,
Result.numWords() *
sizeof(uint64_t));
2773template <PrimType Name, class T = typename PrimConv<Name>::T>
2782template <PrimType Name, class T = typename PrimConv<Name>::T>
2784 const auto &P = S.
Stk.
pop<
T>();
2804 if (!
This.isDummy()) {
2806 if (!
This.isTypeidPointer()) {
2807 [[maybe_unused]]
const Record *R =
This.getRecord();
2809 R =
This.narrow().getRecord();
2833template <
class LT,
class RT, ShiftDir Dir>
2837 const unsigned Bits = LHS.bitWidth();
2841 RT::bitAnd(RHS, RT::from(LHS.bitWidth() - 1, RHS.bitWidth()),
2842 RHS.bitWidth(), &RHS);
2844 if (RHS.isNegative()) {
2848 S.
CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
2854 S, OpPC, LHS, RHS,
Result);
2866 typename LT::AsUnsigned R;
2867 unsigned MaxShiftAmount = LHS.bitWidth() - 1;
2869 if (
Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
2871 if (LHS.isNegative())
2872 R = LT::AsUnsigned::zero(LHS.bitWidth());
2874 RHS = RT::from(LHS.countLeadingZeros(), RHS.bitWidth());
2875 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
2876 LT::AsUnsigned::from(RHS,
Bits),
Bits, &R);
2878 }
else if (LHS.isNegative()) {
2880 R = LT::AsUnsigned::zero(LHS.bitWidth());
2883 typename LT::AsUnsigned LHSU = LT::AsUnsigned::from(-LHS);
2884 LT::AsUnsigned::shiftLeft(LHSU, LT::AsUnsigned::from(RHS,
Bits),
Bits,
2890 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
2891 LT::AsUnsigned::from(RHS,
Bits),
Bits, &R);
2898 if (
Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
2900 R = LT::AsUnsigned::from(-1);
2904 LT::shiftRight(LHS, LT::from(RHS,
Bits),
Bits, &A);
2905 R = LT::AsUnsigned::from(A);
2913template <
class LT,
class RT, ShiftDir Dir>
2916 const unsigned Bits = LHS.getBitWidth();
2921 APSInt(llvm::APInt(RHS.getBitWidth(),
static_cast<uint64_t
>(
Bits - 1)),
2924 if (RHS.isNegative()) {
2928 S.
CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS;
2933 S, OpPC, LHS, -RHS,
Result);
2957template <PrimType NameL, PrimType NameR>
2961 auto RHS = S.
Stk.
pop<RT>();
2969 RHS.toAPSInt(), &
Result);
2976template <PrimType NameL, PrimType NameR>
2980 auto RHS = S.
Stk.
pop<RT>();
2988 RHS.toAPSInt(), &
Result);
2998 llvm::FixedPointSemantics LHSSema = LHS.
getSemantics();
3000 unsigned ShiftBitWidth =
3001 LHSSema.getWidth() - (
unsigned)LHSSema.hasUnsignedPadding() - 1;
3006 if (RHS.isNegative()) {
3009 }
else if (
static_cast<unsigned>(RHS.toAPSInt().getLimitedValue(
3010 ShiftBitWidth)) != RHS.toAPSInt()) {
3012 S.
CCEDiag(E, diag::note_constexpr_large_shift)
3013 << RHS.toAPSInt() << E->
getType() << ShiftBitWidth;
3037 S.
FFDiag(EndLoc, diag::note_constexpr_no_return);
3068template <PrimType Name, class T = typename PrimConv<Name>::T>
3073 if (!Ptr.isZero() && !Offset.isZero()) {
3078 if (Offset.isZero()) {
3079 if (
const Descriptor *Desc = Ptr.getFieldDesc();
3080 Desc && Desc->
isArray() && Ptr.getIndex() == 0) {
3088 assert(!Offset.isZero());
3090 if (std::optional<Pointer>
Result =
3099template <PrimType Name, class T = typename PrimConv<Name>::T>
3104 if (!Ptr.isZero() && !Offset.isZero()) {
3109 if (Offset.isZero()) {
3110 if (
const Descriptor *Desc = Ptr.getFieldDesc();
3111 Desc && Desc->
isArray() && Ptr.getIndex() == 0) {
3119 assert(!Offset.isZero());
3121 if (std::optional<Pointer>
Result =
3129template <PrimType Name, class T = typename PrimConv<Name>::T>
3141template <PrimType Name, class T = typename PrimConv<Name>::T>
3153template <PrimType Name, class T = typename PrimConv<Name>::T>
3155 uint32_t DestIndex, uint32_t Size) {
3159 if (SrcPtr.isDummy() || DestPtr.
isDummy())
3162 for (uint32_t I = 0; I != Size; ++I) {
3168 DestPtr.
elem<
T>(DestIndex + I) = SrcPtr.elem<
T>(SrcIndex + I);
3195 S.
FFDiag(E, diag::note_constexpr_unsupported_unsized_array);
3206template <PrimType Name, class T = typename PrimConv<Name>::T>
3211 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3226 if (!MP.isBaseCastPossible())
3248 S.
FFDiag(Loc, diag::note_constexpr_stmt_expr_unsupported)
3290 bool SrcIsVoidPtr) {
3294 if (!Ptr.isBlockPointer())
3301 bool HasValidResult = !Ptr.isZero();
3303 if (HasValidResult) {
3313 S.
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
3314 << E->getSubExpr()->getType() << S.
getLangOpts().CPlusPlus26
3315 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
3318 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
3319 << diag::ConstexprInvalidCastKind::CastFrom <<
"'void *'"
3328 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3342 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3343 << diag::ConstexprInvalidCastKind::Reinterpret
3347 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3348 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3355 S.
FFDiag(E, diag::note_constexpr_access_volatile_type)
3356 <<
AK_Read << E->getSubExpr()->getType();
3364 S.
CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3365 << diag::ConstexprInvalidCastKind::Dynamic;
3368 llvm_unreachable(
"Unhandled CastKind");
3376 diag::note_constexpr_access_volatile_type)
3391 S.
FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
3392 S.
Note(VD->getLocation(), diag::note_declared_at);
3403 S.
CCEDiag(E, diag::note_constexpr_non_const_vectorelements) << ArgRange;
3411 diag::note_constexpr_pseudo_destructor);
3423 S.
CCEDiag(Loc, diag::note_constexpr_assumption_failed);
3427template <PrimType Name, class T = typename PrimConv<Name>::T>
3431 ArrayIndices.emplace_back(S.
Stk.
pop<int64_t>());
3442template <PrimType Name, class T = typename PrimConv<Name>::T>
3449 S.
CCEDiag(Loc, diag::note_non_null_attribute_failed);
3455 const APSInt &
Value);
3457template <PrimType Name, class T = typename PrimConv<Name>::T>
3470template <PrimType TIn, PrimType TOut>
3476 const FromT &OldPtr = S.
Stk.
pop<FromT>();
3478 if constexpr (std::is_same_v<FromT, FunctionPointer> &&
3479 std::is_same_v<ToT, Pointer>) {
3482 }
else if constexpr (std::is_same_v<FromT, Pointer> &&
3483 std::is_same_v<ToT, FunctionPointer>) {
3484 if (OldPtr.isFunctionPointer()) {
3486 OldPtr.getByteOffset());
3491 S.
Stk.
push<ToT>(ToT(OldPtr.getIntegerRepresentation(),
nullptr));
3528template <PrimType Name, class SizeT = typename PrimConv<Name>::T>
3543 if (NumElements.isNegative()) {
3553 if (!
CheckArraySize(S, OpPC,
static_cast<uint64_t
>(NumElements)))
3558 Allocator.
allocate(Source,
T,
static_cast<size_t>(NumElements),
3561 if (NumElements.isZero())
3568template <PrimType Name, class SizeT = typename PrimConv<Name>::T>
3587 assert(NumElements.isPositive());
3589 if (!
CheckArraySize(S, OpPC,
static_cast<uint64_t
>(NumElements)))
3594 Allocator.
allocate(ElementDesc,
static_cast<size_t>(NumElements),
3597 if (NumElements.isZero())
3605bool Free(InterpState &S, CodePtr OpPC,
bool DeleteIsArrayForm,
3606 bool IsGlobalDelete);
3620 std::optional<uint64_t> ArraySize = std::nullopt);
3622template <PrimType Name, class T = typename PrimConv<Name>::T>
3624 const auto &Size = S.
Stk.
pop<
T>();
3629template <PrimType Name, class T = typename PrimConv<Name>::T>
3631 uint32_t ResultBitWidth,
const llvm::fltSemantics *Sem,
3632 const Type *TargetType) {
3638 if constexpr (std::is_same_v<T, Pointer>) {
3641 diag::note_constexpr_bit_cast_invalid_type)
3642 <<
true <<
false << 1 ;
3648 }
else if constexpr (std::is_same_v<T, MemberPointer>) {
3650 diag::note_constexpr_bit_cast_invalid_type)
3651 <<
true <<
false << 2 ;
3655 size_t BuffSize = ResultBitWidth / 8;
3657 bool HasIndeterminateBits =
false;
3659 Bits FullBitWidth(ResultBitWidth);
3660 Bits BitWidth = FullBitWidth;
3662 if constexpr (std::is_same_v<T, Floating>) {
3664 BitWidth =
Bits(llvm::APFloatBase::getSizeInBits(*Sem));
3667 if (!
DoBitCast(S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth,
3668 HasIndeterminateBits))
3671 if (!
CheckBitCast(S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte))
3674 if constexpr (std::is_same_v<T, Floating>) {
3681 T::bitcastFromMemory(Buff.data(), ResultBitWidth, &
Result);
3683 }
else if constexpr (std::is_same_v<T, Boolean>) {
3687 auto Val =
static_cast<unsigned int>(Buff[0]);
3690 diag::note_constexpr_bit_cast_unrepresentable_value)
3694 S.
Stk.
push<
T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
3697 S.
Stk.
push<
T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
3717bool GetTypeid(InterpState &S, CodePtr OpPC,
const Type *TypePtr,
3718 const Type *TypeInfoType);
3720bool DiagTypeid(InterpState &S, CodePtr OpPC);
3732 if constexpr (std::is_pointer<T>::value) {
3733 uint32_t ID = OpPC.
read<uint32_t>();
3736 return OpPC.
read<
T>();
3746 OpPC +=
align(F.bytesToSerialize());
3755 assert(
Result.bitWidth() == BitWidth);
3766 auto Result = S.
allocAP<IntegralAP<true>>(BitWidth);
3767 assert(Result.bitWidth() == BitWidth);
3770 OpPC +=
align(Result.bytesToSerialize());
Defines the clang::ASTContext interface.
void HandleComplexComplexDiv(APFloat A, APFloat B, APFloat C, APFloat D, APFloat &ResR, APFloat &ResI)
void HandleComplexComplexMul(APFloat A, APFloat B, APFloat C, APFloat D, APFloat &ResR, APFloat &ResI)
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.
bool hasSimilarType(QualType T1, QualType T2) const
Determine if two types are similar, according to the C++ rules.
Represents a static or instance method of a struct/union/class.
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
unsigned getBuiltinCallee() const
getBuiltinCallee - If this is a call to a builtin, return the builtin ID of the callee.
const ValueInfo * getValueInfo(ComparisonCategoryResult ValueKind) const
ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const
Converts the specified result kind into the correct result kind for this category.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getLocation() const
AccessSpecifier getAccess() const
bool isFixed() const
Returns true if this is an Objective-C, C++11, or Microsoft-style enumeration with a fixed underlying...
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...
static FPOptions getFromOpaqueInt(storage_type Value)
Represents a member of a struct/union/class.
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Represents a function declaration or definition.
Implicit declaration of a temporary that was materialized by a MaterializeTemporaryExpr and lifetime-...
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
unsigned getNumExpressions() const
A (possibly-)qualified type.
QualType withVolatile() const
Represents a struct/union/class.
Encodes a location in the source.
A trivial tuple used to represent a source range.
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.
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 isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isNullPtrType() 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 isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
ThreadStorageClassSpecifier getTSCSpec() const
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
bool isUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value can be used in a constant expression, according to the releva...
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.
std::byte * rawData()
Returns a pointer to the raw data, including metadata.
Wrapper around boolean types.
static Boolean from(T Value)
Pointer into the code segment.
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
const Function * getOrCreateFunction(const FunctionDecl *FuncDecl)
unsigned getEvalID() const
Manages dynamic memory allocations done during bytecode interpretation.
Block * allocate(const Descriptor *D, unsigned EvalID, Form AllocForm)
Allocate ONE element of the given descriptor.
Wrapper around fixed point types.
llvm::FixedPointSemantics getSemantics() const
static bool shiftRight(const FixedPoint A, const FixedPoint B, unsigned OpBits, FixedPoint *R)
static FixedPoint deserialize(const std::byte *Buff)
static bool shiftLeft(const FixedPoint A, const FixedPoint B, unsigned OpBits, FixedPoint *R)
static FixedPoint from(const APSInt &I, llvm::FixedPointSemantics Sem, bool *Overflow)
size_t bytesToSerialize() const
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
static APFloat::opStatus div(const Floating &A, const Floating &B, llvm::RoundingMode RM, Floating *R)
static llvm::APFloatBase::Semantics deserializeSemantics(const std::byte *Buff)
void copy(const APFloat &F)
static APFloat::opStatus fromIntegral(APSInt Val, const llvm::fltSemantics &Sem, llvm::RoundingMode RM, Floating *Result)
static APFloat::opStatus sub(const Floating &A, const Floating &B, llvm::RoundingMode RM, Floating *R)
static APFloat::opStatus increment(const Floating &A, llvm::RoundingMode RM, Floating *R)
static APFloat::opStatus add(const Floating &A, const Floating &B, llvm::RoundingMode RM, Floating *R)
static void deserialize(const std::byte *Buff, Floating *Result)
static APFloat::opStatus mul(const Floating &A, const Floating &B, llvm::RoundingMode RM, Floating *R)
void toSemantics(const llvm::fltSemantics *Sem, llvm::RoundingMode RM, Floating *Result) const
const llvm::fltSemantics & getSemantics() const
static APFloat::opStatus decrement(const Floating &A, llvm::RoundingMode RM, Floating *R)
APFloat::opStatus convertToInteger(APSInt &Result) const
static void bitcastFromMemory(const std::byte *Buff, const llvm::fltSemantics &Sem, Floating *Result)
APFloat getAPFloat() const
const Function * getFunction() const
Scope & getScope(unsigned Idx)
Returns a specific scope.
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
bool hasRVO() const
Checks if the first argument is a RVO pointer.
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
static uint32_t deserializeSize(const std::byte *Buff)
static void deserialize(const std::byte *Buff, IntegralAP< Signed > *Result)
void copy(const APInt &V)
Wrapper around numeric types.
Frame storing local variables.
static void free(InterpFrame *F)
const Expr * getExpr(CodePtr PC) const
InterpFrame * Caller
The frame of the previous function.
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
CodePtr getRetPC() const
Returns the return address of the frame.
Block * getLocalBlock(unsigned Offset) const
SourceLocation getLocation(CodePtr PC) const
const Pointer & getThis() const
Returns the 'this' pointer.
const Function * getFunction() const
Returns the current function.
size_t getFrameOffset() const
Returns the offset on the stack at which the frame starts.
SourceRange getRange(CodePtr PC) const
void setLocal(unsigned Offset, const T &Value)
Mutates a local variable.
const T & getParam(unsigned Offset) const
Returns the value of an argument.
bool isBottomFrame() const
bool hasThisPointer() const
Pointer getLocalPointer(unsigned Offset) const
Returns a pointer to a local variables.
unsigned getDepth() const
void setParam(unsigned Offset, const T &Value)
Mutates a local copy of a parameter.
void destroy(unsigned Idx)
Invokes the destructors for a scope.
const Pointer & getRVOPtr() const
Returns the RVO pointer, if the Function has one.
Pointer getParamPointer(unsigned Offset)
Returns a pointer to an argument - lazily creates a block.
const FunctionDecl * getCallee() const override
Returns the caller.
void initScope(unsigned Idx)
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.
void dump() const
dump the stack contents to stderr.
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.
SmallVectorImpl< PartialDiagnosticAt > * PrevDiags
Things needed to do speculative execution.
Expr::EvalStatus & getEvalStatus() const override
Context & getContext() const
bool noteUndefinedBehavior() override
DynamicAllocator & getAllocator()
Context & Ctx
Interpreter Context.
Floating allocFloat(const llvm::fltSemantics &Sem)
ASTContext & getASTContext() const override
llvm::SmallVector< std::pair< const Expr *, const LifetimeExtendedTemporaryDecl * > > SeenGlobalTemporaries
InterpStack & Stk
Temporary stack.
bool maybeDiagnoseDanglingAllocations()
Diagnose any dynamic allocations that haven't been freed yet.
bool noteSideEffect() override
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
InterpFrame * Current
The current frame.
std::optional< bool > ConstantContextOverride
T allocAP(unsigned BitWidth)
const LangOptions & getLangOpts() const
unsigned SpeculationDepth
StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const
bool inConstantContext() const
Program & P
Reference to the module containing all bytecode.
ComparisonCategoryResult compare(const MemberPointer &RHS) const
A pointer to a memory block, live or dead.
static bool hasSameBase(const Pointer &A, const Pointer &B)
Checks if two pointers are comparable.
Pointer narrow() const
Restricts the scope of an array element pointer.
bool isInitialized() const
Checks if an object was initialized.
bool isZeroSizeArray() const
Checks if the pointer is pointing to a zero-size array.
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
bool isDummy() const
Checks if the pointer points to a dummy value.
Pointer atFieldSub(unsigned Off) const
Subtract the given offset from the current Base and Offset of the pointer.
int64_t getIndex() const
Returns the index into an array.
Pointer atField(unsigned Off) const
Creates a pointer to a field.
T & deref() const
Dereferences the pointer, if it's live.
unsigned getNumElems() const
Returns the number of elements.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
void activate() const
Activats a field.
static std::optional< std::pair< Pointer, Pointer > > computeSplitPoint(const Pointer &A, const Pointer &B)
bool isIntegralPointer() const
QualType getType() const
Returns the type of the innermost field.
bool pointsToStringLiteral() const
bool inArray() const
Checks if the innermost field is an array.
T & elem(unsigned I) const
Dereferences the element at index I.
uint64_t getByteOffset() const
Returns the byte offset from the start.
bool isTypeidPointer() const
std::string toDiagnosticString(const ASTContext &Ctx) const
Converts the pointer to a string usable in diagnostics.
bool isZero() const
Checks if the pointer is null.
const IntPointer & asIntPointer() const
bool isRoot() const
Pointer points directly to a block.
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
unsigned getOffset() const
Returns the offset into an array.
bool isOnePastEnd() const
Checks if the index is one past end.
uint64_t getIntegerRepresentation() const
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
bool isBlockPointer() const
const FunctionPointer & asFunctionPointer() const
bool isFunctionPointer() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
size_t elemSize() const
Returns the element size of the innermost field.
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
Lifetime getLifetime() const
size_t computeOffsetForComparison() const
Compute an integer that can be used to compare this pointer to another one.
const BlockPointer & asBlockPointer() const
void initialize() const
Initializes a field.
void initializeElement(unsigned Index) const
Initialized the given element of a primitive array.
const Record * getRecord() const
Returns the record descriptor of a class.
Block * getGlobal(unsigned Idx)
Returns the value of a global.
const void * getNativePointer(unsigned Idx)
Returns the value of a marshalled native pointer.
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
Structure/Class descriptor.
const RecordDecl * getDecl() const
Returns the underlying declaration.
llvm::iterator_range< LocalVectorTy::const_reverse_iterator > locals_reverse() const
Describes the statement/declaration an opcode was generated from.
bool checkingForUndefinedBehavior() const
Are we checking an expression for overflow?
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
DiagnosticBuilder report(SourceLocation Loc, diag::kind DiagId)
Directly reports a diagnostic message.
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)
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.
bool checkingPotentialConstantExpression() const
Are we checking whether the expression is a potential constant expression?
bool arePotentiallyOverlappingStringLiterals(const Pointer &LHS, const Pointer &RHS)
bool EndSpeculation(InterpState &S, CodePtr OpPC)
static bool ShiftFixedPoint(InterpState &S, CodePtr OpPC, bool Left)
bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off)
bool InitPop(InterpState &S, CodePtr OpPC)
bool Shr(InterpState &S, CodePtr OpPC)
bool InitGlobalTemp(InterpState &S, CodePtr OpPC, uint32_t I, const LifetimeExtendedTemporaryDecl *Temp)
1) Converts the value on top of the stack to an APValue 2) Sets that APValue on \Temp 3) Initializes ...
bool CheckDestruction(InterpState &S, CodePtr OpPC)
bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index)
bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool PopCC(InterpState &S, CodePtr OpPC)
bool ArrayElem(InterpState &S, CodePtr OpPC, uint32_t Index)
bool GT(InterpState &S, CodePtr OpPC)
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.
static bool CastFloatingIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth, uint32_t FPOI)
bool GetMemberPtrBase(InterpState &S, CodePtr OpPC)
bool GetThisField(InterpState &S, CodePtr OpPC, uint32_t I)
bool PreInc(InterpState &S, CodePtr OpPC, bool CanOverflow)
bool NarrowPtr(InterpState &S, CodePtr OpPC)
bool CheckFunctionDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *FD)
Opcode. Check if the function decl can be called at compile time.
bool GetMemberPtrBasePop(InterpState &S, CodePtr OpPC, int32_t Off)
bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I)
bool BitCastPrim(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte, uint32_t ResultBitWidth, const llvm::fltSemantics *Sem, const Type *TargetType)
Floating ReadArg< Floating >(InterpState &S, CodePtr &OpPC)
bool Incf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
bool SideEffect(InterpState &S, CodePtr OpPC)
static bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS, LT *Result)
bool GetParam(InterpState &S, CodePtr OpPC, uint32_t I)
bool EndLifetimePop(InterpState &S, CodePtr OpPC)
Ends the lifetime of the pop'd pointer.
bool Sub(InterpState &S, CodePtr OpPC)
bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType)
bool Mulf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx)
The same as InitElem, but pops the pointer as well.
bool StoreBitField(InterpState &S, CodePtr OpPC)
bool LT(InterpState &S, CodePtr OpPC)
bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t Offset)
Checks if the dowcast using the given offset is possible with the given pointer.
bool BitCast(InterpState &S, CodePtr OpPC)
bool LoadPop(InterpState &S, CodePtr OpPC)
bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, const Descriptor *Desc)
bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B)
Checks a direct load of a primitive value from a global or local variable.
static llvm::RoundingMode getRoundingMode(FPOptions FPO)
static bool IncPtr(InterpState &S, CodePtr OpPC)
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 GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr, const Type *TypeInfoType)
Typeid support.
bool Dup(InterpState &S, CodePtr OpPC)
bool SetField(InterpState &S, CodePtr OpPC, uint32_t I)
bool CheckNonNullArg(InterpState &S, CodePtr OpPC)
bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, const APSInt &IntValue)
Sets the given integral value to the pointer, which is of a std::{weak,partial,strong}...
static bool IncDecPtrHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
bool FinishInitActivate(InterpState &S, CodePtr OpPC)
bool GetPtrLocal(InterpState &S, CodePtr OpPC, uint32_t I)
bool Addf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS)
Checks if Div/Rem operation on LHS and RHS is valid.
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Checks if the Descriptor is of a constexpr or const global variable.
static bool IsOpaqueConstantCall(const CallExpr *E)
bool CheckDecl(InterpState &S, CodePtr OpPC, const VarDecl *VD)
bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, unsigned BitWidth)
bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS, const T &RHS)
bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off)
1) Peeks a Pointer 2) Pushes Pointer.atField(Off) on the stack
bool StoreActivate(InterpState &S, CodePtr OpPC)
bool Div(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func)
bool FinishInitActivatePop(InterpState &S, CodePtr OpPC)
bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I)
Same as GetGlobal, but without the checks.
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if Ptr is a one-past-the-end pointer.
bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
static bool Activate(InterpState &S, CodePtr OpPC)
bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC, const FixedPoint &FP)
bool Mulc(InterpState &S, CodePtr OpPC)
bool RetVoid(InterpState &S, CodePtr &PC)
bool ArrayElemPtr(InterpState &S, CodePtr OpPC)
bool NE(InterpState &S, CodePtr OpPC)
bool NoRet(InterpState &S, CodePtr OpPC)
bool GetIntPtr(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
llvm::FixedPointSemantics FixedPointSemantics
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a value can be loaded from a block.
static bool FnPtrCast(InterpState &S, CodePtr OpPC)
static bool ZeroIntAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool Shl(InterpState &S, CodePtr OpPC)
bool RVOPtr(InterpState &S, CodePtr OpPC)
bool CastPointerIntegral(InterpState &S, CodePtr OpPC)
constexpr bool isPtrType(PrimType T)
bool DecfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI)
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, ArrayRef< int64_t > ArrayIndices, int64_t &IntResult)
Interpret an offsetof operation.
bool SubOffset(InterpState &S, CodePtr OpPC)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
bool BitXor(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool CheckBCPResult(InterpState &S, const Pointer &Ptr)
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
bool CastAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool ExpandPtr(InterpState &S, CodePtr OpPC)
bool Store(InterpState &S, CodePtr OpPC)
bool Divc(InterpState &S, CodePtr OpPC)
bool DoBitCastPtr(InterpState &S, CodePtr OpPC, const Pointer &FromPtr, Pointer &ToPtr)
bool GetField(InterpState &S, CodePtr OpPC, uint32_t I)
1) Peeks a pointer on the stack 2) Pushes the value of the pointer's field on the stack
bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC)
bool This(InterpState &S, CodePtr OpPC)
bool InitScope(InterpState &S, CodePtr OpPC, uint32_t I)
bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC)
Checks if dynamic memory allocation is available in the current language mode.
bool InitField(InterpState &S, CodePtr OpPC, uint32_t I)
1) Pops the value from the stack 2) Peeks a pointer from the stack 3) Pushes the value to field I of ...
bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn)
T ReadArg(InterpState &S, CodePtr &OpPC)
bool PreDecBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, uint32_t BitWidth)
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
bool CastFloatingIntegral(InterpState &S, CodePtr OpPC, uint32_t FPOI)
bool ArrayDecay(InterpState &S, CodePtr OpPC)
Just takes a pointer and checks if it's an incomplete array type.
bool PushCC(InterpState &S, CodePtr OpPC, bool Value)
bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK, const Type *TargetType)
bool DiagTypeid(InterpState &S, CodePtr OpPC)
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
This is not used by any of the opcodes directly.
bool InitGlobalTempComp(InterpState &S, CodePtr OpPC, const LifetimeExtendedTemporaryDecl *Temp)
1) Converts the value on top of the stack to an APValue 2) Sets that APValue on \Temp 3) Initialized ...
bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits, bool TargetIsUCharOrByte)
bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I)
bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E)
bool BitAnd(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS, unsigned Bits)
Checks if the shift operation is legal.
static bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue)
FixedPoint ReadArg< FixedPoint >(InterpState &S, CodePtr &OpPC)
static bool CastFloatingFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS)
void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED, const APSInt &Value)
bool StartLifetime(InterpState &S, CodePtr OpPC)
bool LE(InterpState &S, CodePtr OpPC)
bool CheckNewTypeMismatchArray(InterpState &S, CodePtr OpPC, const Expr *E)
bool Zero(InterpState &S, CodePtr OpPC)
bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F, uint32_t FieldOffset)
bool Unsupported(InterpState &S, CodePtr OpPC)
Just emit a diagnostic.
bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR, bool InitializerFailed)
bool DecPop(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value decreased by ...
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source, const Pointer &Ptr)
Check the source of the pointer passed to delete/delete[] has actually been heap allocated by us.
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result, APFloat::opStatus Status, FPOptions FPO)
Checks if the result of a floating-point operation is valid in the current context.
bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, llvm::RoundingMode RM)
1) Pops a Floating from the stack.
ComparisonCategoryResult Compare(const T &X, const T &Y)
Helper to compare two comparable types.
PrimType
Enumeration of the primitive types of the VM.
bool DecPopBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, uint32_t BitWidth)
bool InitThisBitFieldActivate(InterpState &S, CodePtr OpPC, const Record::Field *F, uint32_t FieldOffset)
bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I)
bool StoreBitFieldPop(InterpState &S, CodePtr OpPC)
bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr, bool CanOverflow, UnsignedOrNone BitWidth=std::nullopt)
bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
static bool DecPtr(InterpState &S, CodePtr OpPC)
constexpr bool needsAlloc()
static bool CheckAllocations(InterpState &S, CodePtr OpPC)
bool Alloc(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index)
bool ToMemberPtr(InterpState &S, CodePtr OpPC)
static bool CastIntegralFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS)
bool Rem(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl, const Pointer &Ptr)
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 GetMemberPtr(InterpState &S, CodePtr OpPC, const ValueDecl *D)
bool Dump(InterpState &S, CodePtr OpPC)
bool SizelessVectorElementSize(InterpState &S, CodePtr OpPC)
static bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr)
bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T)
bool IsNonNull(InterpState &S, CodePtr OpPC)
bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off)
bool ConstFloat(InterpState &S, CodePtr OpPC, const Floating &F)
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
bool InitThisFieldActivate(InterpState &S, CodePtr OpPC, uint32_t I)
bool IncBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, unsigned BitWidth)
bool SubPtr(InterpState &S, CodePtr OpPC, bool ElemSizeIsZero)
1) Pops a Pointer from the stack.
bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off)
bool SetParam(InterpState &S, CodePtr OpPC, uint32_t I)
bool StoreActivatePop(InterpState &S, CodePtr OpPC)
bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC)
bool Comp(InterpState &S, CodePtr OpPC)
1) Pops the value from the stack.
static bool CastFixedPointFloating(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem)
bool Divf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
bool CheckThis(InterpState &S, CodePtr OpPC)
Checks the 'this' pointer.
bool FinishInitGlobal(InterpState &S, CodePtr OpPC)
bool DecayPtr(InterpState &S, CodePtr OpPC)
OldPtr -> Integer -> NewPtr.
static bool ActivateThisField(InterpState &S, CodePtr OpPC, uint32_t I)
bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
bool GetPtrVirtBasePop(InterpState &S, CodePtr OpPC, const RecordDecl *D)
bool StorePop(InterpState &S, CodePtr OpPC)
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC, const Function *Func)
bool SetLocal(InterpState &S, CodePtr OpPC, uint32_t I)
1) Pops the value from the stack.
bool FinishInit(InterpState &S, CodePtr OpPC)
bool InvalidStore(InterpState &S, CodePtr OpPC, const Type *T)
static bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth, uint32_t FPOI)
bool Mul(InterpState &S, CodePtr OpPC)
bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx)
1) Pops the value from the stack 2) Peeks a pointer and gets its index \Idx 3) Sets the value on the ...
bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I)
bool Pop(InterpState &S, CodePtr OpPC)
bool DecBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, uint32_t BitWidth)
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F)
bool PreIncBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, uint32_t BitWidth)
bool Dec(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value decreased by ...
bool StoreBitFieldActivate(InterpState &S, CodePtr OpPC)
bool CheckPseudoDtor(InterpState &S, CodePtr OpPC)
bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm, bool IsGlobalDelete)
bool PreDec(InterpState &S, CodePtr OpPC, bool CanOverflow)
bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E)
bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems)
bool CallBI(InterpState &S, CodePtr OpPC, const CallExpr *CE, uint32_t BuiltinID)
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B)
bool FinishInitPop(InterpState &S, CodePtr OpPC)
bool Neg(InterpState &S, CodePtr OpPC)
bool StartSpeculation(InterpState &S, CodePtr OpPC)
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
std::optional< Pointer > OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, const Pointer &Ptr, bool IsPointerArith=false)
bool BitOr(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
llvm::function_ref< bool(ComparisonCategoryResult)> CompareFn
bool Inv(InterpState &S, CodePtr OpPC)
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr, bool WillBeActivated)
Checks if a value can be stored in a block.
bool Load(InterpState &S, CodePtr OpPC)
bool isConstexprUnknown(const Pointer &P)
bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool Cast(InterpState &S, CodePtr OpPC)
bool StoreBitFieldActivatePop(InterpState &S, CodePtr OpPC)
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
bool EQ(InterpState &S, CodePtr OpPC)
bool IncfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI)
bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK)
bool GetFieldPop(InterpState &S, CodePtr OpPC, uint32_t I)
1) Pops a pointer from the stack 2) Pushes the value of the pointer's field on the stack
bool Add(InterpState &S, CodePtr OpPC)
bool CmpHelperEQ< MemberPointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
bool AddOffset(InterpState &S, CodePtr OpPC)
bool Const(InterpState &S, CodePtr OpPC, const T &Arg)
bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest)
Copy the contents of Src into Dest.
bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
bool IncPop(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
bool Memcpy(InterpState &S, CodePtr OpPC)
bool GE(InterpState &S, CodePtr OpPC)
bool DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, std::byte *Buff, Bits BitWidth, Bits FullBitWidth, bool &HasIndeterminateBits)
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, const CallExpr *CE)
bool CmpHelperEQ< Pointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
static bool CastFixedPointIntegral(InterpState &S, CodePtr OpPC)
constexpr bool isIntegralType(PrimType T)
bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
bool CastIntegralFloating(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, uint32_t FPOI)
bool CmpHelper(InterpState &S, CodePtr OpPC, CompareFn Fn)
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
bool CastFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS)
bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t I)
bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc, bool IsNoThrow)
bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool Subf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D)
bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, bool Fatal)
Same here, but only for casts.
bool DoShiftAP(InterpState &S, CodePtr OpPC, const APSInt &LHS, APSInt RHS, LT *Result)
A version of DoShift that works on IntegralAP.
bool CastMemberPtrPtr(InterpState &S, CodePtr OpPC)
bool Ret(InterpState &S, CodePtr &PC)
bool InitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t I)
bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
bool IncPopBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, uint32_t BitWidth)
bool Flip(InterpState &S, CodePtr OpPC)
[Value1, Value2] -> [Value2, Value1]
bool CMP3(InterpState &S, CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo)
bool InitBitFieldActivate(InterpState &S, CodePtr OpPC, const Record::Field *F)
bool CastAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
Like Cast(), but we cast to an arbitrary-bitwidth integral, so we need to know what bitwidth the resu...
bool Invalid(InterpState &S, CodePtr OpPC)
bool CmpHelper< Pointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
bool Decf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
bool Assume(InterpState &S, CodePtr OpPC)
bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off)
bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t FPOI)
static bool IsConstantContext(InterpState &S, CodePtr OpPC)
bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source, bool IsNoThrow)
bool CheckEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
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.
const FunctionProtoType * T
@ ConstantFold
Fold the expression to a constant.
U cast(CodeGen::Address addr)
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
size_t getQuantity() const
unsigned Base
Start of the current subfield.
Block * Pointee
The block the pointer is pointing to.
Describes a memory block created by an allocation site.
unsigned getSize() const
Returns the size of the object without metadata.
const Decl * asDecl() const
SourceLocation getLocation() const
PrimType getPrimType() const
const Expr * asExpr() const
bool isArray() const
Checks if the descriptor is of an array.
Descriptor used for global variables.
Mapping from primitive types to their representation.