13#ifndef LLVM_CLANG_AST_INTERP_INTERP_H
14#define LLVM_CLANG_AST_INTERP_INTERP_H
31#include "llvm/ADT/APFloat.h"
32#include "llvm/ADT/APSInt.h"
33#include "llvm/Support/Endian.h"
40using APSInt = llvm::APSInt;
49bool CheckExtern(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
52bool CheckArray(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
55bool CheckLive(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
59bool CheckDummy(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
62bool CheckNull(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
66bool CheckRange(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
70bool CheckRange(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
74bool CheckSubobject(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
78bool CheckConst(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
81bool CheckConstant(InterpState &S, CodePtr OpPC,
const Descriptor *Desc);
84bool CheckMutable(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
87bool CheckLoad(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
95bool CheckStore(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
98bool CheckInvoke(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
101bool CheckInit(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
104bool CheckCallable(InterpState &S, CodePtr OpPC,
const Function *F);
111bool CheckThis(InterpState &S, CodePtr OpPC,
const Pointer &
This);
118 const CallExpr *CE,
unsigned ArgSize);
123 const Pointer &Ptr,
const APSInt &IntValue);
126bool DoMemcpy(InterpState &S, CodePtr OpPC,
const Pointer &Src, Pointer &Dest);
129template <
typename LT,
typename RT>
132 if (RHS.isNegative()) {
134 S.CCEDiag(
Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
140 if (Bits > 1 && RHS >= RT::from(Bits, RHS.bitWidth())) {
141 const Expr *E = S.Current->getExpr(OpPC);
142 const APSInt Val = RHS.toAPSInt();
144 S.CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty << Bits;
148 if (LHS.isSigned() && !S.getLangOpts().CPlusPlus20) {
149 const Expr *E = S.Current->getExpr(OpPC);
152 if (LHS.isNegative())
153 S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
154 else if (LHS.toUnsigned().countLeadingZeros() <
static_cast<unsigned>(RHS))
155 S.CCEDiag(E, diag::note_constexpr_lshift_discards);
168 const auto *Op = cast<BinaryOperator>(S.Current->getExpr(OpPC));
169 S.FFDiag(Op, diag::note_expr_divide_by_zero)
170 << Op->getRHS()->getSourceRange();
171 if constexpr (!std::is_same_v<T, Floating>)
175 if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) {
176 APSInt LHSInt = LHS.toAPSInt();
178 (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10);
180 const Expr *E = S.Current->getExpr(OpPC);
181 S.CCEDiag(
Loc, diag::note_constexpr_overflow) << Trunc << E->
getType();
190 APFloat::opStatus Status);
206inline bool Invalid(InterpState &S, CodePtr OpPC);
216template <PrimType Name, class T = typename PrimConv<Name>::T>
218 const T &
Ret = S.Stk.pop<
T>();
223 if constexpr (std::is_same_v<T, Pointer>) {
228 if (!
Ret.isZero() && !
Ret.isLive())
233 assert(S.Current->getFrameOffset() == S.Stk.size() &&
"Invalid frame");
234 if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
238 PC = S.Current->getRetPC();
252 assert(S.Current->getFrameOffset() == S.Stk.size() &&
"Invalid frame");
254 if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
258 PC = S.Current->getRetPC();
273 template <typename U>
class OpAP>
278 if (!OpFW(LHS, RHS, Bits, &
Result)) {
287 APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits));
290 const Expr *E = S.Current->getExpr(OpPC);
292 if (S.checkingForUndefinedBehavior()) {
298 S.report(
Loc, diag::warn_integer_constant_overflow)
302 S.CCEDiag(E, diag::note_constexpr_overflow) <<
Value <<
Type;
303 if (!S.noteUndefinedBehavior()) {
311template <PrimType Name, class T = typename PrimConv<Name>::T>
313 const T &RHS = S.Stk.pop<
T>();
314 const T &LHS = S.Stk.pop<
T>();
315 const unsigned Bits = RHS.bitWidth() + 1;
316 return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
329template <PrimType Name, class T = typename PrimConv<Name>::T>
331 const T &RHS = S.Stk.pop<
T>();
332 const T &LHS = S.Stk.pop<
T>();
333 const unsigned Bits = RHS.bitWidth() + 1;
334 return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS);
347template <PrimType Name, class T = typename PrimConv<Name>::T>
349 const T &RHS = S.Stk.pop<
T>();
350 const T &LHS = S.Stk.pop<
T>();
351 const unsigned Bits = RHS.bitWidth() * 2;
352 return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS);
367template <PrimType Name, class T = typename PrimConv<Name>::T>
369 const T &RHS = S.Stk.pop<
T>();
370 const T &LHS = S.Stk.pop<
T>();
372 unsigned Bits = RHS.bitWidth();
374 if (!T::bitAnd(LHS, RHS, Bits, &
Result)) {
384template <PrimType Name, class T = typename PrimConv<Name>::T>
386 const T &RHS = S.Stk.pop<
T>();
387 const T &LHS = S.Stk.pop<
T>();
389 unsigned Bits = RHS.bitWidth();
391 if (!T::bitOr(LHS, RHS, Bits, &
Result)) {
401template <PrimType Name, class T = typename PrimConv<Name>::T>
403 const T &RHS = S.Stk.pop<
T>();
404 const T &LHS = S.Stk.pop<
T>();
406 unsigned Bits = RHS.bitWidth();
408 if (!T::bitXor(LHS, RHS, Bits, &
Result)) {
418template <PrimType Name, class T = typename PrimConv<Name>::T>
420 const T &RHS = S.Stk.pop<
T>();
421 const T &LHS = S.Stk.pop<
T>();
426 const unsigned Bits = RHS.bitWidth() * 2;
428 if (!T::rem(LHS, RHS, Bits, &
Result)) {
438template <PrimType Name, class T = typename PrimConv<Name>::T>
440 const T &RHS = S.Stk.pop<
T>();
441 const T &LHS = S.Stk.pop<
T>();
446 const unsigned Bits = RHS.bitWidth() * 2;
448 if (!T::div(LHS, RHS, Bits, &
Result)) {
472template <PrimType Name, class T = typename PrimConv<Name>::T>
475 const T &Val = S.Stk.pop<
T>();
476 const unsigned Bits = Val.bitWidth();
480 S.Stk.push<BoolT>(R);
488template <PrimType Name, class T = typename PrimConv<Name>::T>
490 const T &
Value = S.Stk.pop<
T>();
499 "don't expect other types to fail at constexpr negation");
503 const Expr *E = S.Current->getExpr(OpPC);
506 if (S.checkingForUndefinedBehavior()) {
508 NegatedValue.trunc(
Result.bitWidth())
512 S.report(
Loc, diag::warn_integer_constant_overflow)
517 S.CCEDiag(E, diag::note_constexpr_overflow) << NegatedValue <<
Type;
518 return S.noteUndefinedBehavior();
530template <
typename T, IncDecOp Op, PushVal DoPush>
534 if constexpr (std::is_same_v<T, Boolean>) {
535 if (!S.getLangOpts().CPlusPlus14)
559 unsigned Bits =
Value.bitWidth() + 1;
562 APResult = ++
Value.toAPSInt(Bits);
564 APResult = --
Value.toAPSInt(Bits);
567 const Expr *E = S.Current->getExpr(OpPC);
569 if (S.checkingForUndefinedBehavior()) {
571 APResult.trunc(
Result.bitWidth())
575 S.report(
Loc, diag::warn_integer_constant_overflow)
580 S.CCEDiag(E, diag::note_constexpr_overflow) << APResult <<
Type;
581 return S.noteUndefinedBehavior();
588template <PrimType Name, class T = typename PrimConv<Name>::T>
596 return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr);
602template <PrimType Name, class T = typename PrimConv<Name>::T>
610 return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr);
617template <PrimType Name, class T = typename PrimConv<Name>::T>
625 return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr);
631template <PrimType Name, class T = typename PrimConv<Name>::T>
639 return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr);
642template <IncDecOp Op, PushVal DoPush>
644 llvm::RoundingMode RM) {
651 llvm::APFloat::opStatus Status;
669 return IncDecFloatHelper<IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, RM);
679 return IncDecFloatHelper<IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, RM);
691 return IncDecFloatHelper<IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, RM);
702 return IncDecFloatHelper<IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, RM);
707template <PrimType Name, class T = typename PrimConv<Name>::T>
709 const T &Val = S.Stk.pop<
T>();
711 if (!T::comp(Val, &
Result)) {
728 const T &RHS = S.Stk.pop<
T>();
729 const T &LHS = S.Stk.pop<
T>();
730 S.Stk.push<BoolT>(BoolT::from(Fn(LHS.compare(RHS))));
736 return CmpHelper<T>(S, OpPC, Fn);
747 S.FFDiag(
Loc, diag::note_constexpr_pointer_comparison_unspecified)
749 << RHS.toDiagnosticString(S.getCtx());
760 for (
const auto &FP : {LHS, RHS}) {
763 S.FFDiag(
Loc, diag::note_constexpr_pointer_weak_comparison)
764 << FP.toDiagnosticString(S.getCtx());
781 S.FFDiag(
Loc, diag::note_constexpr_pointer_comparison_unspecified)
782 << LHS.toDiagnosticString(S.getCtx())
786 unsigned VL = LHS.getByteOffset();
788 S.Stk.push<BoolT>(BoolT::from(Fn(
Compare(VL, VR))));
799 if (LHS.isZero() && RHS.
isZero()) {
804 for (
const auto &
P : {LHS, RHS}) {
809 S.FFDiag(
Loc, diag::note_constexpr_pointer_weak_comparison)
810 <<
P.toDiagnosticString(S.getCtx());
819 unsigned VL = LHS.getByteOffset();
826 if (!LHS.isZero() && LHS.isArrayRoot())
827 VL = LHS.atIndex(0).getByteOffset();
831 S.Stk.push<BoolT>(BoolT::from(Fn(
Compare(VL, VR))));
836template <PrimType Name, class T = typename PrimConv<Name>::T>
843template <PrimType Name, class T = typename PrimConv<Name>::T>
845 const T &RHS = S.Stk.pop<
T>();
846 const T &LHS = S.Stk.pop<
T>();
853 S.FFDiag(
Loc, diag::note_constexpr_pointer_comparison_unspecified)
854 << LHS.toDiagnosticString(S.getCtx())
855 << RHS.toDiagnosticString(S.getCtx());
860 const auto *CmpValueInfo =
862 assert(CmpValueInfo);
863 assert(CmpValueInfo->hasValidIntValue());
867template <PrimType Name, class T = typename PrimConv<Name>::T>
874template <PrimType Name, class T = typename PrimConv<Name>::T>
881template <PrimType Name, class T = typename PrimConv<Name>::T>
889template <PrimType Name, class T = typename PrimConv<Name>::T>
896template <PrimType Name, class T = typename PrimConv<Name>::T>
908template <PrimType Name, class T = typename PrimConv<Name>::T>
910 const T RHS = S.Stk.pop<
T>();
911 const T LHS = S.Stk.pop<
T>();
912 const T Value = S.Stk.pop<
T>();
914 S.Stk.push<
bool>(LHS <=
Value &&
Value <= RHS);
922template <PrimType Name, class T = typename PrimConv<Name>::T>
924 S.Stk.push<
T>(S.Stk.peek<
T>());
928template <PrimType Name, class T = typename PrimConv<Name>::T>
938template <PrimType Name, class T = typename PrimConv<Name>::T>
948template <PrimType Name, class T = typename PrimConv<Name>::T>
950 const Pointer &Ptr = S.Current->getLocalPointer(I);
960template <PrimType Name, class T = typename PrimConv<Name>::T>
962 S.Current->setLocal<
T>(I, S.Stk.pop<
T>());
966template <PrimType Name, class T = typename PrimConv<Name>::T>
968 if (S.checkingPotentialConstantExpression()) {
971 S.Stk.push<
T>(S.Current->getParam<
T>(I));
975template <PrimType Name, class T = typename PrimConv<Name>::T>
977 S.Current->setParam<
T>(I, S.Stk.pop<
T>());
983template <PrimType Name, class T = typename PrimConv<Name>::T>
993 S.Stk.push<
T>(Field.deref<
T>());
997template <PrimType Name, class T = typename PrimConv<Name>::T>
999 const T &
Value = S.Stk.pop<
T>();
1005 const Pointer &Field = Obj.atField(I);
1009 Field.deref<
T>() =
Value;
1015template <PrimType Name, class T = typename PrimConv<Name>::T>
1025 S.Stk.push<
T>(Field.deref<
T>());
1029template <PrimType Name, class T = typename PrimConv<Name>::T>
1031 if (S.checkingPotentialConstantExpression())
1039 S.Stk.push<
T>(Field.deref<
T>());
1043template <PrimType Name, class T = typename PrimConv<Name>::T>
1045 if (S.checkingPotentialConstantExpression())
1047 const T &
Value = S.Stk.pop<
T>();
1054 Field.deref<
T>() =
Value;
1058template <PrimType Name, class T = typename PrimConv<Name>::T>
1060 const Pointer &Ptr = S.P.getPtrGlobal(I);
1071 S.Stk.push<
T>(Ptr.
deref<
T>());
1076template <PrimType Name, class T = typename PrimConv<Name>::T>
1078 auto *B = S.P.getGlobal(I);
1079 S.Stk.push<
T>(B->deref<
T>());
1083template <PrimType Name, class T = typename PrimConv<Name>::T>
1089template <PrimType Name, class T = typename PrimConv<Name>::T>
1091 const Pointer &
P = S.P.getGlobal(I);
1092 P.deref<
T>() = S.Stk.pop<
T>();
1100template <PrimType Name, class T = typename PrimConv<Name>::T>
1104 const T Value = S.Stk.peek<
T>();
1109 const Pointer &
P = S.P.getGlobal(I);
1110 P.deref<
T>() = S.Stk.pop<
T>();
1125 if (std::optional<APValue> APV =
P.toRValue(S.getCtx())) {
1133template <PrimType Name, class T = typename PrimConv<Name>::T>
1135 if (S.checkingPotentialConstantExpression())
1141 Field.deref<
T>() = S.Stk.pop<
T>();
1148template <PrimType Name, class T = typename PrimConv<Name>::T>
1150 uint32_t FieldOffset) {
1151 assert(F->isBitField());
1152 if (S.checkingPotentialConstantExpression())
1158 const auto &
Value = S.Stk.pop<
T>();
1159 Field.deref<
T>() =
Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
1164template <PrimType Name, class T = typename PrimConv<Name>::T>
1166 if (S.checkingPotentialConstantExpression())
1172 Field.deref<
T>() = S.Stk.pop<
T>();
1181template <PrimType Name, class T = typename PrimConv<Name>::T>
1183 const T &
Value = S.Stk.pop<
T>();
1185 Field.deref<
T>() =
Value;
1191template <PrimType Name, class T = typename PrimConv<Name>::T>
1193 assert(F->isBitField());
1194 const T &
Value = S.Stk.pop<
T>();
1196 Field.deref<
T>() =
Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
1202template <PrimType Name, class T = typename PrimConv<Name>::T>
1204 const T &
Value = S.Stk.pop<
T>();
1206 const Pointer &Field = Ptr.atField(I);
1207 Field.deref<
T>() =
Value;
1218 S.Stk.push<
Pointer>(S.Current->getLocalPointer(I));
1223 if (S.checkingPotentialConstantExpression()) {
1226 S.Stk.push<
Pointer>(S.Current->getParamPointer(I));
1231 S.Stk.push<
Pointer>(S.P.getPtrGlobal(I));
1240 if (S.getLangOpts().CPlusPlus && S.inConstantContext() &&
1259 if (S.checkingPotentialConstantExpression())
1277 S.Stk.push<
Pointer>(std::move(Field));
1282 if (S.checkingPotentialConstantExpression())
1290 S.Stk.push<
Pointer>(std::move(Field));
1325 if (S.checkingPotentialConstantExpression())
1357 while (
Base.isBaseClass())
1360 const Record::Base *VirtBase =
Base.getRecord()->getVirtualBase(
Decl);
1361 S.Stk.push<
Pointer>(
Base.atField(VirtBase->Offset));
1380 if (S.checkingPotentialConstantExpression())
1392template <PrimType Name, class T = typename PrimConv<Name>::T>
1399 S.Stk.push<
T>(Ptr.
deref<
T>());
1403template <PrimType Name, class T = typename PrimConv<Name>::T>
1410 S.Stk.push<
T>(Ptr.
deref<
T>());
1414template <PrimType Name, class T = typename PrimConv<Name>::T>
1416 const T &
Value = S.Stk.pop<
T>();
1420 if (Ptr.canBeInitialized())
1426template <PrimType Name, class T = typename PrimConv<Name>::T>
1428 const T &
Value = S.Stk.pop<
T>();
1432 if (Ptr.canBeInitialized())
1438template <PrimType Name, class T = typename PrimConv<Name>::T>
1440 const T &
Value = S.Stk.pop<
T>();
1444 if (Ptr.canBeInitialized())
1446 if (
const auto *FD = Ptr.getField())
1447 Ptr.deref<
T>() =
Value.truncate(FD->getBitWidthValue(S.getCtx()));
1453template <PrimType Name, class T = typename PrimConv<Name>::T>
1455 const T &
Value = S.Stk.pop<
T>();
1459 if (Ptr.canBeInitialized())
1461 if (
const auto *FD = Ptr.getField())
1462 Ptr.deref<
T>() =
Value.truncate(FD->getBitWidthValue(S.getCtx()));
1468template <PrimType Name, class T = typename PrimConv<Name>::T>
1470 const T &
Value = S.Stk.pop<
T>();
1477 new (&Ptr.deref<
T>())
T(
Value);
1481template <PrimType Name, class T = typename PrimConv<Name>::T>
1483 const T &
Value = S.Stk.pop<
T>();
1488 new (&Ptr.deref<
T>())
T(
Value);
1495template <PrimType Name, class T = typename PrimConv<Name>::T>
1497 const T &
Value = S.Stk.pop<
T>();
1499 if (Ptr.isUnknownSizeArray())
1504 new (&Ptr.deref<
T>())
T(
Value);
1509template <PrimType Name, class T = typename PrimConv<Name>::T>
1511 const T &
Value = S.Stk.pop<
T>();
1513 if (Ptr.isUnknownSizeArray())
1518 new (&Ptr.deref<
T>())
T(
Value);
1529 return DoMemcpy(S, OpPC, Src, Dest);
1536template <
class T, ArithOp Op>
1543 if (Offset.isZero()) {
1551 if (S.getLangOpts().CPlusPlus)
1560 uint64_t MaxIndex =
static_cast<uint64_t
>(Ptr.
getNumElems());
1564 auto DiagInvalidOffset = [&]() ->
void {
1565 const unsigned Bits = Offset.bitWidth();
1566 APSInt APOffset(Offset.toAPSInt().extend(Bits + 2),
false);
1570 (Op ==
ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
1571 S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
1572 << NewIndex <<
static_cast<int>(!Ptr.
inArray()) << MaxIndex;
1577 uint64_t IOffset =
static_cast<uint64_t
>(Offset);
1578 uint64_t MaxOffset = MaxIndex - Index;
1582 if (Offset.isNegative() && (Offset.isMin() || -IOffset > Index))
1583 DiagInvalidOffset();
1586 if (Offset.isPositive() && IOffset > MaxOffset)
1587 DiagInvalidOffset();
1590 if (Offset.isPositive() && Index < IOffset)
1591 DiagInvalidOffset();
1594 if (Offset.isNegative() && (Offset.isMin() || -IOffset > MaxOffset))
1595 DiagInvalidOffset();
1599 if (
Invalid && S.getLangOpts().CPlusPlus)
1603 int64_t WideIndex =
static_cast<int64_t
>(Index);
1604 int64_t WideOffset =
static_cast<int64_t
>(Offset);
1607 Result = WideIndex + WideOffset;
1609 Result = WideIndex - WideOffset;
1615template <PrimType Name, class T = typename PrimConv<Name>::T>
1617 const T &Offset = S.Stk.pop<
T>();
1619 return OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr);
1622template <PrimType Name, class T = typename PrimConv<Name>::T>
1624 const T &Offset = S.Stk.pop<
T>();
1626 return OffsetHelper<T, ArithOp::Sub>(S, OpPC, Offset, Ptr);
1629template <ArithOp Op>
1645 OneT One = OneT::from(1);
1646 if (!OffsetHelper<OneT, Op>(S, OpPC, One,
P))
1660 return IncDecPtrHelper<ArithOp::Add>(S, OpPC, Ptr);
1669 return IncDecPtrHelper<ArithOp::Sub>(S, OpPC, Ptr);
1675template <PrimType Name, class T = typename PrimConv<Name>::T>
1690 if (LHS.
isZero() && RHS.isZero()) {
1696 T B = T::from(RHS.getIndex());
1697 return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, A.bitWidth(), A, B);
1705 S.Current->destroy(I);
1716 S.Stk.push<
U>(U::from(S.Stk.pop<
T>()));
1723 llvm::RoundingMode RM) {
1732template <PrimType Name, class T = typename PrimConv<Name>::T>
1739template <PrimType Name, class T = typename PrimConv<Name>::T>
1746template <PrimType Name, class T = typename PrimConv<Name>::T>
1748 const llvm::fltSemantics *Sem,
1749 llvm::RoundingMode RM) {
1750 const T &From = S.Stk.pop<
T>();
1751 APSInt FromAP = From.toAPSInt();
1760template <PrimType Name, class T = typename PrimConv<Name>::T>
1764 if constexpr (std::is_same_v<T, Boolean>) {
1773 if ((Status & APFloat::opStatus::opInvalidOp)) {
1774 const Expr *E = S.Current->getExpr(OpPC);
1777 S.CCEDiag(E, diag::note_constexpr_overflow) << F.
getAPFloat() <<
Type;
1778 if (S.noteUndefinedBehavior()) {
1791 uint32_t BitWidth) {
1798 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite()) {
1799 const Expr *E = S.Current->getExpr(OpPC);
1802 S.CCEDiag(E, diag::note_constexpr_overflow) << F.
getAPFloat() <<
Type;
1803 return S.noteUndefinedBehavior();
1811 uint32_t BitWidth) {
1818 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite()) {
1819 const Expr *E = S.Current->getExpr(OpPC);
1822 S.CCEDiag(E, diag::note_constexpr_overflow) << F.
getAPFloat() <<
Type;
1823 return S.noteUndefinedBehavior();
1830template <PrimType Name, class T = typename PrimConv<Name>::T>
1834 const SourceInfo &E = S.Current->getSource(OpPC);
1835 S.CCEDiag(E, diag::note_constexpr_invalid_cast)
1836 << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
1843 uint32_t BitWidth) {
1846 const SourceInfo &E = S.Current->getSource(OpPC);
1847 S.CCEDiag(E, diag::note_constexpr_invalid_cast)
1848 << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
1856 uint32_t BitWidth) {
1859 const SourceInfo &E = S.Current->getSource(OpPC);
1860 S.CCEDiag(E, diag::note_constexpr_invalid_cast)
1861 << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
1872template <PrimType Name, class T = typename PrimConv<Name>::T>
1874 S.Stk.push<
T>(T::zero());
1888template <PrimType Name, class T = typename PrimConv<Name>::T>
1891 S.Stk.push<
T>(0, Desc);
1901 if (S.checkingPotentialConstantExpression()) {
1910 if (!
This.isDummy()) {
1911 assert(isa<CXXMethodDecl>(S.Current->getFunction()->getDecl()));
1912 assert(
This.getRecord());
1914 This.getRecord()->getDecl() ==
1915 cast<CXXMethodDecl>(S.Current->getFunction()->getDecl())->getParent());
1923 assert(S.Current->getFunction()->hasRVO());
1924 if (S.checkingPotentialConstantExpression())
1926 S.Stk.push<
Pointer>(S.Current->getRVOPtr());
1934template <PrimType NameL, PrimType NameR>
1938 auto RHS = S.Stk.pop<RT>();
1939 const auto &LHS = S.Stk.pop<
LT>();
1940 const unsigned Bits = LHS.bitWidth();
1943 if (S.getLangOpts().OpenCL)
1944 RT::bitAnd(RHS, RT::from(LHS.bitWidth() - 1, RHS.bitWidth()),
1945 RHS.bitWidth(), &RHS);
1953 typename LT::AsUnsigned R;
1954 if (RHS > RT::from(Bits - 1, RHS.bitWidth()))
1955 LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),
1956 LT::AsUnsigned::from(Bits - 1), Bits, &R);
1958 LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),
1959 LT::AsUnsigned::from(RHS, Bits), Bits, &R);
1960 S.Stk.push<
LT>(LT::from(R));
1964template <PrimType NameL, PrimType NameR>
1968 auto RHS = S.Stk.pop<RT>();
1969 const auto &LHS = S.Stk.pop<
LT>();
1970 const unsigned Bits = LHS.bitWidth();
1973 if (S.getLangOpts().OpenCL)
1974 RT::bitAnd(RHS, RT::from(LHS.bitWidth() - 1, RHS.bitWidth()),
1975 RHS.bitWidth(), &RHS);
1983 typename LT::AsUnsigned R;
1984 if (RHS > RT::from(Bits - 1, RHS.bitWidth()))
1985 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
1986 LT::AsUnsigned::from(Bits - 1), Bits, &R);
1988 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
1989 LT::AsUnsigned::from(RHS, Bits), Bits, &R);
1991 S.Stk.push<
LT>(LT::from(R));
2001 S.FFDiag(EndLoc, diag::note_constexpr_no_return);
2029template <PrimType Name, class T = typename PrimConv<Name>::T>
2031 const T &Offset = S.Stk.pop<
T>();
2034 if (!Ptr.isZero()) {
2039 if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
2045template <PrimType Name, class T = typename PrimConv<Name>::T>
2047 const T &Offset = S.Stk.pop<
T>();
2050 if (!Ptr.isZero()) {
2055 if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
2061template <PrimType Name, class T = typename PrimConv<Name>::T>
2072template <PrimType Name, class T = typename PrimConv<Name>::T>
2083template <PrimType Name, class T = typename PrimConv<Name>::T>
2085 const auto &SrcPtr = S.Stk.pop<
Pointer>();
2086 const auto &DestPtr = S.Stk.peek<
Pointer>();
2088 for (uint32_t I = 0; I != Size; ++I) {
2119 const SourceInfo &E = S.Current->getSource(OpPC);
2120 S.FFDiag(E, diag::note_constexpr_unsupported_unsized_array);
2126 uint32_t VarArgSize) {
2127 if (
Func->hasThisPointer()) {
2128 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2136 if (!(S.Current->getFunction() &&
2137 S.Current->getFunction()->isLambdaStaticInvoker() &&
2138 Func->isLambdaCallOperator())) {
2143 if (S.checkingPotentialConstantExpression())
2153 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC, VarArgSize);
2155 S.Current = NewFrame.get();
2163 assert(S.Current == FrameBefore);
2169 S.Current = FrameBefore;
2176 uint32_t VarArgSize) {
2177 if (
Func->hasThisPointer()) {
2178 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2187 if (!(S.Current->getFunction() &&
2188 S.Current->getFunction()->isLambdaStaticInvoker() &&
2189 Func->isLambdaCallOperator())) {
2194 if (S.checkingPotentialConstantExpression())
2204 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC, VarArgSize);
2206 S.Current = NewFrame.get();
2214 assert(S.Current == FrameBefore);
2220 S.Current = FrameBefore;
2225 uint32_t VarArgSize) {
2226 assert(
Func->hasThisPointer());
2227 assert(
Func->isVirtual());
2228 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2235 DynamicDecl =
DynamicType->getPointeeCXXRecordDecl();
2237 DynamicDecl = ThisPtr.getDeclDesc()->getType()->getAsCXXRecordDecl();
2238 const auto *StaticDecl = cast<CXXRecordDecl>(
Func->getParentDecl());
2239 const auto *InitialFunction = cast<CXXMethodDecl>(
Func->getDecl());
2240 const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
2241 DynamicDecl, StaticDecl, InitialFunction);
2243 if (Overrider != InitialFunction) {
2247 if (!S.getLangOpts().CPlusPlus20 && Overrider->
isVirtual()) {
2248 const Expr *E = S.Current->getExpr(OpPC);
2249 S.CCEDiag(E, diag::note_constexpr_virtual_call) << E->
getSourceRange();
2252 Func = S.getContext().getOrCreateFunction(Overrider);
2255 ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
2256 if (
Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
2260 ThisPtr = ThisPtr.getDeclPtr();
2264 return Call(S, OpPC,
Func, VarArgSize);
2269 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, PC);
2272 S.Current = NewFrame.get();
2278 S.Current = FrameBefore;
2288 const Expr *E = S.Current->getExpr(OpPC);
2289 S.FFDiag(E, diag::note_constexpr_null_callee)
2300 if (F->hasNonNullAttr()) {
2305 assert(ArgSize >= F->getWrittenArgSize());
2306 uint32_t VarArgSize = ArgSize - F->getWrittenArgSize();
2309 return CallVirt(S, OpPC, F, VarArgSize);
2311 return Call(S, OpPC, F, VarArgSize);
2320template <PrimType Name, class T = typename PrimConv<Name>::T>
2322 const T &IntVal = S.Stk.pop<
T>();
2324 S.Stk.push<
Pointer>(
static_cast<uint64_t
>(IntVal), Desc);
2332 S.FFDiag(
Loc, diag::note_invalid_subexpr_in_const_expr)
2333 << S.Current->getRange(OpPC);
2346 S.FFDiag(
Loc, diag::note_constexpr_invalid_cast)
2347 <<
static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
2358 const auto Val = S.Stk.pop<
Boolean>();
2365 S.CCEDiag(
Loc, diag::note_constexpr_assumption_failed);
2369template <PrimType Name, class T = typename PrimConv<Name>::T>
2373 ArrayIndices.emplace_back(S.Stk.pop<int64_t>());
2379 S.Stk.push<
T>(T::from(
Result));
2384template <PrimType Name, class T = typename PrimConv<Name>::T>
2386 const T &Arg = S.Stk.peek<
T>();
2391 S.CCEDiag(
Loc, diag::note_non_null_attribute_failed);
2397template <PrimType TIn, PrimType TOut>
2403 const FromT &OldPtr = S.Stk.pop<FromT>();
2404 S.Stk.push<ToT>(ToT(OldPtr.getIntegerRepresentation(),
nullptr));
2413 if constexpr (std::is_pointer<T>::value) {
2414 uint32_t
ID = OpPC.
read<uint32_t>();
2415 return reinterpret_cast<T>(S.P.getNativePointer(
ID));
2417 return OpPC.
read<
T>();
2428inline IntegralAP<false> ReadArg<IntegralAP<false>>(InterpState &S,
2431 OpPC +=
align(I.bytesToSerialize());
2436inline IntegralAP<true> ReadArg<IntegralAP<true>>(InterpState &S,
2439 OpPC +=
align(I.bytesToSerialize());
Defines the clang::ASTContext interface.
ASTImporterLookupTable & LT
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
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]).
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.
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...
Implicit declaration of a temporary that was materialized by a MaterializeTemporaryExpr and lifetime-...
APValue * getOrCreateValue(bool MayCreate) const
Get the storage for the constant value of a materialized temporary of static storage duration.
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
unsigned getNumExpressions() const
A (possibly-)qualified type.
Represents a struct/union/class.
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
The base class of the type hierarchy.
unsigned getSize() const
Returns the size of the block.
Wrapper around boolean types.
static bool inv(Boolean A, Boolean *R)
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.
static APFloat::opStatus div(const Floating &A, const Floating &B, llvm::RoundingMode RM, Floating *R)
static Floating deserialize(const std::byte *Buff)
static APFloat::opStatus sub(const Floating &A, const Floating &B, llvm::RoundingMode RM, Floating *R)
const APFloat & getAPFloat() const
static APFloat::opStatus increment(const Floating &A, llvm::RoundingMode RM, Floating *R)
static APFloat::opStatus fromIntegral(APSInt Val, const llvm::fltSemantics &Sem, llvm::RoundingMode RM, Floating &Result)
Floating toSemantics(const llvm::fltSemantics *Sem, llvm::RoundingMode RM) const
size_t bytesToSerialize() const
static APFloat::opStatus add(const Floating &A, const Floating &B, llvm::RoundingMode RM, Floating *R)
static APFloat::opStatus mul(const Floating &A, const Floating &B, llvm::RoundingMode RM, Floating *R)
static APFloat::opStatus decrement(const Floating &A, llvm::RoundingMode RM, Floating *R)
APFloat::opStatus convertToInteger(APSInt &Result) const
const Function * getFunction() const
ComparisonCategoryResult compare(const FunctionPointer &RHS) const
std::string toDiagnosticString(const ASTContext &Ctx) const
static IntegralAP< Signed > deserialize(const std::byte *Buff)
static IntegralAP zero(int32_t BitWidth)
static IntegralAP from(T Value, unsigned NumBits=0)
Wrapper around numeric types.
Frame storing local variables.
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.
void deactivate() const
Deactivates an entire strurcutre.
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
bool isDummy() const
Checks if the pointer points to a dummy value.
Pointer atFieldSub(unsigned Off) const
Subtract the given offset from the current Base and Offset of the pointer.
bool isExtern() const
Checks if the storage is extern.
int64_t getIndex() const
Returns the index into an array.
Pointer atField(unsigned Off) const
Creates a pointer to a field.
T & deref() const
Dereferences the pointer, if it's live.
unsigned getNumElems() const
Returns the number of elements.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
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.
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.
ComparisonCategoryResult compare(const Pointer &Other) const
Compare two pointers.
uint64_t getIntegerRepresentation() const
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
bool isBlockPointer() const
const Block * block() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
void initialize() const
Initializes a field.
unsigned getByteOffset() const
Returns the byte offset from the start.
Describes the statement/declaration an opcode was generated from.
bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS, unsigned Bits)
Checks if the shift operation is legal.
bool InitPop(InterpState &S, CodePtr OpPC)
bool Inv(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 IncPop(InterpState &S, CodePtr OpPC)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index)
bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off)
bool Subf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
bool ArrayElem(InterpState &S, CodePtr OpPC, uint32_t Index)
bool GT(InterpState &S, CodePtr OpPC)
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
bool DecPop(InterpState &S, CodePtr OpPC)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value decreased by ...
bool GetThisField(InterpState &S, CodePtr OpPC, uint32_t I)
bool NarrowPtr(InterpState &S, CodePtr OpPC)
bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I)
bool Interpret(InterpState &S, APValue &Result)
Interpreter entry point.
Floating ReadArg< Floating >(InterpState &S, CodePtr &OpPC)
static bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
bool GetParam(InterpState &S, CodePtr OpPC, uint32_t I)
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 LoadPop(InterpState &S, CodePtr OpPC)
bool DecfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
static bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
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 Dup(InterpState &S, CodePtr OpPC)
bool CheckCallDepth(InterpState &S, CodePtr OpPC)
Checks if calling the currently active function would exceed the allowed call depth.
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks the 'this' pointer.
bool SetField(InterpState &S, CodePtr OpPC, uint32_t I)
bool CheckNonNullArg(InterpState &S, CodePtr OpPC)
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, llvm::ArrayRef< int64_t > ArrayIndices, int64_t &Result)
Interpret an offsetof operation.
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}_ordering type.
static bool IncDecPtrHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
bool GetPtrLocal(InterpState &S, CodePtr OpPC, uint32_t I)
static bool CastFloatingIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
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.
bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS, const T &RHS)
bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off)
1) Pops a Pointer from the stack 2) Pushes Pointer.atField(Off) on the stack
bool Div(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func)
bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I)
Same as GetGlobal, but without the checks.
bool GetPtrActiveThisField(InterpState &S, CodePtr OpPC, uint32_t Off)
bool SubPtr(InterpState &S, CodePtr OpPC)
1) Pops a Pointer from the stack.
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if Ptr is a one-past-the-end pointer.
static bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool ReturnValue(const T &V, APValue &R)
Convert a value to an APValue.
bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool ArrayElemPtr(InterpState &S, CodePtr OpPC)
bool NE(InterpState &S, CodePtr OpPC)
bool NoRet(InterpState &S, CodePtr OpPC)
bool GetIntPtr(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
static bool ZeroIntAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool Addf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
bool Shl(InterpState &S, CodePtr OpPC)
bool RVOPtr(InterpState &S, CodePtr OpPC)
bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
bool CastPointerIntegral(InterpState &S, CodePtr OpPC)
constexpr bool isPtrType(PrimType T)
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 CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
bool CastAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool ExpandPtr(InterpState &S, CodePtr OpPC)
bool InitThisFieldActive(InterpState &S, CodePtr OpPC, uint32_t I)
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
bool Store(InterpState &S, CodePtr OpPC)
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 Mulf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
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 IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr, llvm::RoundingMode RM)
bool CopyArray(InterpState &S, CodePtr OpPC, uint32_t SrcIndex, uint32_t DestIndex, uint32_t Size)
bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn)
llvm::function_ref< bool(ComparisonCategoryResult)> CompareFn
T ReadArg(InterpState &S, CodePtr &OpPC)
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
bool ArrayDecay(InterpState &S, CodePtr OpPC)
Just takes a pointer and checks if it's an incomplete array type.
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 IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
bool CastFloatingIntegral(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 CastIntegralFloating(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, llvm::RoundingMode RM)
bool LE(InterpState &S, CodePtr OpPC)
bool Zero(InterpState &S, CodePtr OpPC)
bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F, uint32_t FieldOffset)
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be stored in a block.
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
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 SetThisField(InterpState &S, CodePtr OpPC, uint32_t I)
bool StoreBitFieldPop(InterpState &S, CodePtr OpPC)
bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
static bool DecPtr(InterpState &S, CodePtr OpPC)
bool InitFieldActive(InterpState &S, CodePtr OpPC, uint32_t I)
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 CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be loaded from a block.
bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
bool Dump(InterpState &S, CodePtr OpPC)
bool Null(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
static bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off)
bool GetPtrActiveField(InterpState &S, CodePtr OpPC, uint32_t Off)
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Check if a global variable is initialized.
bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off)
bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *CE, unsigned ArgSize)
Checks if all the arguments annotated as 'nonnull' are in fact not null.
bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off)
bool SetParam(InterpState &S, CodePtr OpPC, uint32_t I)
bool CmpHelper< FunctionPointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
Function pointers cannot be compared in an ordered way.
bool Comp(InterpState &S, CodePtr OpPC)
1) Pops the value from the stack.
bool DecayPtr(InterpState &S, CodePtr OpPC)
OldPtr -> Integer -> NewPtr.
bool GetPtrVirtBasePop(InterpState &S, CodePtr OpPC, const RecordDecl *D)
bool StorePop(InterpState &S, CodePtr OpPC)
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC)
bool CallBI(InterpState &S, CodePtr &PC, const Function *Func, const CallExpr *CE)
bool SetLocal(InterpState &S, CodePtr OpPC, uint32_t I)
1) Pops the value from the stack.
bool FinishInit(InterpState &S, CodePtr OpPC)
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 InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind)
Same here, but only for casts.
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F)
bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR)
bool FinishInitPop(InterpState &S, CodePtr OpPC)
bool InRange(InterpState &S, CodePtr OpPC)
bool CmpHelperEQ< FunctionPointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
bool Neg(InterpState &S, CodePtr OpPC)
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call)
Interpret a builtin function.
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
bool Divf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
bool BitOr(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool Load(InterpState &S, CodePtr OpPC)
bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool Cast(InterpState &S, CodePtr OpPC)
bool EQ(InterpState &S, CodePtr OpPC)
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 CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
Checks if a method can be called.
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer is a dummy pointer.
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 Memcpy(InterpState &S, CodePtr OpPC)
bool GE(InterpState &S, CodePtr OpPC)
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, const CallExpr *CE)
bool CmpHelperEQ< Pointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
constexpr bool isIntegralType(PrimType T)
bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
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 GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t I)
bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D)
bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool RetVoid(InterpState &S, CodePtr &PC, APValue &Result)
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 CmpHelper< Pointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
bool Assume(InterpState &S, CodePtr OpPC)
bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a method can be invoked on an object.
bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off)
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result, APFloat::opStatus Status)
Checks if the result of a floating-point operation is valid in the current context.
bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, const Pointer &Ptr)
The JSON file list parser is used to communicate input to InstallAPI.
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
CheckSubobjectKind
The order of this enum is important for diagnostics.
@ Result
The result type of a method or function.
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
const FunctionProtoType * T
Describes a memory block created by an allocation site.
Mapping from primitive types to their representation.