13#ifndef LLVM_CLANG_AST_INTERP_INTERP_H
14#define LLVM_CLANG_AST_INTERP_INTERP_H
35#include "llvm/ADT/APFloat.h"
36#include "llvm/ADT/APSInt.h"
37#include "llvm/Support/Compiler.h"
44#if !defined(__aarch64__) && !defined(__i386__) && \
45 !__has_feature(address_sanitizer) && \
46 __has_cpp_attribute(clang::preserve_none)
47#define PRESERVE_NONE [[clang::preserve_none]]
55using APSInt = llvm::APSInt;
95 bool WillBeActivated =
false);
121 uint32_t VarArgSize);
123 uint32_t VarArgSize);
125 uint32_t VarArgSize);
133 bool TargetIsUCharOrByte);
149 bool IsReferenceCast);
166 const APSInt *
Value =
nullptr,
170template <ShiftDir Dir,
typename LT,
typename RT>
173 if (RHS.isNegative()) {
188 if (LHS.isSigned() && !S.
getLangOpts().CPlusPlus20) {
191 if (LHS.isNegative()) {
196 }
else if (LHS.toUnsigned().countLeadingZeros() <
197 static_cast<unsigned>(RHS)) {
215 if (!LHS.isNumber() || !RHS.isNumber())
221 if constexpr (std::is_same_v<T, Floating>) {
222 S.
CCEDiag(Op, diag::note_expr_divide_by_zero)
223 << Op->getRHS()->getSourceRange();
227 S.
FFDiag(Op, diag::note_expr_divide_by_zero)
228 << Op->getRHS()->getSourceRange();
232 if constexpr (!std::is_same_v<T, FixedPoint>) {
233 if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) {
234 APSInt LHSInt = LHS.toAPSInt();
236 (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10);
239 S.
CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->
getType();
260 APFloat::opStatus Status,
FPOptions FPO);
265bool CheckFloatStatus(InterpState &S, CodePtr OpPC, APFloat::opStatus Status,
287template <PrimType Name, class T = typename PrimConv<Name>::T>
335 template <typename U>
class OpAP>
340 assert(LHS.isNumber() && RHS.isNumber());
356 if constexpr (std::is_same_v<T, FixedPoint>)
372 .toString(Trunc, 10,
Result.isSigned(),
false,
386template <
typename T,
template <
typename U>
class Op>
388 assert(!LHS.isNumber() || !RHS.isNumber());
392 typename T::ReprT Offset;
394 if (LHS.isNumber()) {
398 Number =
static_cast<typename T::ReprT
>(LHS);
400 Offset = RHS.getOffset();
401 Kind = RHS.getKind();
403 assert(RHS.isNumber());
407 Number =
static_cast<typename T::ReprT
>(RHS);
409 Offset = LHS.getOffset();
410 Kind = LHS.getKind();
417template <PrimType Name, class T = typename PrimConv<Name>::T>
421 const unsigned Bits = RHS.bitWidth() + 1;
424 if (LHS.isNumber() != RHS.isNumber())
426 else if (LHS.isNumber() && RHS.isNumber())
446template <PrimType Name, class T = typename PrimConv<Name>::T>
450 const unsigned Bits = RHS.bitWidth() + 1;
459 ?
reinterpret_cast<const Expr *
>(LHS.getPtr())
462 ?
reinterpret_cast<const Expr *
>(RHS.getPtr())
464 if (!isa_and_nonnull<AddrLabelExpr>(A) ||
465 !isa_and_nonnull<AddrLabelExpr>(B))
470 if (LHSAddrExpr->getLabel()->getDeclContext() !=
471 RHSAddrExpr->getLabel()->getDeclContext())
474 S.
Stk.
push<
T>(LHSAddrExpr, RHSAddrExpr);
478 if (!LHS.isNumber() && RHS.isNumber())
480 else if (LHS.isNumber() && RHS.isNumber())
500template <PrimType Name, class T = typename PrimConv<Name>::T>
504 const unsigned Bits = RHS.bitWidth() * 2;
507 if (!LHS.isNumber() || !RHS.isNumber())
527template <PrimType Name, class T = typename PrimConv<Name>::T>
533 if constexpr (std::is_same_v<T, Floating>) {
539 APFloat ResR(A.getSemantics());
540 APFloat ResI(A.getSemantics());
551 Result.initializeAllElements();
554 const T &LHSR = LHS.elem<
T>(0);
555 const T &LHSI = LHS.elem<
T>(1);
556 const T &RHSR = RHS.
elem<
T>(0);
557 const T &RHSI = RHS.
elem<
T>(1);
558 unsigned Bits = LHSR.bitWidth();
561 if (!LHSR.isNumber() || !LHSI.isNumber() || !RHSR.isNumber() ||
569 if (T::mul(LHSR, RHSR,
Bits, &A))
575 if (T::mul(LHSI, RHSI,
Bits, &B))
584 if (T::mul(LHSR, RHSI,
Bits, &A))
586 if (T::mul(LHSI, RHSR,
Bits, &B))
594 Result.initializeAllElements();
600template <PrimType Name, class T = typename PrimConv<Name>::T>
606 if constexpr (std::is_same_v<T, Floating>) {
612 APFloat ResR(A.getSemantics());
613 APFloat ResI(A.getSemantics());
625 Result.initializeAllElements();
628 const T &LHSR = LHS.elem<
T>(0);
629 const T &LHSI = LHS.elem<
T>(1);
630 const T &RHSR = RHS.
elem<
T>(0);
631 const T &RHSI = RHS.
elem<
T>(1);
632 unsigned Bits = LHSR.bitWidth();
634 if (RHSR.isZero() && RHSI.isZero()) {
636 S.
FFDiag(E, diag::note_expr_divide_by_zero);
647 if (T::mul(RHSR, RHSR,
Bits, &A) || T::mul(RHSI, RHSI,
Bits, &B)) {
654 if (T::add(A, B,
Bits, &Den))
659 S.
FFDiag(E, diag::note_expr_divide_by_zero);
670 if (T::mul(LHSR, RHSR,
Bits, &A) || T::mul(LHSI, RHSI,
Bits, &B))
672 if (T::add(A, B,
Bits, &ResultR))
674 if (T::div(ResultR, Den,
Bits, &ResultR))
678 if (T::mul(LHSI, RHSR,
Bits, &A) || T::mul(LHSR, RHSI,
Bits, &B))
680 if (T::sub(A, B,
Bits, &ResultI))
682 if (T::div(ResultI, Den,
Bits, &ResultI))
684 Result.initializeAllElements();
693template <PrimType Name, class T = typename PrimConv<Name>::T>
697 unsigned Bits = RHS.bitWidth();
700 if (!LHS.isNumber() || !RHS.isNumber())
718template <PrimType Name, class T = typename PrimConv<Name>::T>
722 unsigned Bits = RHS.bitWidth();
725 if (!LHS.isNumber() || !RHS.isNumber())
743template <PrimType Name, class T = typename PrimConv<Name>::T>
747 unsigned Bits = RHS.bitWidth();
750 if (!LHS.isNumber() || !RHS.isNumber())
768template <PrimType Name, class T = typename PrimConv<Name>::T>
772 const unsigned Bits = RHS.bitWidth() * 2;
791template <PrimType Name, class T = typename PrimConv<Name>::T>
795 const unsigned Bits = RHS.bitWidth() * 2;
809 if constexpr (std::is_same_v<T, FixedPoint>) {
848template <PrimType Name, class T = typename PrimConv<Name>::T>
852 if constexpr (std::is_same_v<T, Floating>) {
871 "don't expect other types to fail at constexpr negation");
882 NegatedValue.trunc(
Result.bitWidth())
883 .toString(Trunc, 10,
Result.isSigned(),
false,
903template <
typename T, IncDecOp Op, PushVal DoPush>
906 assert(!Ptr.isDummy());
913 if constexpr (std::is_same_v<T, Boolean>) {
918 const T &
Value = Ptr.deref<
T>();
922 if (!
Value.isNumber())
934 if (!T::increment(
Value, &
Result) || !CanOverflow) {
936 Ptr.deref<
T>() =
Result.truncate(*BitWidth);
942 if (!T::decrement(
Value, &
Result) || !CanOverflow) {
944 Ptr.deref<
T>() =
Result.truncate(*BitWidth);
971 APResult.trunc(
Result.bitWidth())
972 .toString(Trunc, 10,
Result.isSigned(),
false,
985template <PrimType Name, class T = typename PrimConv<Name>::T>
997template <PrimType Name, class T = typename PrimConv<Name>::T>
1013template <PrimType Name, class T = typename PrimConv<Name>::T>
1024template <PrimType Name, class T = typename PrimConv<Name>::T>
1026 uint32_t BitWidth) {
1037template <PrimType Name, class T = typename PrimConv<Name>::T>
1048template <PrimType Name, class T = typename PrimConv<Name>::T>
1050 uint32_t BitWidth) {
1065template <PrimType Name, class T = typename PrimConv<Name>::T>
1076template <PrimType Name, class T = typename PrimConv<Name>::T>
1078 uint32_t BitWidth) {
1092template <PrimType Name, class T = typename PrimConv<Name>::T>
1103template <PrimType Name, class T = typename PrimConv<Name>::T>
1105 uint32_t BitWidth) {
1116template <PrimType Name, class T = typename PrimConv<Name>::T>
1126template <PrimType Name, class T = typename PrimConv<Name>::T>
1128 uint32_t BitWidth) {
1138template <IncDecOp Op, PushVal DoPush>
1148 llvm::APFloat::opStatus Status;
1201template <PrimType Name, class T = typename PrimConv<Name>::T>
1209 if (!T::comp(Val, &
Result)) {
1222template <
typename T>
1224 assert((!std::is_same_v<T, MemberPointer>) &&
1225 "Non-equality comparisons on member pointer types should already be "
1226 "rejected in Sema.");
1232 if (!LHS.isNumber() || !RHS.isNumber())
1236 S.
Stk.
push<BoolT>(BoolT::from(
Fn(LHS.compare(RHS))));
1240template <
typename T>
1255 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1268 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1276 if (std::optional<std::pair<PtrView, PtrView>> Split =
1278 const FieldDecl *LF = Split->first.getField();
1279 const FieldDecl *RF = Split->second.getField();
1282 diag::note_constexpr_pointer_comparison_base_classes);
1285 diag::note_constexpr_pointer_comparison_base_field)
1286 << Split->first.getRecord()->getDecl() << RF->
getParent() << RF;
1289 diag::note_constexpr_pointer_comparison_base_field)
1290 << Split->second.getRecord()->getDecl() << LF->
getParent() << LF;
1294 diag::note_constexpr_pointer_comparison_differing_access)
1309 return (
Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
1310 Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
1311 Builtin == Builtin::BI__builtin_ptrauth_sign_constant ||
1312 Builtin == Builtin::BI__builtin_function_start);
1324 if (LHS.isZero() && RHS.
isZero()) {
1330 for (
const auto &P : {LHS, RHS}) {
1335 S.
FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison)
1342 if (RHS.
isZero() || LHS.isZero()) {
1347 assert(!LHS.isZero());
1362 std::optional<size_t> A = LHS.computeOffsetForComparison(S.
getASTContext());
1375 diag::note_constexpr_literal_comparison)
1383 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
1389 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
1395 for (
const auto &P : {LHS, RHS}) {
1398 if (P.pointsToLiteral()) {
1399 const Expr *E = P.getRootExpr();
1402 S.
FFDiag(Loc, diag::note_constexpr_literal_comparison);
1405 if (
const auto *CE = dyn_cast<CallExpr>(E);
1408 S.
FFDiag(Loc, diag::note_constexpr_opaque_call_comparison)
1412 }
else if (P.isIntegralPointer()) {
1414 S.
FFDiag(Loc, diag::note_constexpr_pointer_constant_comparison)
1423 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_zero_sized)
1432 diag::note_constexpr_pointer_comparison_unspecified)
1450 for (
const auto &MP : {LHS, RHS}) {
1453 S.
FFDiag(Loc, diag::note_constexpr_mem_pointer_weak_comparison)
1454 << MP.getMemberFunction();
1462 if (LHS.
isZero() && RHS.isZero()) {
1466 if (LHS.
isZero() || RHS.isZero()) {
1472 for (
const auto &MP : {LHS, RHS}) {
1476 S.
CCEDiag(Loc, diag::note_constexpr_compare_virtual_mem_ptr) << MD;
1484template <PrimType Name, class T = typename PrimConv<Name>::T>
1491template <PrimType Name, class T = typename PrimConv<Name>::T>
1498 if constexpr (std::is_same_v<T, Pointer>) {
1501 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1509 const auto *CmpValueInfo =
1511 assert(CmpValueInfo);
1512 assert(CmpValueInfo->hasValidIntValue());
1516template <PrimType Name, class T = typename PrimConv<Name>::T>
1523template <PrimType Name, class T = typename PrimConv<Name>::T>
1530template <PrimType Name, class T = typename PrimConv<Name>::T>
1538template <PrimType Name, class T = typename PrimConv<Name>::T>
1545template <PrimType Name, class T = typename PrimConv<Name>::T>
1557template <PrimType Name, class T = typename PrimConv<Name>::T>
1563template <PrimType Name, class T = typename PrimConv<Name>::T>
1574 const auto &Top = S.
Stk.
pop<TopT>();
1575 const auto &Bottom = S.
Stk.
pop<BottomT>();
1587template <PrimType Name, class T = typename PrimConv<Name>::T>
1591 Result.copy(Arg.toAPSInt());
1596 if constexpr (std::is_same_v<T, uint16_t>) {
1598 }
else if constexpr (std::is_same_v<T, int16_t>) {
1600 }
else if constexpr (std::is_same_v<T, uint32_t>) {
1602 }
else if constexpr (std::is_same_v<T, int32_t>) {
1604 }
else if constexpr (std::is_same_v<T, uint64_t>) {
1606 }
else if constexpr (std::is_same_v<T, int64_t>) {
1627template <PrimType Name, class T = typename PrimConv<Name>::T>
1637bool PseudoDtor(InterpState &S, CodePtr OpPC);
1645template <PrimType Name, class T = typename PrimConv<Name>::T>
1651template <PrimType Name, class T = typename PrimConv<Name>::T>
1660template <PrimType Name, class T = typename PrimConv<Name>::T>
1668template <PrimType Name, class T = typename PrimConv<Name>::T>
1691template <PrimType Name, class T = typename PrimConv<Name>::T>
1712template <PrimType Name, class T = typename PrimConv<Name>::T>
1726template <PrimType Name, class T = typename PrimConv<Name>::T>
1738template <PrimType Name, class T = typename PrimConv<Name>::T>
1749template <PrimType Name, class T = typename PrimConv<Name>::T>
1755template <PrimType Name, class T = typename PrimConv<Name>::T>
1761 if constexpr (std::is_same_v<T, Floating>) {
1763 if (!Val.singleWord()) {
1764 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
1765 Val.take(NewMemory);
1768 }
else if constexpr (std::is_same_v<T, MemberPointer>) {
1772 for (
unsigned I = 0; I != PathLength; ++I) {
1773 NewPath[I] = Val.getPathEntry(I);
1775 Val.takePath(NewPath);
1777 auto &Val = P.
deref<
T>();
1778 if (!Val.singleWord()) {
1779 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
1780 Val.take(NewMemory);
1791template <PrimType Name, class T = typename PrimConv<Name>::T>
1799 assert(Ptr.getRootExpr());
1821template <PrimType Name, class T = typename PrimConv<Name>::T>
1828 if (!
This.isDereferencable())
1832 assert(Field.canBeInitialized());
1838template <PrimType Name, class T = typename PrimConv<Name>::T>
1845 if (!
This.isDereferencable())
1849 assert(Field.canBeInitialized());
1856template <PrimType Name, class T = typename PrimConv<Name>::T>
1858 uint32_t FieldBitWidth) {
1864 if (!
This.isDereferencable())
1868 assert(Field.canBeInitialized());
1872 if (!
Value.isNumber())
1876 Field.deref<
T>() =
Value.truncate(FieldBitWidth);
1881template <PrimType Name, class T = typename PrimConv<Name>::T>
1883 uint32_t FieldOffset, uint32_t FieldBitWidth) {
1889 if (!
This.isDereferencable())
1893 assert(Field.canBeInitialized());
1897 if (!
Value.isNumber())
1901 Field.deref<
T>() =
Value.truncate(FieldBitWidth);
1910template <PrimType Name, class T = typename PrimConv<Name>::T>
1914 if (!Ptr.isDereferencable())
1922 const Pointer &Field = Ptr.atField(I);
1923 Field.deref<
T>() =
Value;
1928template <PrimType Name, class T = typename PrimConv<Name>::T>
1932 if (!Ptr.isDereferencable())
1939 const Pointer &Field = Ptr.atField(I);
1940 Field.deref<
T>() =
Value;
1946template <PrimType Name, class T = typename PrimConv<Name>::T>
1948 uint32_t FieldBitWidth) {
1951 if (!Ptr.isDereferencable())
1955 if (!
Value.isNumber())
1963 const Pointer &Field = Ptr.atField(FieldOffset);
1965 unsigned BitWidth = std::min(FieldBitWidth,
Value.bitWidth());
1968 if constexpr (T::isSigned())
1970 Value.toAPSInt().trunc(BitWidth).sextOrTrunc(
Value.bitWidth()));
1973 Value.toAPSInt().trunc(BitWidth).zextOrTrunc(
Value.bitWidth()));
1977 Field.deref<
T>() =
Value.truncate(FieldBitWidth);
1983template <PrimType Name, class T = typename PrimConv<Name>::T>
1985 uint32_t FieldBitWidth) {
1988 if (!Ptr.isDereferencable())
1992 if (!
Value.isNumber())
2000 const Pointer &Field = Ptr.atField(FieldOffset);
2002 unsigned BitWidth = std::min(FieldBitWidth,
Value.bitWidth());
2005 if constexpr (T::isSigned())
2007 Value.toAPSInt().trunc(BitWidth).sextOrTrunc(
Value.bitWidth()));
2010 Value.toAPSInt().trunc(BitWidth).zextOrTrunc(
Value.bitWidth()));
2014 Field.deref<
T>() =
Value.truncate(FieldBitWidth);
2082bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t
Off,
bool NullOK);
2085 const Type *TargetType);
2109 if (Ptr.canBeInitialized())
2116 if (Ptr.canBeInitialized())
2123 if (Ptr.canBeInitialized()) {
2132 if (Ptr.canBeInitialized()) {
2150 diag::note_constexpr_dereferencing_null);
2158 if (!Ptr.isBlockPointer())
2160 if (!Ptr.getFieldDesc()->isRecord())
2163 const Record::Base *VirtBase =
Base.getRecord()->findVirtualBase(
Decl);
2202template <PrimType Name, class T = typename PrimConv<Name>::T>
2207 if (!Ptr.isReadablePointerType())
2209 if (!Ptr.canDeref(Name))
2215template <PrimType Name, class T = typename PrimConv<Name>::T>
2220 if (!Ptr.isReadablePointerType())
2222 if (!Ptr.canDeref(Name))
2235 bool Failed =
false;
2238 if (!Ptr.isBlockPointer())
2240 if (!Failed && !Ptr.canDeref(
PT_Ptr))
2245 if (Ptr.isOpaquePointer()) {
2248 if (!Ptr.asOpaquePointer().Base->getType()->isPointerType())
2253 Ptr.getByteOffset());
2258 if (!Ptr.isBlockPointer())
2268template <PrimType Name, class T = typename PrimConv<Name>::T>
2274 if (!Ptr.canDeref(Name))
2276 if (Ptr.canBeInitialized())
2282template <PrimType Name, class T = typename PrimConv<Name>::T>
2288 if (!Ptr.canDeref(Name))
2290 if (Ptr.canBeInitialized())
2298 if (Ptr.canBeInitialized())
2310 assert(Ptr.atField(I).canBeInitialized());
2311 Ptr.atField(I).activate();
2315template <PrimType Name, class T = typename PrimConv<Name>::T>
2322 if (Ptr.canBeInitialized()) {
2330template <PrimType Name, class T = typename PrimConv<Name>::T>
2337 if (Ptr.canBeInitialized()) {
2345template <PrimType Name, class T = typename PrimConv<Name>::T>
2352 if (Ptr.canBeInitialized())
2354 if (
const auto *FD = Ptr.getField())
2355 Ptr.deref<
T>() =
Value.truncate(FD->getBitWidthValue());
2361template <PrimType Name, class T = typename PrimConv<Name>::T>
2367 if (Ptr.canBeInitialized())
2369 if (
const auto *FD = Ptr.getField())
2370 Ptr.deref<
T>() =
Value.truncate(FD->getBitWidthValue());
2376template <PrimType Name, class T = typename PrimConv<Name>::T>
2383 if (Ptr.canBeInitialized()) {
2387 if (
const auto *FD = Ptr.getField())
2388 Ptr.deref<
T>() =
Value.truncate(FD->getBitWidthValue());
2394template <PrimType Name, class T = typename PrimConv<Name>::T>
2401 if (Ptr.canBeInitialized()) {
2405 if (
const auto *FD = Ptr.getField())
2406 Ptr.deref<
T>() =
Value.truncate(FD->getBitWidthValue());
2412template <PrimType Name, class T = typename PrimConv<Name>::T>
2419 new (&Ptr.deref<
T>())
T(
Value);
2423template <PrimType Name, class T = typename PrimConv<Name>::T>
2430 new (&Ptr.deref<
T>())
T(
Value);
2437template <PrimType Name, class T = typename PrimConv<Name>::T>
2442 if (Ptr.isConstexprUnknown())
2451 if (Idx == 0 && !Desc->
isArray()) {
2453 new (&Ptr.deref<
T>())
T(
Value);
2463 S.
FFDiag(Loc, diag::note_constexpr_access_past_end)
2468 Ptr.initializeElement(Idx);
2469 new (&Ptr.elem<
T>(Idx))
T(
Value);
2474template <PrimType Name, class T = typename PrimConv<Name>::T>
2479 if (Ptr.isConstexprUnknown())
2488 if (Idx == 0 && !Desc->
isArray()) {
2490 new (&Ptr.deref<
T>())
T(
Value);
2500 S.
FFDiag(Loc, diag::note_constexpr_access_past_end)
2505 Ptr.initializeElement(Idx);
2506 new (&Ptr.elem<
T>(Idx))
T(
Value);
2519 return DoMemcpy(S, OpPC, Src, Dest);
2533 if (std::optional<Pointer> Ptr = MP.toPointer(S.
Ctx)) {
2544template <
class T, ArithOp Op>
2546 const T &Offset,
const Pointer &Ptr,
2547 bool IsPointerArith =
false) {
2549 if (Offset.isZero())
2556 return std::nullopt;
2561 return std::nullopt;
2564 if (Ptr.isIntegralPointer()) {
2565 uint64_t
V = Ptr.getIntegerRepresentation();
2566 QualType ElemType = Ptr.asIntPointer().getPointeeType();
2571 uint64_t O =
static_cast<uint64_t
>(Offset) * ElemSize;
2573 return Pointer(
V + O, Ptr.asIntPointer().Ty);
2575 return Pointer(
V - O, Ptr.asIntPointer().Ty);
2576 }
else if (Ptr.isFunctionPointer()) {
2577 uint64_t O =
static_cast<uint64_t
>(Offset);
2580 N = Ptr.getByteOffset() + O;
2582 N = Ptr.getByteOffset() - O;
2587 return Pointer(Ptr.asFunctionPointer().Func, N);
2588 }
else if (Ptr.isStringPointer()) {
2591 NewOffset = Ptr.getRawOffset() +
static_cast<int64_t
>(Offset);
2593 NewOffset = Ptr.getRawOffset() -
static_cast<int64_t
>(Offset);
2594 if (NewOffset < 0 ||
2595 NewOffset > (Ptr.asStringPointer().getLiteral()->getLength() + 1)) {
2597 << NewOffset <<
false
2598 << (Ptr.asStringPointer().getLiteral()->getLength() + 1);
2599 return std::nullopt;
2601 return Pointer(Ptr.asStringPointer(), NewOffset);
2602 }
else if (!Ptr.isBlockPointer()) {
2603 return std::nullopt;
2606 assert(Ptr.isBlockPointer());
2608 uint64_t MaxIndex =
static_cast<uint64_t
>(Ptr.getNumElems());
2610 if (Ptr.isOnePastEnd())
2613 Index = Ptr.getIndex();
2617 auto DiagInvalidOffset = [&]() ->
void {
2618 const unsigned Bits = Offset.bitWidth();
2619 APSInt APOffset(Offset.toAPSInt().extend(
Bits + 2),
false);
2623 (Op ==
ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
2625 << NewIndex <<
static_cast<int>(!Ptr.inArray()) << MaxIndex;
2629 uint64_t IOffset =
static_cast<uint64_t
>(Offset);
2630 uint64_t MaxOffset = MaxIndex - Index;
2634 if (Offset.isNegative() && (Offset.isMin() || -IOffset > Index))
2635 DiagInvalidOffset();
2638 if (Offset.isPositive() && IOffset > MaxOffset)
2639 DiagInvalidOffset();
2642 if (Offset.isPositive() && Index < IOffset)
2643 DiagInvalidOffset();
2646 if (Offset.isNegative() && (Offset.isMin() || -IOffset > MaxOffset))
2647 DiagInvalidOffset();
2651 return std::nullopt;
2654 int64_t WideIndex =
static_cast<int64_t
>(Index);
2655 int64_t WideOffset =
static_cast<int64_t
>(Offset);
2658 Result = WideIndex + WideOffset;
2660 Result = WideIndex - WideOffset;
2665 if (
Result == 0 && Ptr.isOnePastEnd()) {
2666 if (Ptr.getFieldDesc()->isArray())
2667 return Ptr.atIndex(0);
2668 return Pointer(Ptr.asBlockPointer().Pointee, Ptr.asBlockPointer().Base);
2671 return Ptr.atIndex(
static_cast<uint64_t
>(
Result));
2675 const Pointer &Ptr, APSInt &&Offset,
2677template <PrimType Name, class T = typename PrimConv<Name>::T>
2682 if (Ptr.isOpaquePointer()) {
2683 if (std::optional<Pointer>
Result =
2692 S, OpPC, Offset, Ptr,
true)) {
2699template <PrimType Name, class T = typename PrimConv<Name>::T>
2704 if (Ptr.isOpaquePointer()) {
2705 if (std::optional<Pointer>
Result =
2714 S, OpPC, Offset, Ptr,
true)) {
2722 bool ConstexprUnknown) {
2727template <ArithOp Op>
2730 if (!Ptr.isDereferencable())
2743 if (std::optional<Pointer>
Result =
2752 OneT One = OneT::from(1);
2753 if (std::optional<Pointer>
Result =
2765 if (!Ptr.isInitialized())
2774 if (!Ptr.isInitialized())
2783template <PrimType Name, class T = typename PrimConv<Name>::T>
2792 if (!LHSAddrExpr || !RHSAddrExpr) {
2794 diag::note_constexpr_pointer_arith_unspecified)
2804 S.
Stk.
push<
T>(LHSAddrExpr, RHSAddrExpr);
2813 diag::note_constexpr_pointer_arith_unspecified)
2819 if (ElemSize == 0) {
2824 diag::note_constexpr_pointer_subtraction_zero_size)
2841 diag::note_constexpr_pointer_subtraction_not_same_array);
2850 assert(((int64_t)*VL - (int64_t)*VR) % ElemSize == 0);
2852 (
static_cast<int64_t
>(*VL) -
static_cast<int64_t
>(*VR)) / ElemSize;
2853 if (
static_cast<int64_t
>(T::from(R64)) != R64)
2899 if (!(U::bitWidth() >= 32 && U::bitWidth() <= In.bitWidth()))
2911 llvm::RoundingMode RM) {
2921 FixedPointSemantics::getFromOpaqueInt(FPS);
2936template <PrimType Name, class T = typename PrimConv<Name>::T>
2941 if (!Source.isNumber())
2948 APInt SourceInt = Source.toAPSInt().extOrTrunc(BitWidth);
2955template <PrimType Name, class T = typename PrimConv<Name>::T>
2960 if (!Source.isNumber())
2967 APInt SourceInt = Source.toAPSInt().extOrTrunc(BitWidth);
2977template <PrimType Name, class T = typename PrimConv<Name>::T>
2980 APSInt Val = Source.toAPSInt();
2981 if (Val.isNegative() || Val.getActiveBits() > 63)
2988template <PrimType Name, class T = typename PrimConv<Name>::T>
2990 const llvm::fltSemantics *Sem, uint32_t FPOI) {
2994 if (!From.isNumber())
2998 APSInt FromAP = From.toAPSInt();
3009template <PrimType Name, class T = typename PrimConv<Name>::T>
3013 if constexpr (std::is_same_v<T, Boolean>) {
3022 if ((Status & APFloat::opStatus::opInvalidOp)) {
3041 const Pointer &Ptr,
unsigned BitWidth);
3046template <PrimType Name, class T = typename PrimConv<Name>::T>
3052 if constexpr (std::is_same_v<T, Boolean>) {
3053 S.
Stk.
push<
T>(T::from(Ptr.getIntegerRepresentation()));
3055 if (Ptr.isBlockPointer()) {
3058 if (Ptr.isDummy()) {
3059 if (
const Expr *E = Ptr.getRootExpr()) {
3064 PtrVal = Ptr.getDeclDesc()->asDecl();
3067 PtrVal = Ptr.block();
3071 }
else if (Ptr.isFunctionPointer()) {
3072 const void *FuncDecl = Ptr.asFunctionPointer().Func->getDecl();
3074 }
else if (Ptr.isStringPointer()) {
3076 (
const void *)Ptr.asStringPointer().getLiteral(), 0);
3078 S.
Stk.
push<
T>(T::from(Ptr.getIntegerRepresentation()));
3081 S.
Stk.
push<
T>(T::from(Ptr.getIntegerRepresentation()));
3086template <PrimType Name, class T = typename PrimConv<Name>::T>
3120 const llvm::fltSemantics *Sem) {
3123 Result.copy(Fixed.toFloat(Sem));
3128template <PrimType Name, class T = typename PrimConv<Name>::T>
3133 APSInt Int = Fixed.toInt(T::bitWidth(), T::isSigned(), &Overflow);
3144 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
3145 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3154 bool HasValidResult = !Ptr.isZero();
3156 if (HasValidResult) {
3163 E->getType()->getPointeeType()))
3166 S.
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
3167 << E->getSubExpr()->getType() << S.
getLangOpts().CPlusPlus26
3168 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
3171 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
3172 << diag::ConstexprInvalidCastKind::CastFrom <<
"'void *'"
3177 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
3178 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3189template <PrimType Name, class T = typename PrimConv<Name>::T>
3197 if (!
Result.singleWord())
3198 std::memset(
Result.Memory, 0,
Result.numWords() *
sizeof(uint64_t));
3205 if (!
Result.singleWord())
3206 std::memset(
Result.Memory, 0,
Result.numWords() *
sizeof(uint64_t));
3211template <PrimType Name, class T = typename PrimConv<Name>::T>
3219template <PrimType Name, class T = typename PrimConv<Name>::T>
3221 const auto &P = S.
Stk.
pop<
T>();
3241 if (!
This.isDummy()) {
3243 if (!
This.isTypeidPointer()) {
3244 [[maybe_unused]]
const Record *R =
This.getRecord();
3246 R =
This.narrow().getRecord();
3249 assert(R->getDecl() ==
3271template <
class LT,
class RT, ShiftDir Dir>
3275 const unsigned Bits = LHS.bitWidth();
3279 RT::bitAnd(RHS, RT::from(LHS.bitWidth() - 1, RHS.bitWidth()),
3280 RHS.bitWidth(), &RHS);
3282 if (RHS.isNegative()) {
3286 S.
CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
3290 RHS = RHS.isMin() ? RT(APSInt::getMaxValue(RHS.bitWidth(),
false)) : -RHS;
3294 S, OpPC, LHS, RHS,
Result);
3306 typename LT::AsUnsigned R;
3307 unsigned MaxShiftAmount = LHS.bitWidth() - 1;
3309 if (
Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
3311 if (LHS.isNegative())
3312 R = LT::AsUnsigned::zero(LHS.bitWidth());
3314 RHS = RT::from(LHS.countLeadingZeros(), RHS.bitWidth());
3315 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
3316 LT::AsUnsigned::from(RHS,
Bits),
Bits, &R);
3318 }
else if (LHS.isNegative()) {
3320 R = LT::AsUnsigned::zero(LHS.bitWidth());
3323 typename LT::AsUnsigned LHSU = LT::AsUnsigned::from(-LHS);
3324 LT::AsUnsigned::shiftLeft(LHSU, LT::AsUnsigned::from(RHS,
Bits),
Bits,
3330 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
3331 LT::AsUnsigned::from(RHS,
Bits),
Bits, &R);
3338 if (
Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
3340 R = LT::AsUnsigned::from(0);
3344 LT::shiftRight(LHS, LT::from(RHS,
Bits),
Bits, &A);
3345 R = LT::AsUnsigned::from(A);
3353template <
class LT,
class RT, ShiftDir Dir>
3356 const unsigned Bits = LHS.getBitWidth();
3361 APSInt(llvm::APInt(RHS.getBitWidth(),
static_cast<uint64_t
>(
Bits - 1)),
3364 if (RHS.isNegative()) {
3368 S.
CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS;
3373 S, OpPC, LHS, -(RHS.extend(RHS.getBitWidth() + 1)),
Result);
3397template <PrimType NameL, PrimType NameR>
3401 auto RHS = S.
Stk.
pop<RT>();
3409 RHS.toAPSInt(), &
Result);
3416template <PrimType NameL, PrimType NameR>
3420 auto RHS = S.
Stk.
pop<RT>();
3428 RHS.toAPSInt(), &
Result);
3438 llvm::FixedPointSemantics LHSSema = LHS.
getSemantics();
3440 unsigned ShiftBitWidth =
3441 LHSSema.getWidth() - (
unsigned)LHSSema.hasUnsignedPadding() - 1;
3446 if (RHS.isNegative()) {
3449 }
else if (
static_cast<unsigned>(RHS.toAPSInt().getLimitedValue(
3450 ShiftBitWidth)) != RHS.toAPSInt()) {
3452 S.
CCEDiag(E, diag::note_constexpr_large_shift)
3453 << RHS.toAPSInt() << E->
getType() << ShiftBitWidth;
3476 S.
FFDiag(EndLoc, diag::note_constexpr_no_return);
3492 if (Ptr.isBlockPointer())
3500 APSInt &&Index,
bool AllowReplace =
true);
3503template <
typename T>
3506 if (Ptr.isOpaquePointer())
3509 if (Offset.isZero()) {
3510 if (
const Descriptor *Desc = Ptr.getFieldDesc();
3511 Desc && Desc->isArray() && Ptr.getIndex() == 0) {
3519 assert(!Offset.isZero());
3521 if (std::optional<Pointer>
Result =
3537template <PrimType Name, class T = typename PrimConv<Name>::T>
3545template <PrimType Name, class T = typename PrimConv<Name>::T>
3553template <PrimType Name, class T = typename PrimConv<Name>::T>
3560 assert(Ptr.atIndex(Index).getFieldDesc()->getPrimType() == Name);
3565template <PrimType Name, class T = typename PrimConv<Name>::T>
3572 assert(Ptr.atIndex(Index).getFieldDesc()->getPrimType() == Name);
3577template <PrimType Name, class T = typename PrimConv<Name>::T>
3579 uint32_t DestIndex, uint32_t Size) {
3583 if (SrcPtr.isDummy() || DestPtr.
isDummy())
3589 const Descriptor *SrcDesc = SrcPtr.getFieldDesc();
3595 for (uint32_t I = 0; I != Size; ++I) {
3601 DestPtr.
elem<
T>(DestIndex + I) = SrcPtr.elem<
T>(SrcIndex + I);
3617 if (!Ptr.isZeroSizeArray()) {
3623 if (Ptr.isBlockPointer()) {
3628 if (Ptr.isStringPointer()) {
3633 if (!Ptr.isOpaquePointer()) {
3638 if (!Ptr.getType()->isArrayType()) {
3643 APSInt(APInt::getZero(1),
true),
3648 diag::note_constexpr_unsupported_unsized_array);
3658template <PrimType Name, class T = typename PrimConv<Name>::T>
3663 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3668 if (IntVal.getOffset() != 0)
3674 if (IntVal.getOffset() != 0)
3677 const Block *B = (
const Block *)IntVal.getPtr();
3708 S.
FFDiag(Loc, diag::note_constexpr_stmt_expr_unsupported)
3806 diag::note_constexpr_access_volatile_type)
3818 S.
CCEDiag(E, diag::note_constexpr_non_const_vectorelements) << ArgRange;
3826 diag::note_constexpr_pseudo_destructor);
3838 S.
CCEDiag(Loc, diag::note_constexpr_assumption_failed);
3842template <PrimType Name, class T = typename PrimConv<Name>::T>
3846 ArrayIndices.emplace_back(
3858template <PrimType Name, class T = typename PrimConv<Name>::T>
3865 S.
CCEDiag(Loc, diag::note_non_null_attribute_failed);
3871 const APSInt &
Value);
3873template <PrimType Name, class T = typename PrimConv<Name>::T>
3891 const FromT &OldPtr = S.
Stk.
pop<FromT>();
3893 if constexpr (std::is_same_v<FromT, FunctionPointer> &&
3894 std::is_same_v<ToT, Pointer>) {
3897 }
else if constexpr (std::is_same_v<FromT, Pointer> &&
3898 std::is_same_v<ToT, FunctionPointer>) {
3899 if (OldPtr.isFunctionPointer()) {
3901 OldPtr.getByteOffset());
3906 S.
Stk.
push<ToT>(ToT(OldPtr.getIntegerRepresentation(),
nullptr));
3936 if (!Ptr.isUnknownSizeArray() && NumElems > Ptr.getNumElems()) {
3938 << Ptr.getNumElems() << NumElems;
3959template <PrimType Name, class SizeT = typename PrimConv<Name>::T>
3974 if (NumElements.isNegative()) {
3984 if (!
CheckArraySize(S, OpPC,
static_cast<uint64_t
>(NumElements)))
3988 Block *B = Allocator.
allocate(Source,
T,
static_cast<size_t>(NumElements),
3991 if (NumElements.isZero())
3998template <PrimType Name, class SizeT = typename PrimConv<Name>::T>
4017 if (NumElements.isNegative()) {
4027 if (!
CheckArraySize(S, OpPC,
static_cast<uint64_t
>(NumElements)))
4031 Block *B = Allocator.
allocate(ElementDesc,
static_cast<size_t>(NumElements),
4034 if (NumElements.isZero())
4042bool Free(InterpState &S, CodePtr OpPC,
bool DeleteIsArrayForm,
4043 bool IsGlobalDelete);
4057 std::optional<uint64_t> ArraySize = std::nullopt);
4059template <PrimType Name, class T = typename PrimConv<Name>::T>
4061 const auto &Size = S.
Stk.
pop<
T>();
4066template <PrimType Name, class T = typename PrimConv<Name>::T>
4068 uint32_t ResultBitWidth,
const llvm::fltSemantics *Sem,
4069 const Type *TargetType) {
4075 if constexpr (std::is_same_v<T, Pointer>) {
4078 diag::note_constexpr_bit_cast_invalid_type)
4079 <<
true <<
false << 1 ;
4085 }
else if constexpr (std::is_same_v<T, MemberPointer>) {
4087 diag::note_constexpr_bit_cast_invalid_type)
4088 <<
true <<
false << 2 ;
4092 size_t BuffSize = ResultBitWidth / 8;
4094 bool HasIndeterminateBits =
false;
4096 Bits FullBitWidth(ResultBitWidth);
4097 Bits BitWidth = FullBitWidth;
4099 if constexpr (std::is_same_v<T, Floating>) {
4101 BitWidth =
Bits(llvm::APFloatBase::getSizeInBits(*Sem));
4104 if (!
DoBitCast(S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth,
4105 HasIndeterminateBits))
4108 if (!
CheckBitCast(S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte))
4111 if constexpr (std::is_same_v<T, Floating>) {
4118 T::bitcastFromMemory(Buff.data(), ResultBitWidth, &
Result);
4120 }
else if constexpr (std::is_same_v<T, Boolean>) {
4124 auto Val =
static_cast<unsigned int>(Buff[0]);
4127 diag::note_constexpr_bit_cast_unrepresentable_value)
4131 S.
Stk.
push<
T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
4134 S.
Stk.
push<
T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
4145 if (D->isPrimitiveArray() && FromPtr.
isArrayRoot())
4160bool DiagTypeid(InterpState &S, CodePtr OpPC);
4177 if constexpr (std::is_pointer<T>::value)
4180 return OpPC.
read<
T>();
4189 OpPC +=
align(F.bytesToSerialize());
4198 assert(
Result.bitWidth() == BitWidth);
4210 assert(
Result.bitWidth() == BitWidth);
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)
Result
Implement __builtin_bit_cast and related operations.
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.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
bool hasSimilarType(QualType T1, QualType T2) const
Determine if two types are similar, according to the C++ rules.
AddrLabelExpr - The GNU address of label extension, representing &&label.
LabelDecl * getLabel() const
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
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.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
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
DeclContext * getDeclContext()
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.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType withVolatile() const
bool isWrapType() const
Returns true if it is a OverflowBehaviorType of Wrap kind.
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...
The base class of the type hierarchy.
bool isNullPtrType() 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.
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.
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 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)
Wrapper around numeric types.
static std::enable_if_t<!std::is_same_v< ValT, IntegralKind >, Integral > from(ValT V, unsigned NumBits=0)
Frame storing local variables.
SourceLocation getLocation(CodePtr PC) const
static void free(InterpFrame *F)
bool isLocalEnabled(unsigned Idx) const
void setParam(unsigned Index, const T &Value)
Mutates a local copy of a parameter.
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.
SourceRange getRange(CodePtr PC) const
void enableLocal(unsigned Idx)
Block * getLocalBlock(unsigned Offset) const
const Pointer & getThis() const
Returns the 'this' pointer.
unsigned MSVCConstexprAllowed
const Function * getFunction() const
Returns the current function.
size_t getFrameOffset() const
Returns the offset on the stack at which the frame starts.
void setLocal(unsigned Offset, const T &Value)
Mutates a local variable.
bool isBottomFrame() const
bool hasThisPointer() const
Pointer getLocalPointer(unsigned Offset) const
Returns a pointer to a local variables.
const Expr * getExpr(CodePtr PC) const
const T & getParam(unsigned Index) const
Returns the value of an argument.
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.
DynamicAllocator & getAllocator()
Context & Ctx
Interpreter Context.
Floating allocFloat(const llvm::fltSemantics &Sem)
const unsigned EvalID
ID identifying this evaluation.
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.
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
InterpFrame * Current
The current frame.
std::optional< bool > ConstantContextOverride
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.
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.
bool pointsToLabel() const
Whether this points to a block created for an AddrLabelExpr.
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
bool isDummy() const
Checks if the pointer points to a dummy value.
const AddrLabelExpr * getPointedToLabel() const
Returns the AddrLabelExpr the Pointer points to, if any.
bool isOpaquePointer() const
bool isStringPointer() const
Pointer atField(unsigned Off) const
Creates a pointer to a field.
T & deref() const
Dereferences the pointer, if it's live.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
QualType getType() const
Returns the type of the innermost field.
void initialize() const
Initializes a field.
std::optional< size_t > computeOffsetForComparison(const ASTContext &ASTCtx) const
Compute an integer that can be used to compare this pointer to another one.
bool isArrayRoot() const
Whether this array refers to an array, but not to the first element.
static bool elemsOfSameArray(const Pointer &A, const Pointer &B)
Checks if two pointers can be subtracted.
T & elem(unsigned I) const
Dereferences the element at index I.
std::optional< size_t > computeLayoutOffset(const ASTContext &ASTCtx) const
Compute the pointer offset as given by the ASTRecordLayout.
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.
bool isConstexprUnknown() const
bool isOnePastEnd() const
Checks if the index is one past end.
uint64_t getIntegerRepresentation() const
bool isBlockPointer() const
void initializeElement(unsigned Index) const
Initialized the given element of a primitive array.
bool isFunctionPointer() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
bool isBaseClass() const
Checks if a structure is a base class.
static std::optional< std::pair< PtrView, PtrView > > computeSplitPoint(const Pointer &A, const Pointer &B)
const Record * getRecord() const
Returns the record descriptor of a class.
Function * getFunction(const FunctionDecl *F)
Returns a function.
Block * getGlobal(unsigned Idx)
Returns the value of a global.
UnsignedOrNone getOrCreateGlobal(const ValueDecl *VD, const Expr *Init=nullptr)
Returns or creates a global an creates an index to it.
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
Structure/Class descriptor.
bool isAnonymousUnion() const
Checks if the record is an anonymous union.
Describes the statement/declaration an opcode was generated from.
bool checkingForUndefinedBehavior() const
Are we checking an expression for overflow?
Expr::EvalStatus & getEvalStatus() const
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)
bool noteSideEffect() const
Note that we have had a side-effect, and determine whether we should keep evaluating.
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?
bool arePotentiallyOverlappingStringLiterals(const Pointer &LHS, const Pointer &RHS)
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a field from which a pointer is going to be derived is valid.
static bool ShiftFixedPoint(InterpState &S, CodePtr OpPC, bool Left)
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.
bool InitPop(InterpState &S, CodePtr OpPC)
bool Shr(InterpState &S, CodePtr OpPC)
bool CheckDestruction(InterpState &S, CodePtr OpPC)
bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index)
bool Flip(InterpState &S)
[Value1, Value2] -> [Value2, Value1]
bool GetTypeid(InterpState &S, const Type *TypePtr, const Type *TypeInfoType)
Typeid support.
bool GetLocalEnabled(InterpState &S, uint32_t I)
bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool CastAPToOffsetIndex(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.
bool GetPtrParam(InterpState &S, uint32_t Index)
bool arrayElemPtrOpaque(InterpState &S, CodePtr OpPC, const Pointer &Ptr, APSInt &&Index, bool AllowReplace)
bool GetThisField(InterpState &S, CodePtr OpPC, uint32_t I)
bool PushCC(InterpState &S, bool Value)
bool PreInc(InterpState &S, CodePtr OpPC, bool CanOverflow)
bool CheckFunctionDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *FD)
Opcode. Check if the function decl can be called at compile time.
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)
std::optional< Pointer > addSubOffsetOpaque(InterpState &S, CodePtr OpPC, const Pointer &Ptr, APSInt &&Offset, ArithOp Op)
bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue)
Floating ReadArg< Floating >(InterpState &S, CodePtr &OpPC)
bool GetPtrLocal(InterpState &S, uint32_t I)
bool Incf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS, LT *Result)
bool StartThisLifetime(InterpState &S)
void cleanupAfterFunctionCall(InterpState &S, const Function *Func)
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc, AccessKinds AK)
Checks if the Descriptor is of a constexpr or const global variable.
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 SubPtr(InterpState &S, CodePtr OpPC, uint32_t ElemSize)
1) Pops a Pointer from the stack.
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.
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.
PRESERVE_NONE bool NoRet(InterpState &S)
bool InitBitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t FieldOffset, uint32_t FieldBitWidth)
bool CtorCheck(InterpState &S)
Abort without a diagnostic if we're checking for a potential constant expression and this is not the ...
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}...
bool CastMemberPtrDerivedPop(InterpState &S, int32_t Off, const RecordDecl *BaseDecl)
BaseToDerivedMemberPointer.
bool InitBitField(InterpState &S, CodePtr OpPC, uint32_t FieldOffset, uint32_t FieldBitWidth)
static bool IncDecPtrHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
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.
static bool IsOpaqueConstantCall(const CallExpr *E)
bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, unsigned BitWidth)
bool CheckDecl(InterpState &S, const VarDecl *VD)
bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS, const T &RHS)
bool EnableLocal(InterpState &S, uint32_t I)
bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off)
1) Peeks a Pointer 2) Pushes Pointer.atField(Off) on the stack
static bool CheckAllocations(InterpState &S)
bool StoreActivate(InterpState &S, CodePtr OpPC)
bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK, bool WillActivate)
bool Div(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
PRESERVE_NONE bool Ret(InterpState &S)
bool InitThisBitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t FieldOffset, uint32_t FieldBitWidth)
bool GetIntPtr(InterpState &S, CodePtr OpPC, const Type *Ty)
bool BitOr(InterpState &S)
1) Pops the RHS from the stack.
static bool CastFixedPointFloating(InterpState &S, const llvm::fltSemantics *Sem)
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 handleFixedPointOverflow(InterpState &S, CodePtr OpPC, const FixedPoint &FP)
bool PopIgnoreDiags(InterpState &S)
constexpr bool isIntegralOrPointer()
bool ArrayElemPtr(InterpState &S, CodePtr OpPC)
bool GetMemberPtrDecl(InterpState &S)
bool NE(InterpState &S, CodePtr OpPC)
bool handleReference(InterpState &S, CodePtr OpPC, Block *B)
bool StartSpeculation(InterpState &S)
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.
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 ZeroIntAPS(InterpState &S, uint32_t BitWidth)
bool Shl(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 CheckBCPResult(InterpState &S, const Pointer &Ptr)
bool SetLocal(InterpState &S, uint32_t I)
1) Pops the value from the stack.
PRESERVE_NONE bool EndSpeculation(InterpState &S)
bool diagnoseShiftFailure(InterpState &S, CodePtr OpPC, ShiftFailure Failure, const APSInt *Value, unsigned Bits)
bool GetFnPtr(InterpState &S, const Function *Func)
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 FinishInitActivate(InterpState &S)
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 LoadPopL(InterpState &S, CodePtr OpPC)
Like LoadPop above, but if any of the checks fail, we turn the pointer into an opaque pointer of appr...
bool Dump(InterpState &S)
bool FinishInitPop(InterpState &S)
bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn)
bool InitScope(InterpState &S, uint32_t I)
T ReadArg(InterpState &S, CodePtr &OpPC)
bool CastFP(InterpState &S, const llvm::fltSemantics *Sem, llvm::RoundingMode RM)
1) Pops a Floating from the stack.
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 GetStringPtr(InterpState &S, const Expr *Base)
bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK, const Type *TargetType)
bool DiagTypeid(InterpState &S, CodePtr OpPC)
bool diagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
This is not used by any of the opcodes directly.
bool InitGlobalTempComp(InterpState &S, const LifetimeExtendedTemporaryDecl *Temp)
1) Converts the value on top of the stack to an APValue 2) Sets that APValue on \Temp 3) Initialized ...
bool CheckRefInit(InterpState &S, CodePtr OpPC)
bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I)
bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E)
bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS, unsigned Bits)
Checks if the shift operation is legal.
bool SetParam(InterpState &S, uint32_t I)
FixedPoint ReadArg< FixedPoint >(InterpState &S, CodePtr &OpPC)
bool IsNonNull(InterpState &S)
static bool CastFloatingFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS)
void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED, const APSInt &Value)
@ BlockAddress
A pointer to an interp::Block.
@ AddrLabelDiff
Difference between two AddrLabelExpr.
@ Number
Just a number, nothing else.
@ ExprAddress
A pointer to an Expr.
@ Address
A pointer to a ValueDecl.
@ LabelAddress
A pointer to a AddrLabelExpr.
@ FunctionAddress
A pointer to a FunctionDecl.
bool LE(InterpState &S, CodePtr OpPC)
bool isConstexprUnknown(const Block *B)
bool CheckNewTypeMismatchArray(InterpState &S, CodePtr OpPC, const Expr *E)
bool StartThisLifetime1(InterpState &S)
bool RVOPtr(InterpState &S)
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.
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 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)
bool GetOpaquePtr(InterpState &S, const ValueDecl *VD, bool ConstexprUnknown)
constexpr bool needsAlloc()
bool CastAPS(InterpState &S, uint32_t BitWidth)
bool Alloc(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index)
bool arrayElemPtr(InterpState &S, CodePtr OpPC, const Pointer &Ptr, const T &Offset)
static bool CastIntegralFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS)
bool Rem(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool ExpandPtr(InterpState &S)
bool NarrowPtr(InterpState &S)
bool InitGlobalTemp(InterpState &S, 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 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 Mulc(InterpState &S)
bool checkDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
bool InitThisBitField(InterpState &S, CodePtr OpPC, uint32_t FieldOffset, uint32_t FieldBitWidth)
bool SizelessVectorElementSize(InterpState &S, CodePtr OpPC)
static bool Activate(InterpState &S)
static bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr)
bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T)
bool SideEffect(InterpState &S)
bool BitAnd(InterpState &S)
1) Pops the RHS from the stack.
bool GetRefGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool EndInit(InterpState &S)
PRESERVE_NONE bool RetVoid(InterpState &S)
bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off)
bool Comp(InterpState &S)
1) Pops the value from the stack.
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 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 CastAP(InterpState &S, uint32_t BitWidth)
Like Cast(), but we cast to an arbitrary-bitwidth integral, so we need to know what bitwidth the resu...
bool IncBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, unsigned BitWidth)
bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off)
bool StoreActivatePop(InterpState &S, CodePtr OpPC)
bool Null(InterpState &S, uint64_t Value, const Type *Ty)
bool StartInit(InterpState &S)
bool Divf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
bool GetRefLocal(InterpState &S, CodePtr OpPC, uint32_t I)
bool CheckThis(InterpState &S, CodePtr OpPC)
Checks the 'this' pointer.
static bool ActivateThisField(InterpState &S, uint32_t I)
bool Const(InterpState &S, const T &Arg)
bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth, uint32_t FPOI)
bool GetPtrVirtBasePop(InterpState &S, CodePtr OpPC, const RecordDecl *D)
bool StorePop(InterpState &S, CodePtr OpPC)
bool CheckIntegralAddressCast(InterpState &S, CodePtr OpPC, unsigned BitWidth)
bool InvalidStore(InterpState &S, CodePtr OpPC, const Type *T)
bool ConstFloat(InterpState &S, const Floating &F)
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)
static bool IsConstantContext(InterpState &S)
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 ToMemberPtr(InterpState &S)
bool GetPtrVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D)
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 BitXor(InterpState &S)
1) Pops the RHS from the stack.
bool CheckPseudoDtor(InterpState &S, CodePtr OpPC)
bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm, bool IsGlobalDelete)
bool IsBaseClass(InterpState &S)
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 InitGlobal(InterpState &S, uint32_t I)
bool CheckArrayDestSize(InterpState &S, CodePtr OpPC, size_t NumElems)
Check if the destination array we're initializing can hold the NumElems elements.
bool CallBI(InterpState &S, CodePtr OpPC, const CallExpr *CE, uint32_t BuiltinID)
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B)
bool Neg(InterpState &S, CodePtr OpPC)
bool DecayPtr(InterpState &S)
OldPtr -> Integer -> NewPtr.
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 FinishInit(InterpState &S)
llvm::function_ref< bool(ComparisonCategoryResult)> CompareFn
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 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 FinishInitGlobal(InterpState &S)
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 DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest)
Copy the contents of Src into Dest.
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 ...
constexpr bool isIntegerType(PrimType T)
static bool AddSubNonNumber(InterpState &S, CodePtr OpPC, T LHS, T RHS)
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)
bool PushMSVCCE(InterpState &S)
bool CastFloatingIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth, uint32_t FPOI)
static bool CastFixedPointIntegral(InterpState &S, CodePtr OpPC)
bool MarkDestroyed(InterpState &S, CodePtr OpPC)
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 PopMSVCCE(InterpState &S)
bool CastFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS)
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 GetMemberPtr(InterpState &S, const ValueDecl *D)
bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D)
bool CastMemberPtrBasePop(InterpState &S, int32_t Off, const RecordDecl *BaseDecl)
DerivedToBaseMemberPointer.
bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, bool Fatal)
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 VirtBaseHelper(InterpState &S, const RecordDecl *Decl, const Pointer &Ptr)
bool InitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t I)
bool IncPopBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, uint32_t BitWidth)
bool CMP3(InterpState &S, CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo)
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 PopCC(InterpState &S)
bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off)
bool GetParam(InterpState &S, uint32_t Index)
bool GetPtrGlobal(InterpState &S, uint32_t I)
bool FinishInitActivatePop(InterpState &S)
bool DynamicCast(InterpState &S, CodePtr OpPC, const Type *DestTypePtr, bool IsReferenceCast)
bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t FPOI)
bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source, bool IsNoThrow)
bool CheckEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED)
static bool ZeroIntAP(InterpState &S, uint32_t BitWidth)
Top level wrappers for InstallAPI frontend operations.
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.
OptionalUnsigned< unsigned > UnsignedOrNone
const FunctionProtoType * T
@ Off
Never emit colors regardless of the output stream.
@ ConstantFold
Fold the expression to a constant.
U cast(CodeGen::Address addr)
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
bool DiagEmitted
Whether any diagnostic has been emitted.
size_t getQuantity() const
Describes a memory block created by an allocation site.
unsigned getNumElems() const
Returns the number of elements stored in the block.
unsigned getSize() const
Returns the size of the object without metadata.
bool isUnknownSizeArray() const
Checks if the descriptor is of an array of unknown size.
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.
bool isArray() const
Checks if the descriptor is of an array.
Descriptor used for global variables.
OpaquePointer withFieldType(const Type *FieldTy, std::optional< bool > PastEnd=std::nullopt) const
Mapping from primitive types to their representation.