13#ifndef LLVM_CLANG_AST_INTERP_INTERP_H
14#define LLVM_CLANG_AST_INTERP_INTERP_H
16#include "../ExprConstShared.h"
32#include "llvm/ADT/APFloat.h"
33#include "llvm/ADT/APSInt.h"
39using APSInt = llvm::APSInt;
44 R =
V.toAPValue(S.getCtx());
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,
63bool CheckNull(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
67bool CheckRange(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
71bool CheckRange(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
75bool CheckSubobject(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
80bool CheckDowncast(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
84bool CheckConst(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
87bool CheckConstant(InterpState &S, CodePtr OpPC,
const Descriptor *Desc);
90bool CheckMutable(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
93bool CheckLoad(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
95bool CheckFinalLoad(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
103bool CheckStore(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
106bool CheckInvoke(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
109bool CheckInit(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
112bool CheckCallable(InterpState &S, CodePtr OpPC,
const Function *F);
119bool CheckThis(InterpState &S, CodePtr OpPC,
const Pointer &
This);
126 const CallExpr *CE,
unsigned ArgSize);
134 bool DeleteIsArray,
const Descriptor *
D,
135 const Expr *NewExpr);
145 const Pointer &Ptr,
const APSInt &IntValue);
148bool DoMemcpy(InterpState &S, CodePtr OpPC,
const Pointer &Src, Pointer &Dest);
151template <
typename LT,
typename RT>
154 if (RHS.isNegative()) {
156 S.CCEDiag(
Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
157 if (!S.noteUndefinedBehavior())
163 if (Bits > 1 && RHS >= RT::from(Bits, RHS.bitWidth())) {
164 const Expr *
E = S.Current->getExpr(OpPC);
165 const APSInt Val = RHS.toAPSInt();
167 S.CCEDiag(
E, diag::note_constexpr_large_shift) << Val << Ty << Bits;
168 if (!S.noteUndefinedBehavior())
172 if (LHS.isSigned() && !S.
getLangOpts().CPlusPlus20) {
173 const Expr *
E = S.Current->getExpr(OpPC);
176 if (LHS.isNegative()) {
177 S.CCEDiag(
E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
178 if (!S.noteUndefinedBehavior())
180 }
else if (LHS.toUnsigned().countLeadingZeros() <
181 static_cast<unsigned>(RHS)) {
182 S.CCEDiag(
E, diag::note_constexpr_lshift_discards);
183 if (!S.noteUndefinedBehavior())
198 const auto *Op = cast<BinaryOperator>(S.Current->getExpr(OpPC));
199 if constexpr (std::is_same_v<T, Floating>) {
200 S.CCEDiag(Op, diag::note_expr_divide_by_zero)
201 << Op->getRHS()->getSourceRange();
205 S.FFDiag(Op, diag::note_expr_divide_by_zero)
206 << Op->getRHS()->getSourceRange();
210 if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) {
211 APSInt LHSInt = LHS.toAPSInt();
213 (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10);
215 const Expr *
E = S.Current->getExpr(OpPC);
216 S.CCEDiag(
Loc, diag::note_constexpr_overflow) << Trunc <<
E->
getType();
222template <
typename SizeT>
224 unsigned ElemSize,
bool IsNoThrow) {
233 if (NumElements->toAPSInt().getActiveBits() >
235 *NumElements > MaxElements) {
238 S.FFDiag(
Loc, diag::note_constexpr_new_too_large)
239 << NumElements->toDiagnosticString(S.getCtx());
249 APFloat::opStatus Status);
265inline bool Invalid(InterpState &S, CodePtr OpPC);
275template <PrimType Name, class T = typename PrimConv<Name>::T>
277 const T &
Ret = S.Stk.pop<
T>();
282 if constexpr (std::is_same_v<T, Pointer>) {
287 if (!
Ret.isZero() && !
Ret.isLive())
292 assert(S.Current->getFrameOffset() == S.Stk.size() &&
"Invalid frame");
293 if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
297 PC = S.Current->getRetPC();
311 assert(S.Current->getFrameOffset() == S.Stk.size() &&
"Invalid frame");
313 if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
317 PC = S.Current->getRetPC();
332 template <typename U>
class OpAP>
337 if (!OpFW(LHS, RHS, Bits, &
Result)) {
346 APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits));
349 const Expr *
E = S.Current->getExpr(OpPC);
351 if (S.checkingForUndefinedBehavior()) {
357 S.report(
Loc, diag::warn_integer_constant_overflow)
361 S.CCEDiag(
E, diag::note_constexpr_overflow) <<
Value <<
Type;
363 if (!S.noteUndefinedBehavior()) {
371template <PrimType Name, class T = typename PrimConv<Name>::T>
373 const T &RHS = S.Stk.pop<
T>();
374 const T &LHS = S.Stk.pop<
T>();
375 const unsigned Bits = RHS.bitWidth() + 1;
376 return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
389template <PrimType Name, class T = typename PrimConv<Name>::T>
391 const T &RHS = S.Stk.pop<
T>();
392 const T &LHS = S.Stk.pop<
T>();
393 const unsigned Bits = RHS.bitWidth() + 1;
394 return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS);
407template <PrimType Name, class T = typename PrimConv<Name>::T>
409 const T &RHS = S.Stk.pop<
T>();
410 const T &LHS = S.Stk.pop<
T>();
411 const unsigned Bits = RHS.bitWidth() * 2;
412 return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS);
425template <PrimType Name, class T = typename PrimConv<Name>::T>
431 if constexpr (std::is_same_v<T, Floating>) {
437 APFloat ResR(A.getSemantics());
438 APFloat ResI(A.getSemantics());
443 Result.atIndex(0).initialize();
445 Result.atIndex(1).initialize();
449 const T &LHSR = LHS.atIndex(0).deref<
T>();
450 const T &LHSI = LHS.atIndex(1).deref<
T>();
453 unsigned Bits = LHSR.bitWidth();
457 if (T::mul(LHSR, RHSR, Bits, &A))
460 if (T::mul(LHSI, RHSI, Bits, &B))
462 if (T::sub(A, B, Bits, &
Result.atIndex(0).deref<
T>()))
464 Result.atIndex(0).initialize();
467 if (T::mul(LHSR, RHSI, Bits, &A))
469 if (T::mul(LHSI, RHSR, Bits, &B))
471 if (T::add(A, B, Bits, &
Result.atIndex(1).deref<
T>()))
473 Result.atIndex(1).initialize();
480template <PrimType Name, class T = typename PrimConv<Name>::T>
486 if constexpr (std::is_same_v<T, Floating>) {
492 APFloat ResR(A.getSemantics());
493 APFloat ResI(A.getSemantics());
498 Result.atIndex(0).initialize();
500 Result.atIndex(1).initialize();
504 const T &LHSR = LHS.atIndex(0).deref<
T>();
505 const T &LHSI = LHS.atIndex(1).deref<
T>();
508 unsigned Bits = LHSR.bitWidth();
509 const T Zero = T::from(0, Bits);
514 S.FFDiag(
E, diag::note_expr_divide_by_zero);
520 if (T::mul(RHSR, RHSR, Bits, &A) || T::mul(RHSI, RHSI, Bits, &B))
523 if (T::add(A, B, Bits, &Den))
527 T &ResultR =
Result.atIndex(0).deref<
T>();
528 T &ResultI =
Result.atIndex(1).deref<
T>();
530 if (T::mul(LHSR, RHSR, Bits, &A) || T::mul(LHSI, RHSI, Bits, &B))
532 if (T::add(A, B, Bits, &ResultR))
534 if (T::div(ResultR, Den, Bits, &ResultR))
536 Result.atIndex(0).initialize();
539 if (T::mul(LHSI, RHSR, Bits, &A) || T::mul(LHSR, RHSI, Bits, &B))
541 if (T::sub(A, B, Bits, &ResultI))
543 if (T::div(ResultI, Den, Bits, &ResultI))
545 Result.atIndex(1).initialize();
555template <PrimType Name, class T = typename PrimConv<Name>::T>
557 const T &RHS = S.Stk.pop<
T>();
558 const T &LHS = S.Stk.pop<
T>();
560 unsigned Bits = RHS.bitWidth();
562 if (!T::bitAnd(LHS, RHS, Bits, &
Result)) {
572template <PrimType Name, class T = typename PrimConv<Name>::T>
574 const T &RHS = S.Stk.pop<
T>();
575 const T &LHS = S.Stk.pop<
T>();
577 unsigned Bits = RHS.bitWidth();
579 if (!T::bitOr(LHS, RHS, Bits, &
Result)) {
589template <PrimType Name, class T = typename PrimConv<Name>::T>
591 const T &RHS = S.Stk.pop<
T>();
592 const T &LHS = S.Stk.pop<
T>();
594 unsigned Bits = RHS.bitWidth();
596 if (!T::bitXor(LHS, RHS, Bits, &
Result)) {
606template <PrimType Name, class T = typename PrimConv<Name>::T>
608 const T &RHS = S.Stk.pop<
T>();
609 const T &LHS = S.Stk.pop<
T>();
614 const unsigned Bits = RHS.bitWidth() * 2;
616 if (!T::rem(LHS, RHS, Bits, &
Result)) {
626template <PrimType Name, class T = typename PrimConv<Name>::T>
628 const T &RHS = S.Stk.pop<
T>();
629 const T &LHS = S.Stk.pop<
T>();
634 const unsigned Bits = RHS.bitWidth() * 2;
636 if (!T::div(LHS, RHS, Bits, &
Result)) {
661 const auto &Val = S.Stk.pop<
Boolean>();
670template <PrimType Name, class T = typename PrimConv<Name>::T>
672 const T &
Value = S.Stk.pop<
T>();
681 "don't expect other types to fail at constexpr negation");
685 const Expr *
E = S.Current->getExpr(OpPC);
688 if (S.checkingForUndefinedBehavior()) {
690 NegatedValue.trunc(
Result.bitWidth())
694 S.report(
Loc, diag::warn_integer_constant_overflow)
699 S.CCEDiag(
E, diag::note_constexpr_overflow) << NegatedValue <<
Type;
700 return S.noteUndefinedBehavior();
712template <
typename T, IncDecOp Op, PushVal DoPush>
716 if constexpr (std::is_same_v<T, Boolean>) {
741 unsigned Bits =
Value.bitWidth() + 1;
744 APResult = ++
Value.toAPSInt(Bits);
746 APResult = --
Value.toAPSInt(Bits);
749 const Expr *
E = S.Current->getExpr(OpPC);
751 if (S.checkingForUndefinedBehavior()) {
753 APResult.trunc(
Result.bitWidth())
757 S.report(
Loc, diag::warn_integer_constant_overflow)
762 S.CCEDiag(
E, diag::note_constexpr_overflow) << APResult <<
Type;
763 return S.noteUndefinedBehavior();
770template <PrimType Name, class T = typename PrimConv<Name>::T>
776 return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr);
782template <PrimType Name, class T = typename PrimConv<Name>::T>
788 return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr);
795template <PrimType Name, class T = typename PrimConv<Name>::T>
801 return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr);
807template <PrimType Name, class T = typename PrimConv<Name>::T>
813 return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr);
816template <IncDecOp Op, PushVal DoPush>
818 llvm::RoundingMode RM) {
825 llvm::APFloat::opStatus Status;
841 return IncDecFloatHelper<IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, RM);
849 return IncDecFloatHelper<IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, RM);
857 return IncDecFloatHelper<IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, RM);
865 return IncDecFloatHelper<IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, RM);
870template <PrimType Name, class T = typename PrimConv<Name>::T>
872 const T &Val = S.Stk.pop<
T>();
874 if (!T::comp(Val, &
Result)) {
890 assert((!std::is_same_v<T, MemberPointer>) &&
891 "Non-equality comparisons on member pointer types should already be "
892 "rejected in Sema.");
894 const T &RHS = S.Stk.pop<
T>();
895 const T &LHS = S.Stk.pop<
T>();
896 S.Stk.push<BoolT>(BoolT::from(
Fn(LHS.compare(RHS))));
902 return CmpHelper<T>(S, OpPC,
Fn);
913 S.FFDiag(
Loc, diag::note_constexpr_pointer_comparison_unspecified)
915 << RHS.toDiagnosticString(S.getCtx());
926 for (
const auto &FP : {LHS, RHS}) {
929 S.FFDiag(
Loc, diag::note_constexpr_pointer_weak_comparison)
930 << FP.toDiagnosticString(S.getCtx());
947 S.FFDiag(
Loc, diag::note_constexpr_pointer_comparison_unspecified)
948 << LHS.toDiagnosticString(S.getCtx())
952 unsigned VL = LHS.getByteOffset();
954 S.Stk.push<BoolT>(BoolT::from(
Fn(
Compare(VL, VR))));
965 if (LHS.isZero() && RHS.
isZero()) {
971 for (
const auto &
P : {LHS, RHS}) {
976 S.FFDiag(
Loc, diag::note_constexpr_pointer_weak_comparison)
977 <<
P.toDiagnosticString(S.getCtx());
986 S.FFDiag(
Loc, diag::note_constexpr_pointer_comparison_past_end)
987 << LHS.toDiagnosticString(S.getCtx());
989 }
else if (RHS.
isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() &&
990 LHS.getOffset() == 0) {
992 S.FFDiag(
Loc, diag::note_constexpr_pointer_comparison_past_end)
1000 unsigned VL = LHS.getByteOffset();
1007 if (!LHS.isZero() && LHS.isArrayRoot())
1008 VL = LHS.atIndex(0).getByteOffset();
1012 S.Stk.push<BoolT>(BoolT::from(
Fn(
Compare(VL, VR))));
1025 for (
const auto &MP : {LHS, RHS}) {
1028 S.FFDiag(
Loc, diag::note_constexpr_mem_pointer_weak_comparison) << MD;
1036 if (LHS.
isZero() && RHS.isZero()) {
1040 if (LHS.
isZero() || RHS.isZero()) {
1046 for (
const auto &MP : {LHS, RHS}) {
1050 S.CCEDiag(
Loc, diag::note_constexpr_compare_virtual_mem_ptr) << MD;
1058template <PrimType Name, class T = typename PrimConv<Name>::T>
1065template <PrimType Name, class T = typename PrimConv<Name>::T>
1067 const T &RHS = S.Stk.pop<
T>();
1068 const T &LHS = S.Stk.pop<
T>();
1075 S.FFDiag(
Loc, diag::note_constexpr_pointer_comparison_unspecified)
1076 << LHS.toDiagnosticString(S.getCtx())
1077 << RHS.toDiagnosticString(S.getCtx());
1082 const auto *CmpValueInfo =
1084 assert(CmpValueInfo);
1085 assert(CmpValueInfo->hasValidIntValue());
1089template <PrimType Name, class T = typename PrimConv<Name>::T>
1096template <PrimType Name, class T = typename PrimConv<Name>::T>
1103template <PrimType Name, class T = typename PrimConv<Name>::T>
1111template <PrimType Name, class T = typename PrimConv<Name>::T>
1118template <PrimType Name, class T = typename PrimConv<Name>::T>
1130template <PrimType Name, class T = typename PrimConv<Name>::T>
1132 const T RHS = S.Stk.pop<
T>();
1133 const T LHS = S.Stk.pop<
T>();
1134 const T Value = S.Stk.pop<
T>();
1136 S.Stk.push<
bool>(LHS <=
Value &&
Value <= RHS);
1144template <PrimType Name, class T = typename PrimConv<Name>::T>
1146 S.Stk.push<
T>(S.Stk.peek<
T>());
1150template <PrimType Name, class T = typename PrimConv<Name>::T>
1157template <PrimType TopName, PrimType BottomName>
1162 const auto &Top = S.Stk.pop<TopT>();
1163 const auto &Bottom = S.Stk.pop<BottomT>();
1165 S.Stk.push<TopT>(Top);
1166 S.Stk.push<BottomT>(Bottom);
1175template <PrimType Name, class T = typename PrimConv<Name>::T>
1185template <PrimType Name, class T = typename PrimConv<Name>::T>
1187 const Pointer &Ptr = S.Current->getLocalPointer(I);
1190 S.Stk.push<
T>(Ptr.
deref<
T>());
1197template <PrimType Name, class T = typename PrimConv<Name>::T>
1199 S.Current->setLocal<
T>(I, S.Stk.pop<
T>());
1203template <PrimType Name, class T = typename PrimConv<Name>::T>
1205 if (S.checkingPotentialConstantExpression()) {
1208 S.Stk.push<
T>(S.Current->getParam<
T>(I));
1212template <PrimType Name, class T = typename PrimConv<Name>::T>
1214 S.Current->setParam<
T>(I, S.Stk.pop<
T>());
1220template <PrimType Name, class T = typename PrimConv<Name>::T>
1230 S.Stk.push<
T>(Field.deref<
T>());
1234template <PrimType Name, class T = typename PrimConv<Name>::T>
1236 const T &
Value = S.Stk.pop<
T>();
1242 const Pointer &Field = Obj.atField(I);
1246 Field.deref<
T>() =
Value;
1252template <PrimType Name, class T = typename PrimConv<Name>::T>
1262 S.Stk.push<
T>(Field.deref<
T>());
1266template <PrimType Name, class T = typename PrimConv<Name>::T>
1268 if (S.checkingPotentialConstantExpression())
1276 S.Stk.push<
T>(Field.deref<
T>());
1280template <PrimType Name, class T = typename PrimConv<Name>::T>
1282 if (S.checkingPotentialConstantExpression())
1284 const T &
Value = S.Stk.pop<
T>();
1291 Field.deref<
T>() =
Value;
1295template <PrimType Name, class T = typename PrimConv<Name>::T>
1297 const Pointer &Ptr = S.P.getPtrGlobal(I);
1308 S.Stk.push<
T>(Ptr.
deref<
T>());
1313template <PrimType Name, class T = typename PrimConv<Name>::T>
1315 const Pointer &Ptr = S.P.getPtrGlobal(I);
1318 S.Stk.push<
T>(Ptr.
deref<
T>());
1322template <PrimType Name, class T = typename PrimConv<Name>::T>
1328template <PrimType Name, class T = typename PrimConv<Name>::T>
1330 const Pointer &
P = S.P.getGlobal(I);
1331 P.deref<
T>() = S.Stk.pop<
T>();
1339template <PrimType Name, class T = typename PrimConv<Name>::T>
1342 const Pointer &Ptr = S.P.getGlobal(I);
1344 const T Value = S.Stk.peek<
T>();
1351 S.SeenGlobalTemporaries.push_back(
1354 Ptr.
deref<
T>() = S.Stk.pop<
T>();
1368 S.SeenGlobalTemporaries.push_back(
1369 std::make_pair(
P.getDeclDesc()->asExpr(), Temp));
1371 if (std::optional<APValue> APV =
1380template <PrimType Name, class T = typename PrimConv<Name>::T>
1382 if (S.checkingPotentialConstantExpression())
1388 Field.deref<
T>() = S.Stk.pop<
T>();
1396template <PrimType Name, class T = typename PrimConv<Name>::T>
1398 uint32_t FieldOffset) {
1399 assert(F->isBitField());
1400 if (S.checkingPotentialConstantExpression())
1406 const auto &
Value = S.Stk.pop<
T>();
1407 Field.deref<
T>() =
Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
1415template <PrimType Name, class T = typename PrimConv<Name>::T>
1417 const T &
Value = S.Stk.pop<
T>();
1419 Field.deref<
T>() =
Value;
1425template <PrimType Name, class T = typename PrimConv<Name>::T>
1427 assert(F->isBitField());
1428 const T &
Value = S.Stk.pop<
T>();
1430 Field.deref<
T>() =
Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
1441 S.Stk.push<
Pointer>(S.Current->getLocalPointer(I));
1446 if (S.checkingPotentialConstantExpression()) {
1449 S.Stk.push<
Pointer>(S.Current->getParamPointer(I));
1454 S.Stk.push<
Pointer>(S.P.getPtrGlobal(I));
1463 if (S.
getLangOpts().CPlusPlus && S.inConstantContext() &&
1491 if (S.
getLangOpts().CPlusPlus && S.inConstantContext() &&
1517 if (S.checkingPotentialConstantExpression())
1535 S.Stk.push<
Pointer>(std::move(Field));
1540 if (S.checkingPotentialConstantExpression())
1548 S.Stk.push<
Pointer>(std::move(Field));
1598 if (S.checkingPotentialConstantExpression())
1633 while (
Base.isBaseClass())
1636 const Record::Base *VirtBase =
Base.getRecord()->getVirtualBase(
Decl);
1637 S.Stk.push<
Pointer>(
Base.atField(VirtBase->Offset));
1653 if (S.checkingPotentialConstantExpression())
1665template <PrimType Name, class T = typename PrimConv<Name>::T>
1672 S.Stk.push<
T>(Ptr.
deref<
T>());
1676template <PrimType Name, class T = typename PrimConv<Name>::T>
1683 S.Stk.push<
T>(Ptr.
deref<
T>());
1687template <PrimType Name, class T = typename PrimConv<Name>::T>
1689 const T &
Value = S.Stk.pop<
T>();
1693 if (Ptr.canBeInitialized()) {
1701template <PrimType Name, class T = typename PrimConv<Name>::T>
1703 const T &
Value = S.Stk.pop<
T>();
1707 if (Ptr.canBeInitialized()) {
1715template <PrimType Name, class T = typename PrimConv<Name>::T>
1717 const T &
Value = S.Stk.pop<
T>();
1721 if (Ptr.canBeInitialized())
1723 if (
const auto *FD = Ptr.getField())
1724 Ptr.deref<
T>() =
Value.truncate(FD->getBitWidthValue(S.getCtx()));
1730template <PrimType Name, class T = typename PrimConv<Name>::T>
1732 const T &
Value = S.Stk.pop<
T>();
1736 if (Ptr.canBeInitialized())
1738 if (
const auto *FD = Ptr.getField())
1739 Ptr.deref<
T>() =
Value.truncate(FD->getBitWidthValue(S.getCtx()));
1745template <PrimType Name, class T = typename PrimConv<Name>::T>
1747 const T &
Value = S.Stk.pop<
T>();
1754 new (&Ptr.deref<
T>())
T(
Value);
1758template <PrimType Name, class T = typename PrimConv<Name>::T>
1760 const T &
Value = S.Stk.pop<
T>();
1765 new (&Ptr.deref<
T>())
T(
Value);
1772template <PrimType Name, class T = typename PrimConv<Name>::T>
1774 const T &
Value = S.Stk.pop<
T>();
1776 if (Ptr.isUnknownSizeArray())
1781 new (&Ptr.deref<
T>())
T(
Value);
1786template <PrimType Name, class T = typename PrimConv<Name>::T>
1788 const T &
Value = S.Stk.pop<
T>();
1790 if (Ptr.isUnknownSizeArray())
1795 new (&Ptr.deref<
T>())
T(
Value);
1806 return DoMemcpy(S, OpPC, Src, Dest);
1820 if (std::optional<Pointer> Ptr = MP.toPointer(S.Ctx)) {
1831template <
class T, ArithOp Op>
1835 if (Offset.isZero()) {
1854 uint64_t O =
static_cast<uint64_t
>(Offset) * Ptr.
elemSize();
1861 uint64_t O =
static_cast<uint64_t
>(Offset);
1869 S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
1877 uint64_t MaxIndex =
static_cast<uint64_t
>(Ptr.
getNumElems());
1886 auto DiagInvalidOffset = [&]() ->
void {
1887 const unsigned Bits = Offset.bitWidth();
1888 APSInt APOffset(Offset.toAPSInt().extend(Bits + 2),
false);
1892 (Op ==
ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
1893 S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
1894 << NewIndex <<
static_cast<int>(!Ptr.
inArray()) << MaxIndex;
1899 uint64_t IOffset =
static_cast<uint64_t
>(Offset);
1900 uint64_t MaxOffset = MaxIndex - Index;
1904 if (Offset.isNegative() && (Offset.isMin() || -IOffset > Index))
1905 DiagInvalidOffset();
1908 if (Offset.isPositive() && IOffset > MaxOffset)
1909 DiagInvalidOffset();
1912 if (Offset.isPositive() && Index < IOffset)
1913 DiagInvalidOffset();
1916 if (Offset.isNegative() && (Offset.isMin() || -IOffset > MaxOffset))
1917 DiagInvalidOffset();
1925 int64_t WideIndex =
static_cast<int64_t
>(Index);
1926 int64_t WideOffset =
static_cast<int64_t
>(Offset);
1929 Result = WideIndex + WideOffset;
1931 Result = WideIndex - WideOffset;
1946template <PrimType Name, class T = typename PrimConv<Name>::T>
1948 const T &Offset = S.Stk.pop<
T>();
1950 return OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr);
1953template <PrimType Name, class T = typename PrimConv<Name>::T>
1955 const T &Offset = S.Stk.pop<
T>();
1957 return OffsetHelper<T, ArithOp::Sub>(S, OpPC, Offset, Ptr);
1960template <ArithOp Op>
1976 OneT One = OneT::from(1);
1977 if (!OffsetHelper<OneT, Op>(S, OpPC, One,
P))
1991 return IncDecPtrHelper<ArithOp::Add>(S, OpPC, Ptr);
2000 return IncDecPtrHelper<ArithOp::Sub>(S, OpPC, Ptr);
2006template <PrimType Name, class T = typename PrimConv<Name>::T>
2011 for (
const Pointer &
P : {LHS, RHS}) {
2012 if (
P.isZeroSizeArray()) {
2014 while (
auto *AT = dyn_cast<ArrayType>(PtrT))
2015 PtrT = AT->getElementType();
2017 QualType ArrayTy = S.getCtx().getConstantArrayType(
2019 S.FFDiag(S.Current->getSource(OpPC),
2020 diag::note_constexpr_pointer_subtraction_zero_size)
2037 if (LHS.
isZero() && RHS.isZero()) {
2046 T B = RHS.isBlockPointer()
2047 ? (RHS.isElementPastEnd() ? T::from(RHS.getNumElems())
2048 : T::from(RHS.getIndex()))
2049 : T::from(RHS.getIntegerRepresentation());
2051 return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, A.bitWidth(), A, B);
2059 S.Current->destroy(I);
2064 S.Current->initScope(I);
2075 S.Stk.push<
U>(U::from(S.Stk.pop<
T>()));
2082 llvm::RoundingMode RM) {
2091template <PrimType Name, class T = typename PrimConv<Name>::T>
2098template <PrimType Name, class T = typename PrimConv<Name>::T>
2105template <PrimType Name, class T = typename PrimConv<Name>::T>
2107 const llvm::fltSemantics *Sem,
2108 llvm::RoundingMode RM) {
2109 const T &From = S.Stk.pop<
T>();
2110 APSInt FromAP = From.toAPSInt();
2119template <PrimType Name, class T = typename PrimConv<Name>::T>
2123 if constexpr (std::is_same_v<T, Boolean>) {
2132 if ((Status & APFloat::opStatus::opInvalidOp)) {
2133 const Expr *
E = S.Current->getExpr(OpPC);
2136 S.CCEDiag(
E, diag::note_constexpr_overflow) << F.
getAPFloat() <<
Type;
2137 if (S.noteUndefinedBehavior()) {
2150 uint32_t BitWidth) {
2157 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite()) {
2158 const Expr *
E = S.Current->getExpr(OpPC);
2161 S.CCEDiag(
E, diag::note_constexpr_overflow) << F.
getAPFloat() <<
Type;
2162 return S.noteUndefinedBehavior();
2170 uint32_t BitWidth) {
2177 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite()) {
2178 const Expr *
E = S.Current->getExpr(OpPC);
2181 S.CCEDiag(
E, diag::note_constexpr_overflow) << F.
getAPFloat() <<
Type;
2182 return S.noteUndefinedBehavior();
2189template <PrimType Name, class T = typename PrimConv<Name>::T>
2197 S.CCEDiag(
E, diag::note_constexpr_invalid_cast)
2198 << 2 << S.
getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
2205 uint32_t BitWidth) {
2212 S.CCEDiag(
E, diag::note_constexpr_invalid_cast)
2213 << 2 << S.
getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
2221 uint32_t BitWidth) {
2228 S.CCEDiag(
E, diag::note_constexpr_invalid_cast)
2229 << 2 << S.
getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
2237 const auto &Ptr = S.Stk.peek<
Pointer>();
2240 bool HasValidResult = !Ptr.
isZero();
2242 if (HasValidResult) {
2246 S.CCEDiag(
E, diag::note_constexpr_invalid_cast)
2247 << 3 <<
"'void *'" << S.Current->getRange(OpPC);
2251 S.CCEDiag(
E, diag::note_constexpr_invalid_cast)
2252 << 2 << S.
getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
2262template <PrimType Name, class T = typename PrimConv<Name>::T>
2264 S.Stk.push<
T>(T::zero());
2278template <PrimType Name, class T = typename PrimConv<Name>::T>
2281 S.Stk.push<
T>(0, Desc);
2291 if (S.checkingPotentialConstantExpression()) {
2300 if (!
This.isDummy()) {
2301 assert(isa<CXXMethodDecl>(S.Current->getFunction()->getDecl()));
2302 assert(
This.getRecord());
2304 This.getRecord()->getDecl() ==
2305 cast<CXXMethodDecl>(S.Current->getFunction()->getDecl())->getParent());
2313 assert(S.Current->getFunction()->hasRVO());
2314 if (S.checkingPotentialConstantExpression())
2316 S.Stk.push<
Pointer>(S.Current->getRVOPtr());
2325template <
class LT,
class RT, ShiftDir Dir>
2327 const unsigned Bits = LHS.bitWidth();
2331 RT::bitAnd(RHS, RT::from(LHS.bitWidth() - 1, RHS.bitWidth()),
2332 RHS.bitWidth(), &RHS);
2334 if (RHS.isNegative()) {
2338 S.CCEDiag(
Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
2339 if (!S.noteUndefinedBehavior())
2348 if (LHS.isNegative() && !S.
getLangOpts().CPlusPlus20) {
2354 S.CCEDiag(
Loc, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
2355 if (!S.noteUndefinedBehavior())
2366 typename LT::AsUnsigned R;
2368 if (RHS > RT::from(Bits - 1, RHS.bitWidth()))
2369 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
2370 LT::AsUnsigned::from(Bits - 1), Bits, &R);
2372 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
2373 LT::AsUnsigned::from(RHS, Bits), Bits, &R);
2375 if (RHS > RT::from(Bits - 1, RHS.bitWidth()))
2376 LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),
2377 LT::AsUnsigned::from(Bits - 1), Bits, &R);
2379 LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),
2380 LT::AsUnsigned::from(RHS, Bits), Bits, &R);
2385 if (LHS.isSigned() && LHS.isNegative()) {
2386 typename LT::AsUnsigned SignBit;
2387 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(1, Bits),
2388 LT::AsUnsigned::from(Bits - 1, Bits), Bits,
2390 LT::AsUnsigned::bitOr(R, SignBit, Bits, &R);
2394 S.Stk.push<
LT>(LT::from(R));
2398template <PrimType NameL, PrimType NameR>
2402 auto RHS = S.Stk.pop<RT>();
2403 auto LHS = S.Stk.pop<
LT>();
2405 return DoShift<LT, RT, ShiftDir::Right>(S, OpPC, LHS, RHS);
2408template <PrimType NameL, PrimType NameR>
2412 auto RHS = S.Stk.pop<RT>();
2413 auto LHS = S.Stk.pop<
LT>();
2415 return DoShift<LT, RT, ShiftDir::Left>(S, OpPC, LHS, RHS);
2424 S.FFDiag(EndLoc, diag::note_constexpr_no_return);
2452template <PrimType Name, class T = typename PrimConv<Name>::T>
2454 const T &Offset = S.Stk.pop<
T>();
2457 if (!Ptr.isZero() && !Offset.isZero()) {
2462 if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
2468template <PrimType Name, class T = typename PrimConv<Name>::T>
2470 const T &Offset = S.Stk.pop<
T>();
2473 if (!Ptr.isZero() && !Offset.isZero()) {
2478 if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
2484template <PrimType Name, class T = typename PrimConv<Name>::T>
2495template <PrimType Name, class T = typename PrimConv<Name>::T>
2506template <PrimType Name, class T = typename PrimConv<Name>::T>
2508 uint32_t DestIndex, uint32_t Size) {
2509 const auto &SrcPtr = S.Stk.pop<
Pointer>();
2510 const auto &DestPtr = S.Stk.peek<
Pointer>();
2512 for (uint32_t I = 0; I != Size; ++I) {
2544 S.FFDiag(
E, diag::note_constexpr_unsupported_unsized_array);
2550 uint32_t VarArgSize) {
2551 if (
Func->hasThisPointer()) {
2552 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2560 if (!(S.Current->getFunction() &&
2561 S.Current->getFunction()->isLambdaStaticInvoker() &&
2562 Func->isLambdaCallOperator())) {
2567 if (S.checkingPotentialConstantExpression())
2577 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC, VarArgSize);
2579 S.Current = NewFrame.get();
2587 assert(S.Current == FrameBefore);
2593 S.Current = FrameBefore;
2600 uint32_t VarArgSize) {
2601 if (
Func->hasThisPointer()) {
2602 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2611 if (!(S.Current->getFunction() &&
2612 S.Current->getFunction()->isLambdaStaticInvoker() &&
2613 Func->isLambdaCallOperator())) {
2622 if (
Func->hasThisPointer() && S.checkingPotentialConstantExpression())
2628 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, OpPC, VarArgSize);
2630 S.Current = NewFrame.get();
2638 assert(S.Current == FrameBefore);
2644 S.Current = FrameBefore;
2649 uint32_t VarArgSize) {
2650 assert(
Func->hasThisPointer());
2651 assert(
Func->isVirtual());
2652 size_t ArgSize =
Func->getArgSize() + VarArgSize;
2664 DynamicDecl =
DynamicType->getPointeeCXXRecordDecl();
2668 assert(DynamicDecl);
2670 const auto *StaticDecl = cast<CXXRecordDecl>(
Func->getParentDecl());
2671 const auto *InitialFunction = cast<CXXMethodDecl>(
Func->getDecl());
2672 const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
2673 DynamicDecl, StaticDecl, InitialFunction);
2675 if (Overrider != InitialFunction) {
2680 const Expr *
E = S.Current->getExpr(OpPC);
2684 Func = S.getContext().getOrCreateFunction(Overrider);
2687 ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
2688 if (
Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
2692 while (ThisPtr.isBaseClass())
2693 ThisPtr = ThisPtr.getBase();
2697 if (!
Call(S, OpPC,
Func, VarArgSize))
2702 if (Overrider != InitialFunction &&
2704 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
2713 unsigned Offset = S.getContext().collectBaseOffset(
2724 auto NewFrame = std::make_unique<InterpFrame>(S,
Func, PC);
2727 S.Current = NewFrame.get();
2733 S.Current = FrameBefore;
2743 const auto *
E = cast<CallExpr>(S.Current->getExpr(OpPC));
2744 S.FFDiag(
E, diag::note_constexpr_null_callee)
2749 if (!FuncPtr.
isValid() || !F->getDecl())
2756 if (S.Ctx.classify(F->getDecl()->getReturnType()) !=
2757 S.Ctx.classify(CE->
getType()))
2761 if (F->hasNonNullAttr()) {
2766 assert(ArgSize >= F->getWrittenArgSize());
2767 uint32_t VarArgSize = ArgSize - F->getWrittenArgSize();
2771 if (F->isThisPointerExplicit())
2775 return CallVirt(S, OpPC, F, VarArgSize);
2777 return Call(S, OpPC, F, VarArgSize);
2786template <PrimType Name, class T = typename PrimConv<Name>::T>
2788 const T &IntVal = S.Stk.pop<
T>();
2790 S.Stk.push<
Pointer>(
static_cast<uint64_t
>(IntVal), Desc);
2802 S.Stk.push<
Pointer>(MP.getBase());
2809 const auto *FD = cast<FunctionDecl>(MP.getDecl());
2810 const auto *
Func = S.getContext().getOrCreateFunction(FD);
2820 S.FFDiag(
Loc, diag::note_invalid_subexpr_in_const_expr)
2821 << S.Current->getRange(OpPC);
2827 S.FFDiag(
Loc, diag::note_constexpr_stmt_expr_unsupported)
2828 << S.Current->getRange(OpPC);
2842 S.CCEDiag(
Loc, diag::note_constexpr_invalid_cast)
2843 <<
static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
2856 if (S.inConstantContext()) {
2857 const SourceRange &ArgRange = S.Current->getRange(OpPC);
2858 const Expr *
E = S.Current->getExpr(OpPC);
2859 S.CCEDiag(
E, diag::note_constexpr_non_const_vectorelements) << ArgRange;
2865 const auto Val = S.Stk.pop<
Boolean>();
2872 S.CCEDiag(
Loc, diag::note_constexpr_assumption_failed);
2876template <PrimType Name, class T = typename PrimConv<Name>::T>
2879 for (
size_t I = 0; I !=
E->getNumExpressions(); ++I)
2880 ArrayIndices.emplace_back(S.Stk.pop<int64_t>());
2886 S.Stk.push<
T>(T::from(
Result));
2891template <PrimType Name, class T = typename PrimConv<Name>::T>
2893 const T &Arg = S.Stk.peek<
T>();
2898 S.CCEDiag(
Loc, diag::note_non_null_attribute_failed);
2906template <PrimType Name, class T = typename PrimConv<Name>::T>
2910 const APSInt Val = S.Stk.peek<
T>().toAPSInt();
2912 if (S.inConstantContext())
2918template <PrimType TIn, PrimType TOut>
2924 const FromT &OldPtr = S.Stk.pop<FromT>();
2926 if constexpr (std::is_same_v<FromT, FunctionPointer> &&
2927 std::is_same_v<ToT, Pointer>) {
2928 S.Stk.push<
Pointer>(OldPtr.getFunction(), OldPtr.getOffset());
2930 }
else if constexpr (std::is_same_v<FromT, Pointer> &&
2931 std::is_same_v<ToT, FunctionPointer>) {
2932 if (OldPtr.isFunctionPointer()) {
2934 OldPtr.getByteOffset());
2939 S.Stk.push<ToT>(ToT(OldPtr.getIntegerRepresentation(),
nullptr));
2951 if (VD == S.EvaluatingDecl)
2955 S.CCEDiag(VD->
getLocation(), diag::note_constexpr_static_local)
2969 Block *B = Allocator.allocate(Desc, S.Ctx.getEvalID());
2977template <PrimType Name, class SizeT = typename PrimConv<Name>::T>
2983 SizeT NumElements = S.Stk.pop<SizeT>();
2989 S.Stk.push<
Pointer>(0,
nullptr);
2994 Block *B = Allocator.allocate(Source,
T,
static_cast<size_t>(NumElements),
3002template <PrimType Name, class SizeT = typename PrimConv<Name>::T>
3008 SizeT NumElements = S.Stk.pop<SizeT>();
3015 S.Stk.push<
Pointer>(0, ElementDesc);
3020 Block *B = Allocator.allocate(ElementDesc,
static_cast<size_t>(NumElements),
3029bool RunDestructors(InterpState &S, CodePtr OpPC,
const Block *B);
3034 const Expr *Source =
nullptr;
3035 const Block *BlockToDelete =
nullptr;
3047 S.FFDiag(
Loc, diag::note_constexpr_delete_subobject)
3053 BlockToDelete = Ptr.
block();
3059 assert(BlockToDelete);
3066 bool WasArrayAlloc = Allocator.isArrayAllocation(Source);
3069 if (!Allocator.deallocate(Source, BlockToDelete, S)) {
3072 S.FFDiag(
Loc, diag::note_constexpr_double_delete);
3102 if (S.EvaluatingDecl)
3105 if (S.Current->getFunction() && S.Current->getFunction()->isConstructor() &&
3106 S.Current->getThis().getDeclDesc()->asDecl() == S.EvaluatingDecl)
3109 const Expr *
E = S.Current->getExpr(OpPC);
3111 S.FFDiag(
E, diag::note_constexpr_nonliteral) <<
E->
getType();
3113 S.FFDiag(
E, diag::note_invalid_subexpr_in_const_expr);
3122 if constexpr (std::is_pointer<T>::value) {
3123 uint32_t ID = OpPC.
read<uint32_t>();
3124 return reinterpret_cast<T>(S.P.getNativePointer(ID));
3126 return OpPC.
read<
T>();
3137inline IntegralAP<false> ReadArg<IntegralAP<false>>(InterpState &S,
3140 OpPC +=
align(I.bytesToSerialize());
3145inline IntegralAP<true> ReadArg<IntegralAP<true>>(InterpState &S,
3148 OpPC +=
align(I.bytesToSerialize());
Defines the clang::ASTContext interface.
ASTImporterLookupTable & LT
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)
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.
static unsigned getMaxSizeBits(const ASTContext &Context)
Determine the maximum number of active bits that an array's size can require, which limits the maximu...
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getLocation() 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...
QualType getReturnType() const
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.
Expr * getTemporaryExpr()
Retrieve the expression to which the temporary materialization conversion was applied.
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
A (possibly-)qualified type.
Represents a struct/union/class.
const LangOptions & getLangOpts() const
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.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isPointerOrReferenceType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isWeak() const
Determine whether this symbol is weakly-imported, or declared with the weak or weak-ref attr.
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.
unsigned getSize() const
Returns the size of the block.
const Descriptor * getDescriptor() const
Returns the block's descriptor.
Wrapper around boolean types.
static Boolean from(T Value)
Pointer into the code segment.
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
Manages dynamic memory allocations done during bytecode interpretation.
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.
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.
void deactivate() const
Deactivates an entire strurcutre.
bool isInitialized() const
Checks if an object was initialized.
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.
void activate() const
Activats a field.
bool isIntegralPointer() const
QualType getType() const
Returns the type of the innermost field.
bool isArrayElement() const
Checks if the pointer points to an array.
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.
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
uint64_t getByteOffset() const
Returns the byte offset from the start.
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.
const IntPointer & asIntPointer() const
bool isRoot() const
Pointer points directly to a block.
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
unsigned getOffset() const
Returns the offset into an array.
bool isOnePastEnd() const
Checks if the index is one past end.
uint64_t getIntegerRepresentation() const
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
bool isBlockPointer() const
const FunctionPointer & asFunctionPointer() const
const Block * block() const
bool isFunctionPointer() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
bool isBaseClass() const
Checks if a structure is a base class.
size_t elemSize() const
Returns the element size of the innermost field.
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
const BlockPointer & asBlockPointer() const
void initialize() const
Initializes a field.
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 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 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 GetMemberPtrBase(InterpState &S, CodePtr OpPC)
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 RunDestructors(InterpState &S, CodePtr OpPC, const Block *B)
bool GetMemberPtrBasePop(InterpState &S, CodePtr OpPC, int32_t Off)
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 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 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 CheckDecl(InterpState &S, CodePtr OpPC, const VarDecl *VD)
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 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 GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool Mulc(InterpState &S, CodePtr OpPC)
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)
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a value can be loaded from a block.
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 CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
bool Store(InterpState &S, CodePtr OpPC)
bool Divc(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 InitScope(InterpState &S, CodePtr OpPC, uint32_t I)
bool Mulf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
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 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 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 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.
void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED, const APSInt &Value)
bool CastIntegralFloating(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, llvm::RoundingMode RM)
bool LE(InterpState &S, CodePtr OpPC)
PrimType
Enumeration of the primitive types of the VM.
bool Zero(InterpState &S, CodePtr OpPC)
bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F, uint32_t FieldOffset)
bool Unsupported(InterpState &S, CodePtr OpPC)
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 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 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 Alloc(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
bool ToMemberPtr(InterpState &S, CodePtr OpPC)
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 IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
bool Dump(InterpState &S, CodePtr OpPC)
bool SizelessVectorElementSize(InterpState &S, CodePtr OpPC)
bool Null(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
static bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
static bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr)
bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T)
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 CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is a dummy pointer.
bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC)
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 DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS)
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)
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 GetMemberPtr(InterpState &S, CodePtr OpPC, const Decl *D)
bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR)
bool FinishInitPop(InterpState &S, CodePtr OpPC)
bool ReturnValue(const InterpState &S, const T &V, APValue &R)
Convert a value to an APValue.
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 Inv(InterpState &S, CodePtr OpPC)
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 CheckNewDeleteForms(InterpState &S, CodePtr OpPC, bool NewWasArray, bool DeleteIsArray, const Descriptor *D, const Expr *NewExpr)
Diagnose mismatched new[]/delete or new/delete[] pairs.
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 CmpHelperEQ< MemberPointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
Checks if a method can be called.
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 CheckArraySize(InterpState &S, CodePtr OpPC, SizeT *NumElements, unsigned ElemSize, bool IsNoThrow)
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 AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc, bool IsNoThrow)
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 InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, bool Fatal)
Same here, but only for casts.
bool CastMemberPtrPtr(InterpState &S, CodePtr OpPC)
bool RetVoid(InterpState &S, CodePtr &PC, APValue &Result)
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 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)
static bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm)
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)
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.
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
unsigned Base
Start of the current subfield.
Block * Pointee
The block the pointer is pointing to.
Describes a memory block created by an allocation site.
unsigned getSize() const
Returns the size of the object without metadata.
static constexpr unsigned MaxArrayElemBytes
Maximum number of bytes to be used for array elements.
const Expr * asExpr() const
Inline descriptor embedded in structures and arrays.
IntPointer atOffset(const ASTContext &ASTCtx, unsigned Offset) const
Mapping from primitive types to their representation.