13 #ifndef LLVM_CLANG_AST_INTERP_INTERP_H
14 #define LLVM_CLANG_AST_INTERP_INTERP_H
28 #include "llvm/ADT/APFloat.h"
29 #include "llvm/ADT/APSInt.h"
30 #include "llvm/Support/Endian.h"
32 #include <type_traits>
48 bool CheckExtern(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
51 bool CheckArray(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
54 bool CheckLive(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
57 bool CheckNull(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
61 bool CheckRange(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
65 bool CheckRange(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
69 bool CheckConst(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
72 bool CheckMutable(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
75 bool CheckLoad(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
78 bool CheckStore(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
81 bool CheckInvoke(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
84 bool CheckInit(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
87 bool CheckCallable(InterpState &S, CodePtr OpPC, Function *F);
90 bool CheckThis(InterpState &S, CodePtr OpPC,
const Pointer &
This);
95 template <
typename T>
inline bool IsTrue(
const T &
V) {
return !
V.isZero(); }
101 template <
typename T,
bool (*OpFW)(T, T,
unsigned, T *),
102 template <typename U>
class OpAP>
107 if (!OpFW(LHS, RHS, Bits, &Result)) {
108 S.Stk.push<T>(Result);
113 S.Stk.push<T>(Result);
116 APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits));
119 const Expr *E = S.Current->getExpr(OpPC);
121 if (S.checkingForUndefinedBehavior()) {
125 S.report(Loc, diag::warn_integer_constant_overflow) <<
Trunc <<
Type;
128 S.CCEDiag(E, diag::note_constexpr_overflow) <<
Value <<
Type;
129 return S.noteUndefinedBehavior();
133 template <PrimType Name, class T = typename PrimConv<Name>::T>
135 const T &RHS = S.Stk.pop<T>();
136 const T &LHS = S.Stk.pop<T>();
137 const unsigned Bits = RHS.bitWidth() + 1;
138 return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
141 template <PrimType Name, class T = typename PrimConv<Name>::T>
143 const T &RHS = S.Stk.pop<T>();
144 const T &LHS = S.Stk.pop<T>();
145 const unsigned Bits = RHS.bitWidth() + 1;
146 return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS);
149 template <PrimType Name, class T = typename PrimConv<Name>::T>
151 const T &RHS = S.Stk.pop<T>();
152 const T &LHS = S.Stk.pop<T>();
153 const unsigned Bits = RHS.bitWidth() * 2;
154 return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS);
163 template <
typename T>
166 const T &RHS = S.Stk.pop<T>();
167 const T &LHS = S.Stk.pop<T>();
168 S.Stk.push<BoolT>(BoolT::from(Fn(LHS.compare(RHS))));
172 template <
typename T>
174 return CmpHelper<T>(S, OpPC, Fn);
184 const SourceInfo &Loc = S.Current->getSource(OpPC);
185 S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
188 unsigned VL = LHS.getByteOffset();
190 S.Stk.push<BoolT>(BoolT::from(Fn(
Compare(VL, VR))));
201 if (LHS.isZero() && RHS.
isZero()) {
210 unsigned VL = LHS.getByteOffset();
212 S.Stk.push<BoolT>(BoolT::from(Fn(
Compare(VL, VR))));
217 template <PrimType Name, class T = typename PrimConv<Name>::T>
224 template <PrimType Name, class T = typename PrimConv<Name>::T>
231 template <PrimType Name, class T = typename PrimConv<Name>::T>
238 template <PrimType Name, class T = typename PrimConv<Name>::T>
246 template <PrimType Name, class T = typename PrimConv<Name>::T>
253 template <PrimType Name, class T = typename PrimConv<Name>::T>
265 template <PrimType Name, class T = typename PrimConv<Name>::T>
267 const T RHS = S.Stk.pop<T>();
268 const T LHS = S.Stk.pop<T>();
269 const T
Value = S.Stk.pop<T>();
271 S.Stk.push<
bool>(LHS <=
Value &&
Value <= RHS);
279 template <PrimType Name, class T = typename PrimConv<Name>::T>
281 S.Stk.push<T>(S.Stk.peek<T>());
285 template <PrimType Name, class T = typename PrimConv<Name>::T>
295 template <PrimType Name, class T = typename PrimConv<Name>::T>
305 template <PrimType Name, class T = typename PrimConv<Name>::T>
307 S.Stk.push<T>(S.Current->getLocal<T>(I));
311 template <PrimType Name, class T = typename PrimConv<Name>::T>
313 S.Current->setLocal<T>(I, S.Stk.pop<T>());
317 template <PrimType Name, class T = typename PrimConv<Name>::T>
319 if (S.checkingPotentialConstantExpression()) {
322 S.Stk.push<T>(S.Current->getParam<T>(I));
326 template <PrimType Name, class T = typename PrimConv<Name>::T>
328 S.Current->setParam<T>(I, S.Stk.pop<T>());
332 template <PrimType Name, class T = typename PrimConv<Name>::T>
342 S.Stk.push<T>(Field.deref<T>());
346 template <PrimType Name, class T = typename PrimConv<Name>::T>
348 const T &
Value = S.Stk.pop<T>();
354 const Pointer &Field = Obj.atField(I);
357 Field.deref<T>() =
Value;
361 template <PrimType Name, class T = typename PrimConv<Name>::T>
371 S.Stk.push<T>(Field.deref<T>());
375 template <PrimType Name, class T = typename PrimConv<Name>::T>
377 if (S.checkingPotentialConstantExpression())
385 S.Stk.push<T>(Field.deref<T>());
389 template <PrimType Name, class T = typename PrimConv<Name>::T>
391 if (S.checkingPotentialConstantExpression())
393 const T &
Value = S.Stk.pop<T>();
400 Field.deref<T>() =
Value;
404 template <PrimType Name, class T = typename PrimConv<Name>::T>
406 auto *B = S.P.getGlobal(I);
409 S.Stk.push<T>(B->deref<T>());
413 template <PrimType Name, class T = typename PrimConv<Name>::T>
419 template <PrimType Name, class T = typename PrimConv<Name>::T>
421 S.P.getGlobal(I)->deref<T>() = S.Stk.pop<T>();
425 template <PrimType Name, class T = typename PrimConv<Name>::T>
427 if (S.checkingPotentialConstantExpression())
433 Field.deref<T>() = S.Stk.pop<T>();
438 template <PrimType Name, class T = typename PrimConv<Name>::T>
440 if (S.checkingPotentialConstantExpression())
446 const auto &
Value = S.Stk.pop<T>();
452 template <PrimType Name, class T = typename PrimConv<Name>::T>
454 if (S.checkingPotentialConstantExpression())
460 Field.deref<T>() = S.Stk.pop<T>();
466 template <PrimType Name, class T = typename PrimConv<Name>::T>
468 const T &
Value = S.Stk.pop<T>();
470 Field.deref<T>() =
Value;
476 template <PrimType Name, class T = typename PrimConv<Name>::T>
478 const T &
Value = S.Stk.pop<T>();
486 template <PrimType Name, class T = typename PrimConv<Name>::T>
488 const T &
Value = S.Stk.pop<T>();
490 const Pointer &Field = Ptr.atField(I);
491 Field.deref<T>() =
Value;
502 S.Stk.push<
Pointer>(S.Current->getLocalPointer(I));
507 if (S.checkingPotentialConstantExpression()) {
510 S.Stk.push<
Pointer>(S.Current->getParamPointer(I));
515 S.Stk.push<
Pointer>(S.P.getPtrGlobal(I));
532 if (S.checkingPotentialConstantExpression())
550 S.Stk.push<
Pointer>(std::move(Field));
555 if (S.checkingPotentialConstantExpression())
563 S.Stk.push<
Pointer>(std::move(Field));
576 if (S.checkingPotentialConstantExpression())
588 while (
Base.isBaseClass())
591 auto *Field =
Base.getRecord()->getVirtualBase(
Decl);
605 if (S.checkingPotentialConstantExpression())
617 template <PrimType Name, class T = typename PrimConv<Name>::T>
622 S.Stk.push<T>(Ptr.
deref<T>());
626 template <PrimType Name, class T = typename PrimConv<Name>::T>
631 S.Stk.push<T>(Ptr.
deref<T>());
635 template <PrimType Name, class T = typename PrimConv<Name>::T>
637 const T &
Value = S.Stk.pop<T>();
645 template <PrimType Name, class T = typename PrimConv<Name>::T>
647 const T &
Value = S.Stk.pop<T>();
655 template <PrimType Name, class T = typename PrimConv<Name>::T>
657 const T &
Value = S.Stk.pop<T>();
661 if (
auto *FD = Ptr.getField()) {
662 Ptr.
deref<T>() =
Value.truncate(FD->getBitWidthValue(S.getCtx()));
664 Ptr.deref<T>() =
Value;
669 template <PrimType Name, class T = typename PrimConv<Name>::T>
671 const T &
Value = S.Stk.pop<T>();
675 if (
auto *FD = Ptr.getField()) {
676 Ptr.
deref<T>() =
Value.truncate(FD->getBitWidthValue(S.getCtx()));
678 Ptr.deref<T>() =
Value;
683 template <PrimType Name, class T = typename PrimConv<Name>::T>
685 const T &
Value = S.Stk.pop<T>();
690 new (&Ptr.deref<T>()) T(
Value);
694 template <PrimType Name, class T = typename PrimConv<Name>::T>
696 const T &
Value = S.Stk.pop<T>();
701 new (&Ptr.deref<T>()) T(
Value);
705 template <PrimType Name, class T = typename PrimConv<Name>::T>
707 const T &
Value = S.Stk.pop<T>();
712 new (&Ptr.deref<T>()) T(
Value);
722 const T &
Offset = S.Stk.pop<T>();
730 T Index = T::from(Ptr.getIndex(),
Offset.bitWidth());
734 S.Stk.push<
Pointer>(Index.isZero() ? Ptr.atIndex(0) : Ptr);
745 auto InvalidOffset = [&]() {
746 const unsigned Bits =
Offset.bitWidth();
747 APSInt APOffset(
Offset.toAPSInt().extend(Bits + 2),
false);
748 APSInt APIndex(Index.toAPSInt().extend(Bits + 2),
false);
749 APSInt NewIndex =
Add ? (APIndex + APOffset) : (APIndex - APOffset);
750 S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
752 <<
static_cast<int>(!Ptr.inArray())
753 <<
static_cast<unsigned>(MaxIndex);
759 return InvalidOffset();
761 return InvalidOffset();
764 unsigned MaxOffset = MaxIndex - Ptr.getIndex();
766 return InvalidOffset();
768 return InvalidOffset();
771 int64_t WideIndex =
static_cast<int64_t
>(Index);
772 int64_t WideOffset =
static_cast<int64_t
>(
Offset);
773 int64_t Result =
Add ? (WideIndex + WideOffset) : (WideIndex - WideOffset);
774 S.Stk.push<
Pointer>(Ptr.atIndex(
static_cast<unsigned>(Result)));
778 template <PrimType Name, class T = typename PrimConv<Name>::T>
780 return OffsetHelper<T, true>(S, OpPC);
783 template <PrimType Name, class T = typename PrimConv<Name>::T>
785 return OffsetHelper<T, false>(S, OpPC);
794 S.Current->destroy(I);
805 S.Stk.push<
U>(U::from(S.Stk.pop<T>()));
813 template <PrimType Name, class T = typename PrimConv<Name>::T>
815 S.Stk.push<T>(T::zero());
819 template <PrimType Name, class T = typename PrimConv<Name>::T>
831 if (S.checkingPotentialConstantExpression()) {
847 template <PrimType TR, PrimType TL, class T = typename PrimConv<TR>::T>
851 if (Bits > 1 &&
V >= T::from(Bits,
V.bitWidth())) {
852 const Expr *E = S.Current->getExpr(OpPC);
853 const APSInt Val =
V.toAPSInt();
855 S.CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty << Bits;
858 return static_cast<unsigned>(
V);
862 template <PrimType TL, PrimType TR, typename T = typename PrimConv<TL>::T>
864 if (RHS >=
V.bitWidth()) {
865 S.Stk.push<T>(T::from(0,
V.bitWidth()));
867 S.Stk.push<T>(T::from(
V >> RHS,
V.bitWidth()));
872 template <PrimType TL, PrimType TR, typename T = typename PrimConv<TL>::T>
874 if (
V.isSigned() && !S.getLangOpts().CPlusPlus20) {
879 if (
V.isNegative()) {
880 const Expr *E = S.Current->getExpr(OpPC);
881 S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) <<
V.toAPSInt();
882 }
else if (
V.countLeadingZeros() < RHS) {
883 S.CCEDiag(S.Current->getExpr(OpPC), diag::note_constexpr_lshift_discards);
887 if (
V.bitWidth() == 1) {
889 }
else if (RHS >=
V.bitWidth()) {
890 S.Stk.push<T>(T::from(0,
V.bitWidth()));
892 S.Stk.push<T>(T::from(
V.toUnsigned() << RHS,
V.bitWidth()));
897 template <PrimType TL, PrimType TR>
901 const unsigned Bits = LHS.bitWidth();
903 if (RHS.isSigned() && RHS.isNegative()) {
904 const SourceInfo &Loc = S.Current->getSource(OpPC);
905 S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
906 return ShiftLeft<TL, TR>(S, OpPC, LHS, Trunc<TR, TL>(S, OpPC, Bits, -RHS));
908 return ShiftRight<TL, TR>(S, OpPC, LHS, Trunc<TR, TL>(S, OpPC, Bits, RHS));
912 template <PrimType TL, PrimType TR>
916 const unsigned Bits = LHS.bitWidth();
918 if (RHS.isSigned() && RHS.isNegative()) {
919 const SourceInfo &Loc = S.Current->getSource(OpPC);
920 S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
921 return ShiftRight<TL, TR>(S, OpPC, LHS, Trunc<TR, TL>(S, OpPC, Bits, -RHS));
923 return ShiftLeft<TL, TR>(S, OpPC, LHS, Trunc<TR, TL>(S, OpPC, Bits, RHS));
933 S.FFDiag(EndLoc, diag::note_constexpr_no_return);
957 template <
typename T>
960 return OpPC.
read<T>();
963 template <
typename T>
966 uint32_t
ID = OpPC.
read<uint32_t>();
967 return reinterpret_cast<T
>(S.P.getNativePointer(
ID));