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/ADT/ScopeExit.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;
93 bool WillBeActivated =
false);
119 uint32_t VarArgSize);
121 uint32_t VarArgSize);
123 uint32_t VarArgSize);
131 bool TargetIsUCharOrByte);
147 bool IsReferenceCast);
152template <ShiftDir Dir,
typename LT,
typename RT>
155 if (RHS.isNegative()) {
157 S.
CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
166 const APSInt Val = RHS.toAPSInt();
168 S.
CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty <<
Bits;
174 if (LHS.isSigned() && !S.
getLangOpts().CPlusPlus20) {
177 if (LHS.isNegative()) {
179 S.
CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
182 }
else if (LHS.toUnsigned().countLeadingZeros() <
183 static_cast<unsigned>(RHS)) {
185 S.
CCEDiag(E, diag::note_constexpr_lshift_discards);
203 if (!LHS.isNumber() || !RHS.isNumber())
209 if constexpr (std::is_same_v<T, Floating>) {
210 S.
CCEDiag(Op, diag::note_expr_divide_by_zero)
211 << Op->getRHS()->getSourceRange();
215 S.
FFDiag(Op, diag::note_expr_divide_by_zero)
216 << Op->getRHS()->getSourceRange();
220 if constexpr (!std::is_same_v<T, FixedPoint>) {
221 if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) {
222 APSInt LHSInt = LHS.toAPSInt();
224 (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10);
227 S.
CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->
getType();
237 APFloat::opStatus Status,
FPOptions FPO);
259template <PrimType Name, class T = typename PrimConv<Name>::T>
312 template <typename U>
class OpAP>
317 assert(LHS.isNumber() && RHS.isNumber());
333 if constexpr (std::is_same_v<T, FixedPoint>)
349 .toString(Trunc, 10,
Result.isSigned(),
false,
363template <
typename T,
template <
typename U>
class Op>
365 assert(!LHS.isNumber() || !RHS.isNumber());
369 typename T::ReprT Offset;
371 if (LHS.isNumber()) {
375 Number =
static_cast<typename T::ReprT
>(LHS);
377 Offset = RHS.getOffset();
378 Kind = RHS.getKind();
380 assert(RHS.isNumber());
384 Number =
static_cast<typename T::ReprT
>(RHS);
386 Offset = LHS.getOffset();
387 Kind = LHS.getKind();
394template <PrimType Name, class T = typename PrimConv<Name>::T>
396 const T &RHS = S.
Stk.
pop<T>();
397 const T &LHS = S.
Stk.
pop<T>();
398 const unsigned Bits = RHS.bitWidth() + 1;
401 if (LHS.isNumber() != RHS.isNumber())
403 else if (LHS.isNumber() && RHS.isNumber())
423template <PrimType Name, class T = typename PrimConv<Name>::T>
425 const T &RHS = S.
Stk.
pop<T>();
426 const T &LHS = S.
Stk.
pop<T>();
427 const unsigned Bits = RHS.bitWidth() + 1;
436 ?
reinterpret_cast<const Expr *
>(LHS.getPtr())
439 ?
reinterpret_cast<const Expr *
>(RHS.getPtr())
441 if (!isa_and_nonnull<AddrLabelExpr>(A) ||
442 !isa_and_nonnull<AddrLabelExpr>(B))
447 if (LHSAddrExpr->getLabel()->getDeclContext() !=
448 RHSAddrExpr->getLabel()->getDeclContext())
451 S.
Stk.
push<T>(LHSAddrExpr, RHSAddrExpr);
455 if (!LHS.isNumber() && RHS.isNumber())
457 else if (LHS.isNumber() && RHS.isNumber())
477template <PrimType Name, class T = typename PrimConv<Name>::T>
479 const T &RHS = S.
Stk.
pop<T>();
480 const T &LHS = S.
Stk.
pop<T>();
481 const unsigned Bits = RHS.bitWidth() * 2;
484 if (!LHS.isNumber() || !RHS.isNumber())
504template <PrimType Name, class T = typename PrimConv<Name>::T>
510 if constexpr (std::is_same_v<T, Floating>) {
516 APFloat ResR(A.getSemantics());
517 APFloat ResI(A.getSemantics());
528 Result.initializeAllElements();
531 const T &LHSR = LHS.elem<T>(0);
532 const T &LHSI = LHS.elem<T>(1);
533 const T &RHSR = RHS.
elem<T>(0);
534 const T &RHSI = RHS.
elem<T>(1);
535 unsigned Bits = LHSR.bitWidth();
538 if (!LHSR.isNumber() || !LHSI.isNumber() || !RHSR.isNumber() ||
546 if (T::mul(LHSR, RHSR,
Bits, &A))
552 if (T::mul(LHSI, RHSI,
Bits, &B))
561 if (T::mul(LHSR, RHSI,
Bits, &A))
563 if (T::mul(LHSI, RHSR,
Bits, &B))
571 Result.initializeAllElements();
577template <PrimType Name, class T = typename PrimConv<Name>::T>
583 if constexpr (std::is_same_v<T, Floating>) {
589 APFloat ResR(A.getSemantics());
590 APFloat ResI(A.getSemantics());
602 Result.initializeAllElements();
605 const T &LHSR = LHS.elem<T>(0);
606 const T &LHSI = LHS.elem<T>(1);
607 const T &RHSR = RHS.
elem<T>(0);
608 const T &RHSI = RHS.
elem<T>(1);
609 unsigned Bits = LHSR.bitWidth();
611 if (RHSR.isZero() && RHSI.isZero()) {
613 S.
FFDiag(E, diag::note_expr_divide_by_zero);
624 if (T::mul(RHSR, RHSR,
Bits, &A) || T::mul(RHSI, RHSI,
Bits, &B)) {
631 if (T::add(A, B,
Bits, &Den))
636 S.
FFDiag(E, diag::note_expr_divide_by_zero);
641 T &ResultR =
Result.elem<T>(0);
642 T &ResultI =
Result.elem<T>(1);
647 if (T::mul(LHSR, RHSR,
Bits, &A) || T::mul(LHSI, RHSI,
Bits, &B))
649 if (T::add(A, B,
Bits, &ResultR))
651 if (T::div(ResultR, Den,
Bits, &ResultR))
655 if (T::mul(LHSI, RHSR,
Bits, &A) || T::mul(LHSR, RHSI,
Bits, &B))
657 if (T::sub(A, B,
Bits, &ResultI))
659 if (T::div(ResultI, Den,
Bits, &ResultI))
661 Result.initializeAllElements();
670template <PrimType Name, class T = typename PrimConv<Name>::T>
672 const T &RHS = S.
Stk.
pop<T>();
673 const T &LHS = S.
Stk.
pop<T>();
674 unsigned Bits = RHS.bitWidth();
677 if (!LHS.isNumber() || !RHS.isNumber())
695template <PrimType Name, class T = typename PrimConv<Name>::T>
697 const T &RHS = S.
Stk.
pop<T>();
698 const T &LHS = S.
Stk.
pop<T>();
699 unsigned Bits = RHS.bitWidth();
702 if (!LHS.isNumber() || !RHS.isNumber())
720template <PrimType Name, class T = typename PrimConv<Name>::T>
722 const T &RHS = S.
Stk.
pop<T>();
723 const T &LHS = S.
Stk.
pop<T>();
724 unsigned Bits = RHS.bitWidth();
727 if (!LHS.isNumber() || !RHS.isNumber())
745template <PrimType Name, class T = typename PrimConv<Name>::T>
747 const T &RHS = S.
Stk.
pop<T>();
748 const T &LHS = S.
Stk.
pop<T>();
749 const unsigned Bits = RHS.bitWidth() * 2;
768template <PrimType Name, class T = typename PrimConv<Name>::T>
770 const T &RHS = S.
Stk.
pop<T>();
771 const T &LHS = S.
Stk.
pop<T>();
772 const unsigned Bits = RHS.bitWidth() * 2;
786 if constexpr (std::is_same_v<T, FixedPoint>) {
825template <PrimType Name, class T = typename PrimConv<Name>::T>
829 if constexpr (std::is_same_v<T, Floating>) {
848 "don't expect other types to fail at constexpr negation");
859 NegatedValue.trunc(
Result.bitWidth())
860 .toString(Trunc, 10,
Result.isSigned(),
false,
880template <
typename T, IncDecOp Op, PushVal DoPush>
890 if constexpr (std::is_same_v<T, Boolean>) {
899 if (!
Value.isNumber())
911 if (!T::increment(
Value, &
Result) || !CanOverflow) {
919 if (!T::decrement(
Value, &
Result) || !CanOverflow) {
948 APResult.trunc(
Result.bitWidth())
949 .toString(Trunc, 10,
Result.isSigned(),
false,
962template <PrimType Name, class T = typename PrimConv<Name>::T>
974template <PrimType Name, class T = typename PrimConv<Name>::T>
990template <PrimType Name, class T = typename PrimConv<Name>::T>
1001template <PrimType Name, class T = typename PrimConv<Name>::T>
1003 uint32_t BitWidth) {
1014template <PrimType Name, class T = typename PrimConv<Name>::T>
1025template <PrimType Name, class T = typename PrimConv<Name>::T>
1027 uint32_t BitWidth) {
1042template <PrimType Name, class T = typename PrimConv<Name>::T>
1053template <PrimType Name, class T = typename PrimConv<Name>::T>
1055 uint32_t BitWidth) {
1069template <PrimType Name, class T = typename PrimConv<Name>::T>
1080template <PrimType Name, class T = typename PrimConv<Name>::T>
1082 uint32_t BitWidth) {
1093template <PrimType Name, class T = typename PrimConv<Name>::T>
1103template <PrimType Name, class T = typename PrimConv<Name>::T>
1105 uint32_t BitWidth) {
1115template <IncDecOp Op, PushVal DoPush>
1125 llvm::APFloat::opStatus Status;
1178template <PrimType Name, class T = typename PrimConv<Name>::T>
1180 const T &Val = S.
Stk.
pop<T>();
1186 if (!T::comp(Val, &
Result)) {
1199template <
typename T>
1201 assert((!std::is_same_v<T, MemberPointer>) &&
1202 "Non-equality comparisons on member pointer types should already be "
1203 "rejected in Sema.");
1205 const T &RHS = S.
Stk.
pop<T>();
1206 const T &LHS = S.
Stk.
pop<T>();
1209 if (!LHS.isNumber() || !RHS.isNumber())
1213 S.
Stk.
push<BoolT>(BoolT::from(
Fn(LHS.compare(RHS))));
1217template <
typename T>
1232 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1245 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1253 if (std::optional<std::pair<PtrView, PtrView>> Split =
1255 const FieldDecl *LF = Split->first.getField();
1256 const FieldDecl *RF = Split->second.getField();
1259 diag::note_constexpr_pointer_comparison_base_classes);
1262 diag::note_constexpr_pointer_comparison_base_field)
1263 << Split->first.getRecord()->getDecl() << RF->
getParent() << RF;
1266 diag::note_constexpr_pointer_comparison_base_field)
1267 << Split->second.getRecord()->getDecl() << LF->
getParent() << LF;
1271 diag::note_constexpr_pointer_comparison_differing_access)
1286 return (
Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
1287 Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
1288 Builtin == Builtin::BI__builtin_ptrauth_sign_constant ||
1289 Builtin == Builtin::BI__builtin_function_start);
1301 if (LHS.isZero() && RHS.
isZero()) {
1307 for (
const auto &P : {LHS, RHS}) {
1312 S.
FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison)
1319 if (RHS.
isZero() || LHS.isZero()) {
1324 assert(!LHS.isZero());
1343 S.
FFDiag(Loc, diag::note_constexpr_literal_comparison)
1351 std::optional<size_t> A = LHS.computeOffsetForComparison(S.
getASTContext());
1364 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
1368 if (RHS.
isOnePastEnd() && !LHS.isOnePastEnd() && LHS.isBlockPointer() &&
1369 LHS.getOffset() == 0) {
1371 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
1377 for (
const auto &P : {LHS, RHS}) {
1380 if (P.pointsToLiteral()) {
1381 const Expr *E = P.getDeclDesc()->asExpr();
1384 S.
FFDiag(Loc, diag::note_constexpr_literal_comparison);
1387 if (
const auto *CE = dyn_cast<CallExpr>(E);
1390 S.
FFDiag(Loc, diag::note_constexpr_opaque_call_comparison)
1394 }
else if (P.isIntegralPointer()) {
1396 S.
FFDiag(Loc, diag::note_constexpr_pointer_constant_comparison)
1405 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_zero_sized)
1414 diag::note_constexpr_pointer_comparison_unspecified)
1432 for (
const auto &MP : {LHS, RHS}) {
1435 S.
FFDiag(Loc, diag::note_constexpr_mem_pointer_weak_comparison)
1436 << MP.getMemberFunction();
1444 if (LHS.
isZero() && RHS.isZero()) {
1448 if (LHS.
isZero() || RHS.isZero()) {
1454 for (
const auto &MP : {LHS, RHS}) {
1458 S.
CCEDiag(Loc, diag::note_constexpr_compare_virtual_mem_ptr) << MD;
1466template <PrimType Name, class T = typename PrimConv<Name>::T>
1473template <PrimType Name, class T = typename PrimConv<Name>::T>
1475 const T &RHS = S.
Stk.
pop<T>();
1476 const T &LHS = S.
Stk.
pop<T>();
1480 if constexpr (std::is_same_v<T, Pointer>) {
1483 S.
FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1491 const auto *CmpValueInfo =
1493 assert(CmpValueInfo);
1494 assert(CmpValueInfo->hasValidIntValue());
1498template <PrimType Name, class T = typename PrimConv<Name>::T>
1505template <PrimType Name, class T = typename PrimConv<Name>::T>
1512template <PrimType Name, class T = typename PrimConv<Name>::T>
1520template <PrimType Name, class T = typename PrimConv<Name>::T>
1527template <PrimType Name, class T = typename PrimConv<Name>::T>
1539template <PrimType Name, class T = typename PrimConv<Name>::T>
1545template <PrimType Name, class T = typename PrimConv<Name>::T>
1552template <PrimType TopName, PrimType BottomName>
1557 const auto &Top = S.
Stk.
pop<TopT>();
1558 const auto &Bottom = S.
Stk.
pop<BottomT>();
1570template <PrimType Name, class T = typename PrimConv<Name>::T>
1574 Result.copy(Arg.toAPSInt());
1579 if constexpr (std::is_same_v<T, uint16_t>) {
1581 }
else if constexpr (std::is_same_v<T, int16_t>) {
1583 }
else if constexpr (std::is_same_v<T, uint32_t>) {
1585 }
else if constexpr (std::is_same_v<T, int32_t>) {
1587 }
else if constexpr (std::is_same_v<T, uint64_t>) {
1589 }
else if constexpr (std::is_same_v<T, int64_t>) {
1610template <PrimType Name, class T = typename PrimConv<Name>::T>
1628template <PrimType Name, class T = typename PrimConv<Name>::T>
1634template <PrimType Name, class T = typename PrimConv<Name>::T>
1643template <PrimType Name, class T = typename PrimConv<Name>::T>
1651template <PrimType Name, class T = typename PrimConv<Name>::T>
1668 S.
Stk.
push<T>(Field.deref<T>());
1674template <PrimType Name, class T = typename PrimConv<Name>::T>
1691 S.
Stk.
push<T>(Field.deref<T>());
1695template <PrimType Name, class T = typename PrimConv<Name>::T>
1707 Field.deref<T>() =
Value;
1711template <PrimType Name, class T = typename PrimConv<Name>::T>
1721 S.
Stk.
push<T>(Field.deref<T>());
1725template <PrimType Name, class T = typename PrimConv<Name>::T>
1736 Field.deref<T>() =
Value;
1740template <PrimType Name, class T = typename PrimConv<Name>::T>
1752template <PrimType Name, class T = typename PrimConv<Name>::T>
1763template <PrimType Name, class T = typename PrimConv<Name>::T>
1769template <PrimType Name, class T = typename PrimConv<Name>::T>
1775 if constexpr (std::is_same_v<T, Floating>) {
1777 if (!Val.singleWord()) {
1778 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
1779 Val.take(NewMemory);
1782 }
else if constexpr (std::is_same_v<T, MemberPointer>) {
1786 for (
unsigned I = 0; I != PathLength; ++I) {
1787 NewPath[I] = Val.getPathEntry(I);
1789 Val.takePath(NewPath);
1791 auto &Val = P.
deref<T>();
1792 if (!Val.singleWord()) {
1793 uint64_t *NewMemory =
new (S.
P) uint64_t[Val.numWords()];
1794 Val.take(NewMemory);
1805template <PrimType Name, class T = typename PrimConv<Name>::T>
1837template <PrimType Name, class T = typename PrimConv<Name>::T>
1844 if (!
This.isDereferencable())
1848 assert(Field.canBeInitialized());
1849 Field.deref<T>() = S.
Stk.
pop<T>();
1854template <PrimType Name, class T = typename PrimConv<Name>::T>
1861 if (!
This.isDereferencable())
1865 assert(Field.canBeInitialized());
1866 Field.deref<T>() = S.
Stk.
pop<T>();
1872template <PrimType Name, class T = typename PrimConv<Name>::T>
1874 uint32_t FieldBitWidth) {
1880 if (!
This.isDereferencable())
1884 assert(Field.canBeInitialized());
1888 if (!
Value.isNumber())
1892 Field.deref<T>() =
Value.truncate(FieldBitWidth);
1897template <PrimType Name, class T = typename PrimConv<Name>::T>
1899 uint32_t FieldOffset, uint32_t FieldBitWidth) {
1905 if (!
This.isDereferencable())
1909 assert(Field.canBeInitialized());
1913 if (!
Value.isNumber())
1917 Field.deref<T>() =
Value.truncate(FieldBitWidth);
1926template <PrimType Name, class T = typename PrimConv<Name>::T>
1930 if (!Ptr.isDereferencable())
1944template <PrimType Name, class T = typename PrimConv<Name>::T>
1948 if (!Ptr.isDereferencable())
1962template <PrimType Name, class T = typename PrimConv<Name>::T>
1964 uint32_t FieldBitWidth) {
1967 if (!Ptr.isDereferencable())
1971 if (!
Value.isNumber())
1981 unsigned BitWidth = std::min(FieldBitWidth,
Value.bitWidth());
1984 if constexpr (T::isSigned())
1986 Value.toAPSInt().trunc(BitWidth).sextOrTrunc(
Value.bitWidth()));
1989 Value.toAPSInt().trunc(BitWidth).zextOrTrunc(
Value.bitWidth()));
1991 Field.deref<T>() =
Result;
1993 Field.deref<T>() =
Value.truncate(FieldBitWidth);
1999template <PrimType Name, class T = typename PrimConv<Name>::T>
2001 uint32_t FieldBitWidth) {
2004 if (!Ptr.isDereferencable())
2008 if (!
Value.isNumber())
2018 unsigned BitWidth = std::min(FieldBitWidth,
Value.bitWidth());
2021 if constexpr (T::isSigned())
2023 Value.toAPSInt().trunc(BitWidth).sextOrTrunc(
Value.bitWidth()));
2026 Value.toAPSInt().trunc(BitWidth).zextOrTrunc(
Value.bitWidth()));
2028 Field.deref<T>() =
Result;
2030 Field.deref<T>() =
Value.truncate(FieldBitWidth);
2086bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off);
2089bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off);
2090bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off,
bool NullOK);
2092bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off,
bool NullOK,
2093 const Type *TargetType);
2158 diag::note_constexpr_dereferencing_null);
2171 const Record::Base *VirtBase =
Base.getRecord()->getVirtualBase(
Decl);
2202template <PrimType Name, class T = typename PrimConv<Name>::T>
2215template <PrimType Name, class T = typename PrimConv<Name>::T>
2228template <PrimType Name, class T = typename PrimConv<Name>::T>
2234 if (!Ptr.canDeref(Name))
2236 if (Ptr.canBeInitialized())
2238 Ptr.deref<T>() =
Value;
2242template <PrimType Name, class T = typename PrimConv<Name>::T>
2248 if (!Ptr.canDeref(Name))
2250 if (Ptr.canBeInitialized())
2252 Ptr.deref<T>() =
Value;
2275template <PrimType Name, class T = typename PrimConv<Name>::T>
2282 if (Ptr.canBeInitialized()) {
2290template <PrimType Name, class T = typename PrimConv<Name>::T>
2297 if (Ptr.canBeInitialized()) {
2305template <PrimType Name, class T = typename PrimConv<Name>::T>
2312 if (Ptr.canBeInitialized())
2314 if (
const auto *FD = Ptr.getField())
2315 Ptr.deref<T>() =
Value.truncate(FD->getBitWidthValue());
2317 Ptr.deref<T>() =
Value;
2321template <PrimType Name, class T = typename PrimConv<Name>::T>
2327 if (Ptr.canBeInitialized())
2329 if (
const auto *FD = Ptr.getField())
2330 Ptr.deref<T>() =
Value.truncate(FD->getBitWidthValue());
2332 Ptr.deref<T>() =
Value;
2336template <PrimType Name, class T = typename PrimConv<Name>::T>
2343 if (Ptr.canBeInitialized()) {
2347 if (
const auto *FD = Ptr.getField())
2348 Ptr.
deref<T>() =
Value.truncate(FD->getBitWidthValue());
2350 Ptr.deref<T>() =
Value;
2354template <PrimType Name, class T = typename PrimConv<Name>::T>
2361 if (Ptr.canBeInitialized()) {
2365 if (
const auto *FD = Ptr.getField())
2366 Ptr.
deref<T>() =
Value.truncate(FD->getBitWidthValue());
2368 Ptr.deref<T>() =
Value;
2372template <PrimType Name, class T = typename PrimConv<Name>::T>
2379 new (&Ptr.deref<T>()) T(
Value);
2383template <PrimType Name, class T = typename PrimConv<Name>::T>
2390 new (&Ptr.deref<T>()) T(
Value);
2397template <PrimType Name, class T = typename PrimConv<Name>::T>
2402 if (Ptr.isConstexprUnknown())
2411 if (Idx == 0 && !Desc->
isArray()) {
2413 new (&Ptr.deref<T>()) T(
Value);
2423 S.
FFDiag(Loc, diag::note_constexpr_access_past_end)
2428 Ptr.initializeElement(Idx);
2429 new (&Ptr.elem<T>(Idx)) T(
Value);
2434template <PrimType Name, class T = typename PrimConv<Name>::T>
2439 if (Ptr.isConstexprUnknown())
2448 if (Idx == 0 && !Desc->
isArray()) {
2450 new (&Ptr.deref<T>()) T(
Value);
2460 S.
FFDiag(Loc, diag::note_constexpr_access_past_end)
2465 Ptr.initializeElement(Idx);
2466 new (&Ptr.elem<T>(Idx)) T(
Value);
2479 return DoMemcpy(S, OpPC, Src, Dest);
2493 if (std::optional<Pointer> Ptr = MP.toPointer(S.
Ctx)) {
2504template <
class T, ArithOp Op>
2506 const T &Offset,
const Pointer &Ptr,
2507 bool IsPointerArith =
false) {
2509 if (Offset.isZero())
2516 return std::nullopt;
2521 return std::nullopt;
2531 uint64_t O =
static_cast<uint64_t
>(Offset) * ElemSize;
2537 uint64_t O =
static_cast<uint64_t
>(Offset);
2549 return std::nullopt;
2554 uint64_t MaxIndex =
static_cast<uint64_t
>(Ptr.
getNumElems());
2563 auto DiagInvalidOffset = [&]() ->
void {
2564 const unsigned Bits = Offset.bitWidth();
2565 APSInt APOffset(Offset.toAPSInt().extend(
Bits + 2),
false);
2569 (Op ==
ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
2571 << NewIndex <<
static_cast<int>(!Ptr.
inArray()) << MaxIndex;
2576 uint64_t IOffset =
static_cast<uint64_t
>(Offset);
2577 uint64_t MaxOffset = MaxIndex - Index;
2581 if (Offset.isNegative() && (Offset.isMin() || -IOffset > Index))
2582 DiagInvalidOffset();
2585 if (Offset.isPositive() && IOffset > MaxOffset)
2586 DiagInvalidOffset();
2589 if (Offset.isPositive() && Index < IOffset)
2590 DiagInvalidOffset();
2593 if (Offset.isNegative() && (Offset.isMin() || -IOffset > MaxOffset))
2594 DiagInvalidOffset();
2599 return std::nullopt;
2602 int64_t WideIndex =
static_cast<int64_t
>(Index);
2603 int64_t WideOffset =
static_cast<int64_t
>(Offset);
2606 Result = WideIndex + WideOffset;
2608 Result = WideIndex - WideOffset;
2622template <PrimType Name, class T = typename PrimConv<Name>::T>
2624 const T &Offset = S.
Stk.
pop<T>();
2628 S, OpPC, Offset, Ptr,
true)) {
2635template <PrimType Name, class T = typename PrimConv<Name>::T>
2637 const T &Offset = S.
Stk.
pop<T>();
2641 S, OpPC, Offset, Ptr,
true)) {
2648template <ArithOp Op>
2664 OneT One = OneT::from(1);
2665 if (std::optional<Pointer>
Result =
2695template <PrimType Name, class T = typename PrimConv<Name>::T>
2704 if (!LHSAddrExpr || !RHSAddrExpr) {
2706 diag::note_constexpr_pointer_arith_unspecified)
2716 S.
Stk.
push<T>(LHSAddrExpr, RHSAddrExpr);
2725 diag::note_constexpr_pointer_arith_unspecified)
2731 if (ElemSizeIsZero) {
2733 while (
auto *AT = dyn_cast<ArrayType>(PtrT))
2734 PtrT = AT->getElementType();
2739 diag::note_constexpr_pointer_subtraction_zero_size)
2760 int64_t R64 = A64 - B64;
2761 if (
static_cast<int64_t
>(T::from(R64)) != R64)
2793 auto In = S.
Stk.
pop<T>();
2807 if (!(U::bitWidth() >= 32 && U::bitWidth() <= In.bitWidth()))
2819 llvm::RoundingMode RM) {
2829 FixedPointSemantics::getFromOpaqueInt(FPS);
2844template <PrimType Name, class T = typename PrimConv<Name>::T>
2846 T Source = S.
Stk.
pop<T>();
2849 if (!Source.isNumber())
2856 APInt SourceInt = Source.toAPSInt().extOrTrunc(BitWidth);
2863template <PrimType Name, class T = typename PrimConv<Name>::T>
2865 T Source = S.
Stk.
pop<T>();
2868 if (!Source.isNumber())
2875 APInt SourceInt = Source.toAPSInt().extOrTrunc(BitWidth);
2882template <PrimType Name, class T = typename PrimConv<Name>::T>
2884 const llvm::fltSemantics *Sem, uint32_t FPOI) {
2885 const T &From = S.
Stk.
pop<T>();
2888 if (!From.isNumber())
2892 APSInt FromAP = From.toAPSInt();
2903template <PrimType Name, class T = typename PrimConv<Name>::T>
2907 if constexpr (std::is_same_v<T, Boolean>) {
2916 if ((Status & APFloat::opStatus::opInvalidOp)) {
2935 uint32_t BitWidth, uint32_t FPOI) {
2942 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite() &&
2957 uint32_t BitWidth, uint32_t FPOI) {
2964 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite() &&
2979 const Pointer &Ptr,
unsigned BitWidth);
2984template <PrimType Name, class T = typename PrimConv<Name>::T>
2990 if constexpr (std::is_same_v<T, Boolean>) {
3005 PtrVal = Ptr.
block();
3008 S.
Stk.
push<T>(Kind, PtrVal, 0);
3021template <PrimType Name, class T = typename PrimConv<Name>::T>
3055 const llvm::fltSemantics *Sem) {
3058 Result.copy(Fixed.toFloat(Sem));
3063template <PrimType Name, class T = typename PrimConv<Name>::T>
3068 APSInt Int = Fixed.toInt(T::bitWidth(), T::isSigned(), &Overflow);
3079 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
3080 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3089 bool HasValidResult = !Ptr.isZero();
3091 if (HasValidResult) {
3098 E->getType()->getPointeeType()))
3101 S.
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
3102 << E->getSubExpr()->getType() << S.
getLangOpts().CPlusPlus26
3103 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
3106 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
3107 << diag::ConstexprInvalidCastKind::CastFrom <<
"'void *'"
3112 S.
CCEDiag(E, diag::note_constexpr_invalid_cast)
3113 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3124template <PrimType Name, class T = typename PrimConv<Name>::T>
3132 if (!
Result.singleWord())
3133 std::memset(
Result.Memory, 0,
Result.numWords() *
sizeof(uint64_t));
3140 if (!
Result.singleWord())
3141 std::memset(
Result.Memory, 0,
Result.numWords() *
sizeof(uint64_t));
3146template <PrimType Name, class T = typename PrimConv<Name>::T>
3154template <PrimType Name, class T = typename PrimConv<Name>::T>
3156 const auto &P = S.
Stk.
pop<T>();
3176 if (!
This.isDummy()) {
3178 if (!
This.isTypeidPointer()) {
3179 [[maybe_unused]]
const Record *R =
This.getRecord();
3181 R =
This.narrow().getRecord();
3184 assert(R->getDecl() ==
3206template <
class LT,
class RT, ShiftDir Dir>
3210 const unsigned Bits = LHS.bitWidth();
3214 RT::bitAnd(RHS, RT::from(LHS.bitWidth() - 1, RHS.bitWidth()),
3215 RHS.bitWidth(), &RHS);
3217 if (RHS.isNegative()) {
3221 S.
CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
3225 RHS = RHS.isMin() ? RT(APSInt::getMaxValue(RHS.bitWidth(),
false)) : -RHS;
3229 S, OpPC, LHS, RHS,
Result);
3241 typename LT::AsUnsigned R;
3242 unsigned MaxShiftAmount = LHS.bitWidth() - 1;
3244 if (
Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
3246 if (LHS.isNegative())
3247 R = LT::AsUnsigned::zero(LHS.bitWidth());
3249 RHS = RT::from(LHS.countLeadingZeros(), RHS.bitWidth());
3250 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
3251 LT::AsUnsigned::from(RHS,
Bits),
Bits, &R);
3253 }
else if (LHS.isNegative()) {
3255 R = LT::AsUnsigned::zero(LHS.bitWidth());
3258 typename LT::AsUnsigned LHSU = LT::AsUnsigned::from(-LHS);
3259 LT::AsUnsigned::shiftLeft(LHSU, LT::AsUnsigned::from(RHS,
Bits),
Bits,
3265 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
3266 LT::AsUnsigned::from(RHS,
Bits),
Bits, &R);
3273 if (
Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
3275 R = LT::AsUnsigned::from(0);
3279 LT::shiftRight(LHS, LT::from(RHS,
Bits),
Bits, &A);
3280 R = LT::AsUnsigned::from(A);
3288template <
class LT,
class RT, ShiftDir Dir>
3291 const unsigned Bits = LHS.getBitWidth();
3296 APSInt(llvm::APInt(RHS.getBitWidth(),
static_cast<uint64_t
>(
Bits - 1)),
3299 if (RHS.isNegative()) {
3303 S.
CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS;
3308 S, OpPC, LHS, -(RHS.extend(RHS.getBitWidth() + 1)),
Result);
3332template <PrimType NameL, PrimType NameR>
3336 auto RHS = S.
Stk.
pop<RT>();
3344 RHS.toAPSInt(), &
Result);
3351template <PrimType NameL, PrimType NameR>
3355 auto RHS = S.
Stk.
pop<RT>();
3363 RHS.toAPSInt(), &
Result);
3373 llvm::FixedPointSemantics LHSSema = LHS.
getSemantics();
3375 unsigned ShiftBitWidth =
3376 LHSSema.getWidth() - (
unsigned)LHSSema.hasUnsignedPadding() - 1;
3381 if (RHS.isNegative()) {
3384 }
else if (
static_cast<unsigned>(RHS.toAPSInt().getLimitedValue(
3385 ShiftBitWidth)) != RHS.toAPSInt()) {
3387 S.
CCEDiag(E, diag::note_constexpr_large_shift)
3388 << RHS.toAPSInt() << E->
getType() << ShiftBitWidth;
3411 S.
FFDiag(EndLoc, diag::note_constexpr_no_return);
3442template <PrimType Name, class T = typename PrimConv<Name>::T>
3444 const T &Offset = S.
Stk.
pop<T>();
3447 if (!Ptr.isZero() && !Offset.isZero()) {
3452 if (Offset.isZero()) {
3453 if (
const Descriptor *Desc = Ptr.getFieldDesc();
3454 Desc && Desc->
isArray() && Ptr.getIndex() == 0) {
3462 assert(!Offset.isZero());
3464 if (std::optional<Pointer>
Result =
3473template <PrimType Name, class T = typename PrimConv<Name>::T>
3475 const T &Offset = S.
Stk.
pop<T>();
3478 if (!Ptr.isZero() && !Offset.isZero()) {
3483 if (Offset.isZero()) {
3484 if (
const Descriptor *Desc = Ptr.getFieldDesc();
3485 Desc && Desc->
isArray() && Ptr.getIndex() == 0) {
3493 assert(!Offset.isZero());
3495 if (std::optional<Pointer>
Result =
3503template <PrimType Name, class T = typename PrimConv<Name>::T>
3515template <PrimType Name, class T = typename PrimConv<Name>::T>
3527template <PrimType Name, class T = typename PrimConv<Name>::T>
3529 uint32_t DestIndex, uint32_t Size) {
3533 if (SrcPtr.isDummy() || DestPtr.
isDummy())
3539 const Descriptor *SrcDesc = SrcPtr.getFieldDesc();
3545 for (uint32_t I = 0; I != Size; ++I) {
3551 DestPtr.
elem<T>(DestIndex + I) = SrcPtr.elem<T>(SrcIndex + I);
3578 S.
FFDiag(E, diag::note_constexpr_unsupported_unsized_array);
3589template <PrimType Name, class T = typename PrimConv<Name>::T>
3591 const T &IntVal = S.
Stk.
pop<T>();
3594 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3599 if (IntVal.getOffset() != 0)
3605 if (IntVal.getOffset() != 0)
3608 const Block *B = (
const Block *)IntVal.getPtr();
3635 S.
FFDiag(Loc, diag::note_constexpr_stmt_expr_unsupported)
3735 diag::note_constexpr_access_volatile_type)
3747 S.
CCEDiag(E, diag::note_constexpr_non_const_vectorelements) << ArgRange;
3755 diag::note_constexpr_pseudo_destructor);
3767 S.
CCEDiag(Loc, diag::note_constexpr_assumption_failed);
3771template <PrimType Name, class T = typename PrimConv<Name>::T>
3775 ArrayIndices.emplace_back(
3787template <PrimType Name, class T = typename PrimConv<Name>::T>
3789 const T &Arg = S.
Stk.
peek<T>();
3794 S.
CCEDiag(Loc, diag::note_non_null_attribute_failed);
3800 const APSInt &
Value);
3802template <PrimType Name, class T = typename PrimConv<Name>::T>
3815template <PrimType TIn, PrimType TOut>
3821 const FromT &OldPtr = S.
Stk.
pop<FromT>();
3823 if constexpr (std::is_same_v<FromT, FunctionPointer> &&
3824 std::is_same_v<ToT, Pointer>) {
3827 }
else if constexpr (std::is_same_v<FromT, Pointer> &&
3828 std::is_same_v<ToT, FunctionPointer>) {
3829 if (OldPtr.isFunctionPointer()) {
3831 OldPtr.getByteOffset());
3836 S.
Stk.
push<ToT>(ToT(OldPtr.getIntegerRepresentation(),
nullptr));
3889template <PrimType Name, class SizeT = typename PrimConv<Name>::T>
3904 if (NumElements.isNegative()) {
3914 if (!
CheckArraySize(S, OpPC,
static_cast<uint64_t
>(NumElements)))
3918 Block *B = Allocator.
allocate(Source, T,
static_cast<size_t>(NumElements),
3921 if (NumElements.isZero())
3928template <PrimType Name, class SizeT = typename PrimConv<Name>::T>
3947 if (NumElements.isNegative()) {
3957 if (!
CheckArraySize(S, OpPC,
static_cast<uint64_t
>(NumElements)))
3961 Block *B = Allocator.
allocate(ElementDesc,
static_cast<size_t>(NumElements),
3964 if (NumElements.isZero())
3972bool Free(InterpState &S, CodePtr OpPC,
bool DeleteIsArrayForm,
3973 bool IsGlobalDelete);
3987 std::optional<uint64_t> ArraySize = std::nullopt);
3989template <PrimType Name, class T = typename PrimConv<Name>::T>
3991 const auto &Size = S.
Stk.
pop<T>();
3996template <PrimType Name, class T = typename PrimConv<Name>::T>
3998 uint32_t ResultBitWidth,
const llvm::fltSemantics *Sem,
3999 const Type *TargetType) {
4005 if constexpr (std::is_same_v<T, Pointer>) {
4008 diag::note_constexpr_bit_cast_invalid_type)
4009 <<
true <<
false << 1 ;
4015 }
else if constexpr (std::is_same_v<T, MemberPointer>) {
4017 diag::note_constexpr_bit_cast_invalid_type)
4018 <<
true <<
false << 2 ;
4022 size_t BuffSize = ResultBitWidth / 8;
4024 bool HasIndeterminateBits =
false;
4026 Bits FullBitWidth(ResultBitWidth);
4027 Bits BitWidth = FullBitWidth;
4029 if constexpr (std::is_same_v<T, Floating>) {
4031 BitWidth =
Bits(llvm::APFloatBase::getSizeInBits(*Sem));
4034 if (!
DoBitCast(S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth,
4035 HasIndeterminateBits))
4038 if (!
CheckBitCast(S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte))
4041 if constexpr (std::is_same_v<T, Floating>) {
4048 T::bitcastFromMemory(Buff.data(), ResultBitWidth, &
Result);
4050 }
else if constexpr (std::is_same_v<T, Boolean>) {
4054 auto Val =
static_cast<unsigned int>(Buff[0]);
4057 diag::note_constexpr_bit_cast_unrepresentable_value)
4061 S.
Stk.
push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
4064 S.
Stk.
push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
4075 if (D->isPrimitiveArray() && FromPtr.
isArrayRoot())
4088bool GetTypeid(InterpState &S, CodePtr OpPC,
const Type *TypePtr,
4089 const Type *TypeInfoType);
4091bool DiagTypeid(InterpState &S, CodePtr OpPC);
4103 if constexpr (std::is_pointer<T>::value) {
4104 uint32_t ID = OpPC.
read<uint32_t>();
4107 return OpPC.
read<T>();
4117 OpPC +=
align(F.bytesToSerialize());
4126 assert(
Result.bitWidth() == BitWidth);
4138 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.
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.
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)
void copy(const APInt &V)
Wrapper around numeric types.
static std::enable_if_t<!std::is_same_v< ValT, IntegralKind >, Integral > from(ValT V, unsigned NumBits=0)
Frame storing local variables.
static void free(InterpFrame *F)
const Expr * getExpr(CodePtr PC) const
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.
void enableLocal(unsigned Idx)
Block * getLocalBlock(unsigned Offset) const
SourceLocation getLocation(CodePtr PC) 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.
SourceRange getRange(CodePtr PC) const
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 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.
Pointer narrow() const
Restricts the scope of an array element pointer.
Pointer stripBaseCasts() const
Strip base casts from this Pointer.
bool isInitialized() const
Checks if an object was initialized.
bool pointsToLabel() const
Whether this points to a block created for an AddrLabelExpr.
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.
const AddrLabelExpr * getPointedToLabel() const
Returns the AddrLabelExpr the Pointer points to, if any.
int64_t getIndex() const
Returns the index into an array.
bool canDeref(PrimType T) const
Checks whether the pointer can be dereferenced to the given PrimType.
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.
bool isIntegralPointer() const
QualType getType() const
Returns the type of the innermost field.
bool pointsToStringLiteral() const
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.
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.
bool isConstexprUnknown() const
const IntPointer & asIntPointer() const
bool isRoot() const
Pointer points directly to a block.
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
void activate() const
Activates a field.
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 isDereferencable() const
Whether this block can be read from at all.
bool isBlockPointer() const
const FunctionPointer & asFunctionPointer() const
const Block * block() 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 canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
const BlockPointer & asBlockPointer() const
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.
const void * getNativePointer(unsigned Idx) const
Returns the value of a marshalled native pointer.
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)
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 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)
bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue)
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 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 CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B)
Checks a direct load of a primitive value from a global or local variable.
PRESERVE_NONE bool NoRet(InterpState &S, CodePtr OpPC)
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 InitBitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t FieldOffset, uint32_t FieldBitWidth)
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}...
bool InitBitField(InterpState &S, CodePtr OpPC, uint32_t FieldOffset, uint32_t FieldBitWidth)
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 CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK, bool WillActivate)
bool StartInit(InterpState &S, CodePtr OpPC)
bool Div(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool StartThisLifetime1(InterpState &S, CodePtr OpPC)
PRESERVE_NONE bool EndSpeculation(InterpState &S, CodePtr &OpPC)
bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func)
bool InitThisBitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t FieldOffset, uint32_t FieldBitWidth)
bool FinishInitActivatePop(InterpState &S, CodePtr OpPC)
bool GetIntPtr(InterpState &S, CodePtr OpPC, const Type *Ty)
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)
PRESERVE_NONE bool RetVoid(InterpState &S, CodePtr &PC)
bool Mulc(InterpState &S, CodePtr OpPC)
constexpr bool isIntegralOrPointer()
bool ArrayElemPtr(InterpState &S, CodePtr OpPC)
bool NE(InterpState &S, CodePtr OpPC)
bool handleReference(InterpState &S, CodePtr OpPC, Block *B)
bool CheckBitCast(InterpState &S, CodePtr OpPC, const Type *TargetType, bool SrcIsVoidPtr)
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 CastAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, const Type *Ty)
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 GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t Index)
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 CopyMemberPtrPath(InterpState &S, CodePtr OpPC, const RecordDecl *Entry, bool IsDerived)
Just append the given Entry to the MemberPointer's path.
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 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.
bool PushIgnoreDiags(InterpState &S, CodePtr OpPC)
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 CastMemberPtrDerivedPop(InterpState &S, CodePtr OpPC, int32_t Off, const RecordDecl *BaseDecl)
BaseToDerivedMemberPointer.
@ BlockAddress
A pointer to an interp::Block.
@ AddrLabelDiff
Difference between two AddrLabelExpr.
@ Number
Just a number, nothing else.
@ Address
A pointer to a ValueDecl.
@ LabelAddress
A pointer to a AddrLabelExpr.
@ FunctionAddress
A pointer to a FunctionDecl.
bool PopIgnoreDiags(InterpState &S, CodePtr OpPC)
bool LE(InterpState &S, CodePtr OpPC)
bool isConstexprUnknown(const Block *B)
bool CheckNewTypeMismatchArray(InterpState &S, CodePtr OpPC, const Expr *E)
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.
bool PushMSVCCE(InterpState &S, CodePtr OpPC)
PrimType
Enumeration of the primitive types of the VM.
bool DecPopBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, uint32_t BitWidth)
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 GetParam(InterpState &S, CodePtr OpPC, uint32_t Index)
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 InitThisBitField(InterpState &S, CodePtr OpPC, uint32_t FieldOffset, uint32_t FieldBitWidth)
bool Dump(InterpState &S, CodePtr OpPC)
bool SizelessVectorElementSize(InterpState &S, CodePtr OpPC)
bool CheckRange(InterpState &S, CodePtr OpPC, PtrView Ptr, AccessKinds AK)
Checks if a pointer is in range.
static bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr)
bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T)
bool StartThisLifetime(InterpState &S, CodePtr OpPC)
bool GetRefGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool IsNonNull(InterpState &S, CodePtr OpPC)
bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off)
bool CtorCheck(InterpState &S, CodePtr OpPC)
Abort without a diagnostic if we're checking for a potential constant expression and this is not the ...
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 GetRefLocal(InterpState &S, CodePtr OpPC, uint32_t I)
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 GetPtrVirtBasePop(InterpState &S, CodePtr OpPC, const RecordDecl *D)
bool StorePop(InterpState &S, CodePtr OpPC)
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC, const Function *Func)
bool CheckIntegralAddressCast(InterpState &S, CodePtr OpPC, unsigned BitWidth)
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 CastMemberPtrBasePop(InterpState &S, CodePtr OpPC, int32_t Off, const RecordDecl *BaseDecl)
DerivedToBaseMemberPointer.
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 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 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 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 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 ...
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)
static bool CastFixedPointIntegral(InterpState &S, CodePtr OpPC)
PRESERVE_NONE bool Ret(InterpState &S, CodePtr &PC)
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 CastFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS)
bool PopMSVCCE(InterpState &S, CodePtr OpPC)
bool EnableLocal(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 EndInit(InterpState &S, CodePtr OpPC)
bool Subf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D)
bool GetLocalEnabled(InterpState &S, CodePtr OpPC, uint32_t I)
bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
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 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 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 DynamicCast(InterpState &S, CodePtr OpPC, const Type *DestTypePtr, bool IsReferenceCast)
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.
OptionalUnsigned< unsigned > UnsignedOrNone
@ ConstantFold
Fold the expression to a constant.
U cast(CodeGen::Address addr)
__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
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 getNumElems() const
Returns the number of elements stored in the block.
unsigned getSize() const
Returns the size of the object without metadata.
const Decl * asDecl() const
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.
PrimType getPrimType() const
bool isRecord() const
Checks if the descriptor is of a record.
const Expr * asExpr() const
bool isArray() const
Checks if the descriptor is of an array.
Descriptor used for global variables.
QualType getPointeeType() const
Mapping from primitive types to their representation.