xref: /llvm-project/clang/lib/AST/ByteCode/Interp.h (revision e8674af6f41b2e78ceebabb23e40588c41da5a23)
1 //===--- Interp.h - Interpreter for the constexpr VM ------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Definition of the interpreter state and entry point.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_AST_INTERP_INTERP_H
14 #define LLVM_CLANG_AST_INTERP_INTERP_H
15 
16 #include "../ExprConstShared.h"
17 #include "BitcastBuffer.h"
18 #include "Boolean.h"
19 #include "DynamicAllocator.h"
20 #include "FixedPoint.h"
21 #include "Floating.h"
22 #include "Function.h"
23 #include "FunctionPointer.h"
24 #include "InterpBuiltinBitCast.h"
25 #include "InterpFrame.h"
26 #include "InterpStack.h"
27 #include "InterpState.h"
28 #include "MemberPointer.h"
29 #include "Opcode.h"
30 #include "PrimType.h"
31 #include "Program.h"
32 #include "State.h"
33 #include "clang/AST/ASTContext.h"
34 #include "clang/AST/Expr.h"
35 #include "llvm/ADT/APFloat.h"
36 #include "llvm/ADT/APSInt.h"
37 #include <type_traits>
38 
39 namespace clang {
40 namespace interp {
41 
42 using APSInt = llvm::APSInt;
43 using FixedPointSemantics = llvm::FixedPointSemantics;
44 
45 /// Checks if the variable has externally defined storage.
46 bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
47 
48 /// Checks if the array is offsetable.
49 bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
50 
51 /// Checks if a pointer is live and accessible.
52 bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
53                AccessKinds AK);
54 
55 /// Checks if a pointer is a dummy pointer.
56 bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
57                 AccessKinds AK);
58 
59 /// Checks if a pointer is null.
60 bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
61                CheckSubobjectKind CSK);
62 
63 /// Checks if a pointer is in range.
64 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
65                 AccessKinds AK);
66 
67 /// Checks if a field from which a pointer is going to be derived is valid.
68 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
69                 CheckSubobjectKind CSK);
70 
71 /// Checks if Ptr is a one-past-the-end pointer.
72 bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
73                     CheckSubobjectKind CSK);
74 
75 /// Checks if the dowcast using the given offset is possible with the given
76 /// pointer.
77 bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
78                    uint32_t Offset);
79 
80 /// Checks if a pointer points to const storage.
81 bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
82 
83 /// Checks if the Descriptor is of a constexpr or const global variable.
84 bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc);
85 
86 /// Checks if a pointer points to a mutable field.
87 bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
88 
89 /// Checks if a value can be loaded from a block.
90 bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
91                AccessKinds AK = AK_Read);
92 bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
93 
94 bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
95                       AccessKinds AK);
96 /// Check if a global variable is initialized.
97 bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
98 
99 /// Checks if a value can be stored in a block.
100 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
101 
102 /// Checks if a method can be invoked on an object.
103 bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
104 
105 /// Checks if a value can be initialized.
106 bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
107 
108 /// Checks if a method can be called.
109 bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F);
110 
111 /// Checks if calling the currently active function would exceed
112 /// the allowed call depth.
113 bool CheckCallDepth(InterpState &S, CodePtr OpPC);
114 
115 /// Checks the 'this' pointer.
116 bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This);
117 
118 /// Checks if a method is pure virtual.
119 bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD);
120 
121 /// Checks if all the arguments annotated as 'nonnull' are in fact not null.
122 bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F,
123                       const CallExpr *CE, unsigned ArgSize);
124 
125 /// Checks if dynamic memory allocation is available in the current
126 /// language mode.
127 bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC);
128 
129 /// Diagnose mismatched new[]/delete or new/delete[] pairs.
130 bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC,
131                          DynamicAllocator::Form AllocForm,
132                          DynamicAllocator::Form DeleteForm, const Descriptor *D,
133                          const Expr *NewExpr);
134 
135 /// Check the source of the pointer passed to delete/delete[] has actually
136 /// been heap allocated by us.
137 bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source,
138                        const Pointer &Ptr);
139 
140 /// Sets the given integral value to the pointer, which is of
141 /// a std::{weak,partial,strong}_ordering type.
142 bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,
143                                 const Pointer &Ptr, const APSInt &IntValue);
144 
145 /// Copy the contents of Src into Dest.
146 bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest);
147 
148 bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
149              uint32_t VarArgSize);
150 bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
151           uint32_t VarArgSize);
152 bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
153               uint32_t VarArgSize);
154 bool CallBI(InterpState &S, CodePtr OpPC, const Function *Func,
155             const CallExpr *CE, uint32_t BuiltinID);
156 bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
157              const CallExpr *CE);
158 bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T);
159 bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index);
160 bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits,
161                   bool TargetIsUCharOrByte);
162 
163 template <typename T>
164 static bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue) {
165   const Expr *E = S.Current->getExpr(OpPC);
166   S.CCEDiag(E, diag::note_constexpr_overflow) << SrcValue << E->getType();
167   return S.noteUndefinedBehavior();
168 }
169 bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC,
170                               const FixedPoint &FP);
171 
172 enum class ShiftDir { Left, Right };
173 
174 /// Checks if the shift operation is legal.
175 template <ShiftDir Dir, typename LT, typename RT>
176 bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS,
177                 unsigned Bits) {
178   if (RHS.isNegative()) {
179     const SourceInfo &Loc = S.Current->getSource(OpPC);
180     S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
181     if (!S.noteUndefinedBehavior())
182       return false;
183   }
184 
185   // C++11 [expr.shift]p1: Shift width must be less than the bit width of
186   // the shifted type.
187   if (Bits > 1 && RHS >= RT::from(Bits, RHS.bitWidth())) {
188     const Expr *E = S.Current->getExpr(OpPC);
189     const APSInt Val = RHS.toAPSInt();
190     QualType Ty = E->getType();
191     S.CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty << Bits;
192     if (!S.noteUndefinedBehavior())
193       return false;
194   }
195 
196   if constexpr (Dir == ShiftDir::Left) {
197     if (LHS.isSigned() && !S.getLangOpts().CPlusPlus20) {
198       const Expr *E = S.Current->getExpr(OpPC);
199       // C++11 [expr.shift]p2: A signed left shift must have a non-negative
200       // operand, and must not overflow the corresponding unsigned type.
201       if (LHS.isNegative()) {
202         S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
203         if (!S.noteUndefinedBehavior())
204           return false;
205       } else if (LHS.toUnsigned().countLeadingZeros() <
206                  static_cast<unsigned>(RHS)) {
207         S.CCEDiag(E, diag::note_constexpr_lshift_discards);
208         if (!S.noteUndefinedBehavior())
209           return false;
210       }
211     }
212   }
213 
214   // C++2a [expr.shift]p2: [P0907R4]:
215   //    E1 << E2 is the unique value congruent to
216   //    E1 x 2^E2 module 2^N.
217   return true;
218 }
219 
220 /// Checks if Div/Rem operation on LHS and RHS is valid.
221 template <typename T>
222 bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS) {
223   if (RHS.isZero()) {
224     const auto *Op = cast<BinaryOperator>(S.Current->getExpr(OpPC));
225     if constexpr (std::is_same_v<T, Floating>) {
226       S.CCEDiag(Op, diag::note_expr_divide_by_zero)
227           << Op->getRHS()->getSourceRange();
228       return true;
229     }
230 
231     S.FFDiag(Op, diag::note_expr_divide_by_zero)
232         << Op->getRHS()->getSourceRange();
233     return false;
234   }
235 
236   if constexpr (!std::is_same_v<T, FixedPoint>) {
237     if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) {
238       APSInt LHSInt = LHS.toAPSInt();
239       SmallString<32> Trunc;
240       (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10);
241       const SourceInfo &Loc = S.Current->getSource(OpPC);
242       const Expr *E = S.Current->getExpr(OpPC);
243       S.CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->getType();
244       return false;
245     }
246   }
247   return true;
248 }
249 
250 template <typename SizeT>
251 bool CheckArraySize(InterpState &S, CodePtr OpPC, SizeT *NumElements,
252                     unsigned ElemSize, bool IsNoThrow) {
253   // FIXME: Both the SizeT::from() as well as the
254   // NumElements.toAPSInt() in this function are rather expensive.
255 
256   // Can't be too many elements if the bitwidth of NumElements is lower than
257   // that of Descriptor::MaxArrayElemBytes.
258   if ((NumElements->bitWidth() - NumElements->isSigned()) <
259       (sizeof(Descriptor::MaxArrayElemBytes) * 8))
260     return true;
261 
262   // FIXME: GH63562
263   // APValue stores array extents as unsigned,
264   // so anything that is greater that unsigned would overflow when
265   // constructing the array, we catch this here.
266   SizeT MaxElements = SizeT::from(Descriptor::MaxArrayElemBytes / ElemSize);
267   assert(MaxElements.isPositive());
268   if (NumElements->toAPSInt().getActiveBits() >
269           ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||
270       *NumElements > MaxElements) {
271     if (!IsNoThrow) {
272       const SourceInfo &Loc = S.Current->getSource(OpPC);
273 
274       if (NumElements->isSigned() && NumElements->isNegative()) {
275         S.FFDiag(Loc, diag::note_constexpr_new_negative)
276             << NumElements->toDiagnosticString(S.getASTContext());
277       } else {
278         S.FFDiag(Loc, diag::note_constexpr_new_too_large)
279             << NumElements->toDiagnosticString(S.getASTContext());
280       }
281     }
282     return false;
283   }
284   return true;
285 }
286 
287 /// Checks if the result of a floating-point operation is valid
288 /// in the current context.
289 bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
290                       APFloat::opStatus Status, FPOptions FPO);
291 
292 /// Checks why the given DeclRefExpr is invalid.
293 bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR);
294 
295 /// Interpreter entry point.
296 bool Interpret(InterpState &S);
297 
298 /// Interpret a builtin function.
299 bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
300                       const CallExpr *Call, uint32_t BuiltinID);
301 
302 /// Interpret an offsetof operation.
303 bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
304                        llvm::ArrayRef<int64_t> ArrayIndices, int64_t &Result);
305 
306 inline bool Invalid(InterpState &S, CodePtr OpPC);
307 
308 enum class ArithOp { Add, Sub };
309 
310 //===----------------------------------------------------------------------===//
311 // Returning values
312 //===----------------------------------------------------------------------===//
313 
314 void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
315                               const Function *Func);
316 
317 template <PrimType Name, class T = typename PrimConv<Name>::T>
318 bool Ret(InterpState &S, CodePtr &PC) {
319   const T &Ret = S.Stk.pop<T>();
320 
321   assert(S.Current);
322   assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
323   if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
324     cleanupAfterFunctionCall(S, PC, S.Current->getFunction());
325 
326   if (InterpFrame *Caller = S.Current->Caller) {
327     PC = S.Current->getRetPC();
328     delete S.Current;
329     S.Current = Caller;
330     S.Stk.push<T>(Ret);
331   } else {
332     delete S.Current;
333     S.Current = nullptr;
334     // The topmost frame should come from an EvalEmitter,
335     // which has its own implementation of the Ret<> instruction.
336   }
337   return true;
338 }
339 
340 inline bool RetVoid(InterpState &S, CodePtr &PC) {
341   assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
342 
343   if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
344     cleanupAfterFunctionCall(S, PC, S.Current->getFunction());
345 
346   if (InterpFrame *Caller = S.Current->Caller) {
347     PC = S.Current->getRetPC();
348     delete S.Current;
349     S.Current = Caller;
350   } else {
351     delete S.Current;
352     S.Current = nullptr;
353   }
354   return true;
355 }
356 
357 //===----------------------------------------------------------------------===//
358 // Add, Sub, Mul
359 //===----------------------------------------------------------------------===//
360 
361 template <typename T, bool (*OpFW)(T, T, unsigned, T *),
362           template <typename U> class OpAP>
363 bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS,
364                      const T &RHS) {
365   // Fast path - add the numbers with fixed width.
366   T Result;
367   if (!OpFW(LHS, RHS, Bits, &Result)) {
368     S.Stk.push<T>(Result);
369     return true;
370   }
371   // If for some reason evaluation continues, use the truncated results.
372   S.Stk.push<T>(Result);
373 
374   // Short-circuit fixed-points here since the error handling is easier.
375   if constexpr (std::is_same_v<T, FixedPoint>)
376     return handleFixedPointOverflow(S, OpPC, Result);
377 
378   // Slow path - compute the result using another bit of precision.
379   APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits));
380 
381   // Report undefined behaviour, stopping if required.
382   const Expr *E = S.Current->getExpr(OpPC);
383   QualType Type = E->getType();
384   if (S.checkingForUndefinedBehavior()) {
385     SmallString<32> Trunc;
386     Value.trunc(Result.bitWidth())
387         .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
388                   /*UpperCase=*/true, /*InsertSeparators=*/true);
389     auto Loc = E->getExprLoc();
390     S.report(Loc, diag::warn_integer_constant_overflow)
391         << Trunc << Type << E->getSourceRange();
392   }
393 
394   if (!handleOverflow(S, OpPC, Value)) {
395     S.Stk.pop<T>();
396     return false;
397   }
398   return true;
399 }
400 
401 template <PrimType Name, class T = typename PrimConv<Name>::T>
402 bool Add(InterpState &S, CodePtr OpPC) {
403   const T &RHS = S.Stk.pop<T>();
404   const T &LHS = S.Stk.pop<T>();
405   const unsigned Bits = RHS.bitWidth() + 1;
406   return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
407 }
408 
409 static inline llvm::RoundingMode getRoundingMode(FPOptions FPO) {
410   auto RM = FPO.getRoundingMode();
411   if (RM == llvm::RoundingMode::Dynamic)
412     return llvm::RoundingMode::NearestTiesToEven;
413   return RM;
414 }
415 
416 inline bool Addf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
417   const Floating &RHS = S.Stk.pop<Floating>();
418   const Floating &LHS = S.Stk.pop<Floating>();
419 
420   FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
421   Floating Result;
422   auto Status = Floating::add(LHS, RHS, getRoundingMode(FPO), &Result);
423   S.Stk.push<Floating>(Result);
424   return CheckFloatResult(S, OpPC, Result, Status, FPO);
425 }
426 
427 template <PrimType Name, class T = typename PrimConv<Name>::T>
428 bool Sub(InterpState &S, CodePtr OpPC) {
429   const T &RHS = S.Stk.pop<T>();
430   const T &LHS = S.Stk.pop<T>();
431   const unsigned Bits = RHS.bitWidth() + 1;
432   return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS);
433 }
434 
435 inline bool Subf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
436   const Floating &RHS = S.Stk.pop<Floating>();
437   const Floating &LHS = S.Stk.pop<Floating>();
438 
439   FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
440   Floating Result;
441   auto Status = Floating::sub(LHS, RHS, getRoundingMode(FPO), &Result);
442   S.Stk.push<Floating>(Result);
443   return CheckFloatResult(S, OpPC, Result, Status, FPO);
444 }
445 
446 template <PrimType Name, class T = typename PrimConv<Name>::T>
447 bool Mul(InterpState &S, CodePtr OpPC) {
448   const T &RHS = S.Stk.pop<T>();
449   const T &LHS = S.Stk.pop<T>();
450   const unsigned Bits = RHS.bitWidth() * 2;
451   return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS);
452 }
453 
454 inline bool Mulf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
455   const Floating &RHS = S.Stk.pop<Floating>();
456   const Floating &LHS = S.Stk.pop<Floating>();
457 
458   FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
459   Floating Result;
460   auto Status = Floating::mul(LHS, RHS, getRoundingMode(FPO), &Result);
461   S.Stk.push<Floating>(Result);
462   return CheckFloatResult(S, OpPC, Result, Status, FPO);
463 }
464 
465 template <PrimType Name, class T = typename PrimConv<Name>::T>
466 inline bool Mulc(InterpState &S, CodePtr OpPC) {
467   const Pointer &RHS = S.Stk.pop<Pointer>();
468   const Pointer &LHS = S.Stk.pop<Pointer>();
469   const Pointer &Result = S.Stk.peek<Pointer>();
470 
471   if constexpr (std::is_same_v<T, Floating>) {
472     APFloat A = LHS.atIndex(0).deref<Floating>().getAPFloat();
473     APFloat B = LHS.atIndex(1).deref<Floating>().getAPFloat();
474     APFloat C = RHS.atIndex(0).deref<Floating>().getAPFloat();
475     APFloat D = RHS.atIndex(1).deref<Floating>().getAPFloat();
476 
477     APFloat ResR(A.getSemantics());
478     APFloat ResI(A.getSemantics());
479     HandleComplexComplexMul(A, B, C, D, ResR, ResI);
480 
481     // Copy into the result.
482     Result.atIndex(0).deref<Floating>() = Floating(ResR);
483     Result.atIndex(0).initialize();
484     Result.atIndex(1).deref<Floating>() = Floating(ResI);
485     Result.atIndex(1).initialize();
486     Result.initialize();
487   } else {
488     // Integer element type.
489     const T &LHSR = LHS.atIndex(0).deref<T>();
490     const T &LHSI = LHS.atIndex(1).deref<T>();
491     const T &RHSR = RHS.atIndex(0).deref<T>();
492     const T &RHSI = RHS.atIndex(1).deref<T>();
493     unsigned Bits = LHSR.bitWidth();
494 
495     // real(Result) = (real(LHS) * real(RHS)) - (imag(LHS) * imag(RHS))
496     T A;
497     if (T::mul(LHSR, RHSR, Bits, &A))
498       return false;
499     T B;
500     if (T::mul(LHSI, RHSI, Bits, &B))
501       return false;
502     if (T::sub(A, B, Bits, &Result.atIndex(0).deref<T>()))
503       return false;
504     Result.atIndex(0).initialize();
505 
506     // imag(Result) = (real(LHS) * imag(RHS)) + (imag(LHS) * real(RHS))
507     if (T::mul(LHSR, RHSI, Bits, &A))
508       return false;
509     if (T::mul(LHSI, RHSR, Bits, &B))
510       return false;
511     if (T::add(A, B, Bits, &Result.atIndex(1).deref<T>()))
512       return false;
513     Result.atIndex(1).initialize();
514     Result.initialize();
515   }
516 
517   return true;
518 }
519 
520 template <PrimType Name, class T = typename PrimConv<Name>::T>
521 inline bool Divc(InterpState &S, CodePtr OpPC) {
522   const Pointer &RHS = S.Stk.pop<Pointer>();
523   const Pointer &LHS = S.Stk.pop<Pointer>();
524   const Pointer &Result = S.Stk.peek<Pointer>();
525 
526   if constexpr (std::is_same_v<T, Floating>) {
527     APFloat A = LHS.atIndex(0).deref<Floating>().getAPFloat();
528     APFloat B = LHS.atIndex(1).deref<Floating>().getAPFloat();
529     APFloat C = RHS.atIndex(0).deref<Floating>().getAPFloat();
530     APFloat D = RHS.atIndex(1).deref<Floating>().getAPFloat();
531 
532     APFloat ResR(A.getSemantics());
533     APFloat ResI(A.getSemantics());
534     HandleComplexComplexDiv(A, B, C, D, ResR, ResI);
535 
536     // Copy into the result.
537     Result.atIndex(0).deref<Floating>() = Floating(ResR);
538     Result.atIndex(0).initialize();
539     Result.atIndex(1).deref<Floating>() = Floating(ResI);
540     Result.atIndex(1).initialize();
541     Result.initialize();
542   } else {
543     // Integer element type.
544     const T &LHSR = LHS.atIndex(0).deref<T>();
545     const T &LHSI = LHS.atIndex(1).deref<T>();
546     const T &RHSR = RHS.atIndex(0).deref<T>();
547     const T &RHSI = RHS.atIndex(1).deref<T>();
548     unsigned Bits = LHSR.bitWidth();
549     const T Zero = T::from(0, Bits);
550 
551     if (Compare(RHSR, Zero) == ComparisonCategoryResult::Equal &&
552         Compare(RHSI, Zero) == ComparisonCategoryResult::Equal) {
553       const SourceInfo &E = S.Current->getSource(OpPC);
554       S.FFDiag(E, diag::note_expr_divide_by_zero);
555       return false;
556     }
557 
558     // Den = real(RHS)² + imag(RHS)²
559     T A, B;
560     if (T::mul(RHSR, RHSR, Bits, &A) || T::mul(RHSI, RHSI, Bits, &B)) {
561       // Ignore overflow here, because that's what the current interpeter does.
562     }
563     T Den;
564     if (T::add(A, B, Bits, &Den))
565       return false;
566 
567     if (Compare(Den, Zero) == ComparisonCategoryResult::Equal) {
568       const SourceInfo &E = S.Current->getSource(OpPC);
569       S.FFDiag(E, diag::note_expr_divide_by_zero);
570       return false;
571     }
572 
573     // real(Result) = ((real(LHS) * real(RHS)) + (imag(LHS) * imag(RHS))) / Den
574     T &ResultR = Result.atIndex(0).deref<T>();
575     T &ResultI = Result.atIndex(1).deref<T>();
576 
577     if (T::mul(LHSR, RHSR, Bits, &A) || T::mul(LHSI, RHSI, Bits, &B))
578       return false;
579     if (T::add(A, B, Bits, &ResultR))
580       return false;
581     if (T::div(ResultR, Den, Bits, &ResultR))
582       return false;
583     Result.atIndex(0).initialize();
584 
585     // imag(Result) = ((imag(LHS) * real(RHS)) - (real(LHS) * imag(RHS))) / Den
586     if (T::mul(LHSI, RHSR, Bits, &A) || T::mul(LHSR, RHSI, Bits, &B))
587       return false;
588     if (T::sub(A, B, Bits, &ResultI))
589       return false;
590     if (T::div(ResultI, Den, Bits, &ResultI))
591       return false;
592     Result.atIndex(1).initialize();
593     Result.initialize();
594   }
595 
596   return true;
597 }
598 
599 /// 1) Pops the RHS from the stack.
600 /// 2) Pops the LHS from the stack.
601 /// 3) Pushes 'LHS & RHS' on the stack
602 template <PrimType Name, class T = typename PrimConv<Name>::T>
603 bool BitAnd(InterpState &S, CodePtr OpPC) {
604   const T &RHS = S.Stk.pop<T>();
605   const T &LHS = S.Stk.pop<T>();
606 
607   unsigned Bits = RHS.bitWidth();
608   T Result;
609   if (!T::bitAnd(LHS, RHS, Bits, &Result)) {
610     S.Stk.push<T>(Result);
611     return true;
612   }
613   return false;
614 }
615 
616 /// 1) Pops the RHS from the stack.
617 /// 2) Pops the LHS from the stack.
618 /// 3) Pushes 'LHS | RHS' on the stack
619 template <PrimType Name, class T = typename PrimConv<Name>::T>
620 bool BitOr(InterpState &S, CodePtr OpPC) {
621   const T &RHS = S.Stk.pop<T>();
622   const T &LHS = S.Stk.pop<T>();
623 
624   unsigned Bits = RHS.bitWidth();
625   T Result;
626   if (!T::bitOr(LHS, RHS, Bits, &Result)) {
627     S.Stk.push<T>(Result);
628     return true;
629   }
630   return false;
631 }
632 
633 /// 1) Pops the RHS from the stack.
634 /// 2) Pops the LHS from the stack.
635 /// 3) Pushes 'LHS ^ RHS' on the stack
636 template <PrimType Name, class T = typename PrimConv<Name>::T>
637 bool BitXor(InterpState &S, CodePtr OpPC) {
638   const T &RHS = S.Stk.pop<T>();
639   const T &LHS = S.Stk.pop<T>();
640 
641   unsigned Bits = RHS.bitWidth();
642   T Result;
643   if (!T::bitXor(LHS, RHS, Bits, &Result)) {
644     S.Stk.push<T>(Result);
645     return true;
646   }
647   return false;
648 }
649 
650 /// 1) Pops the RHS from the stack.
651 /// 2) Pops the LHS from the stack.
652 /// 3) Pushes 'LHS % RHS' on the stack (the remainder of dividing LHS by RHS).
653 template <PrimType Name, class T = typename PrimConv<Name>::T>
654 bool Rem(InterpState &S, CodePtr OpPC) {
655   const T &RHS = S.Stk.pop<T>();
656   const T &LHS = S.Stk.pop<T>();
657 
658   if (!CheckDivRem(S, OpPC, LHS, RHS))
659     return false;
660 
661   const unsigned Bits = RHS.bitWidth() * 2;
662   T Result;
663   if (!T::rem(LHS, RHS, Bits, &Result)) {
664     S.Stk.push<T>(Result);
665     return true;
666   }
667   return false;
668 }
669 
670 /// 1) Pops the RHS from the stack.
671 /// 2) Pops the LHS from the stack.
672 /// 3) Pushes 'LHS / RHS' on the stack
673 template <PrimType Name, class T = typename PrimConv<Name>::T>
674 bool Div(InterpState &S, CodePtr OpPC) {
675   const T &RHS = S.Stk.pop<T>();
676   const T &LHS = S.Stk.pop<T>();
677 
678   if (!CheckDivRem(S, OpPC, LHS, RHS))
679     return false;
680 
681   const unsigned Bits = RHS.bitWidth() * 2;
682   T Result;
683   if (!T::div(LHS, RHS, Bits, &Result)) {
684     S.Stk.push<T>(Result);
685     return true;
686   }
687 
688   if constexpr (std::is_same_v<T, FixedPoint>) {
689     if (handleFixedPointOverflow(S, OpPC, Result)) {
690       S.Stk.push<T>(Result);
691       return true;
692     }
693   }
694   return false;
695 }
696 
697 inline bool Divf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
698   const Floating &RHS = S.Stk.pop<Floating>();
699   const Floating &LHS = S.Stk.pop<Floating>();
700 
701   if (!CheckDivRem(S, OpPC, LHS, RHS))
702     return false;
703 
704   FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
705   Floating Result;
706   auto Status = Floating::div(LHS, RHS, getRoundingMode(FPO), &Result);
707   S.Stk.push<Floating>(Result);
708   return CheckFloatResult(S, OpPC, Result, Status, FPO);
709 }
710 
711 //===----------------------------------------------------------------------===//
712 // Inv
713 //===----------------------------------------------------------------------===//
714 
715 inline bool Inv(InterpState &S, CodePtr OpPC) {
716   const auto &Val = S.Stk.pop<Boolean>();
717   S.Stk.push<Boolean>(!Val);
718   return true;
719 }
720 
721 //===----------------------------------------------------------------------===//
722 // Neg
723 //===----------------------------------------------------------------------===//
724 
725 template <PrimType Name, class T = typename PrimConv<Name>::T>
726 bool Neg(InterpState &S, CodePtr OpPC) {
727   const T &Value = S.Stk.pop<T>();
728   T Result;
729 
730   if (!T::neg(Value, &Result)) {
731     S.Stk.push<T>(Result);
732     return true;
733   }
734 
735   assert(isIntegralType(Name) &&
736          "don't expect other types to fail at constexpr negation");
737   S.Stk.push<T>(Result);
738 
739   APSInt NegatedValue = -Value.toAPSInt(Value.bitWidth() + 1);
740   const Expr *E = S.Current->getExpr(OpPC);
741   QualType Type = E->getType();
742 
743   if (S.checkingForUndefinedBehavior()) {
744     SmallString<32> Trunc;
745     NegatedValue.trunc(Result.bitWidth())
746         .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
747                   /*UpperCase=*/true, /*InsertSeparators=*/true);
748     auto Loc = E->getExprLoc();
749     S.report(Loc, diag::warn_integer_constant_overflow)
750         << Trunc << Type << E->getSourceRange();
751     return true;
752   }
753 
754   return handleOverflow(S, OpPC, NegatedValue);
755 }
756 
757 enum class PushVal : bool {
758   No,
759   Yes,
760 };
761 enum class IncDecOp {
762   Inc,
763   Dec,
764 };
765 
766 template <typename T, IncDecOp Op, PushVal DoPush>
767 bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
768   assert(!Ptr.isDummy());
769 
770   if constexpr (std::is_same_v<T, Boolean>) {
771     if (!S.getLangOpts().CPlusPlus14)
772       return Invalid(S, OpPC);
773   }
774 
775   const T &Value = Ptr.deref<T>();
776   T Result;
777 
778   if constexpr (DoPush == PushVal::Yes)
779     S.Stk.push<T>(Value);
780 
781   if constexpr (Op == IncDecOp::Inc) {
782     if (!T::increment(Value, &Result)) {
783       Ptr.deref<T>() = Result;
784       return true;
785     }
786   } else {
787     if (!T::decrement(Value, &Result)) {
788       Ptr.deref<T>() = Result;
789       return true;
790     }
791   }
792 
793   // Something went wrong with the previous operation. Compute the
794   // result with another bit of precision.
795   unsigned Bits = Value.bitWidth() + 1;
796   APSInt APResult;
797   if constexpr (Op == IncDecOp::Inc)
798     APResult = ++Value.toAPSInt(Bits);
799   else
800     APResult = --Value.toAPSInt(Bits);
801 
802   // Report undefined behaviour, stopping if required.
803   const Expr *E = S.Current->getExpr(OpPC);
804   QualType Type = E->getType();
805   if (S.checkingForUndefinedBehavior()) {
806     SmallString<32> Trunc;
807     APResult.trunc(Result.bitWidth())
808         .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
809                   /*UpperCase=*/true, /*InsertSeparators=*/true);
810     auto Loc = E->getExprLoc();
811     S.report(Loc, diag::warn_integer_constant_overflow)
812         << Trunc << Type << E->getSourceRange();
813     return true;
814   }
815 
816   return handleOverflow(S, OpPC, APResult);
817 }
818 
819 /// 1) Pops a pointer from the stack
820 /// 2) Load the value from the pointer
821 /// 3) Writes the value increased by one back to the pointer
822 /// 4) Pushes the original (pre-inc) value on the stack.
823 template <PrimType Name, class T = typename PrimConv<Name>::T>
824 bool Inc(InterpState &S, CodePtr OpPC) {
825   const Pointer &Ptr = S.Stk.pop<Pointer>();
826   if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
827     return false;
828 
829   return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr);
830 }
831 
832 /// 1) Pops a pointer from the stack
833 /// 2) Load the value from the pointer
834 /// 3) Writes the value increased by one back to the pointer
835 template <PrimType Name, class T = typename PrimConv<Name>::T>
836 bool IncPop(InterpState &S, CodePtr OpPC) {
837   const Pointer &Ptr = S.Stk.pop<Pointer>();
838   if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
839     return false;
840 
841   return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr);
842 }
843 
844 /// 1) Pops a pointer from the stack
845 /// 2) Load the value from the pointer
846 /// 3) Writes the value decreased by one back to the pointer
847 /// 4) Pushes the original (pre-dec) value on the stack.
848 template <PrimType Name, class T = typename PrimConv<Name>::T>
849 bool Dec(InterpState &S, CodePtr OpPC) {
850   const Pointer &Ptr = S.Stk.pop<Pointer>();
851   if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
852     return false;
853 
854   return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr);
855 }
856 
857 /// 1) Pops a pointer from the stack
858 /// 2) Load the value from the pointer
859 /// 3) Writes the value decreased by one back to the pointer
860 template <PrimType Name, class T = typename PrimConv<Name>::T>
861 bool DecPop(InterpState &S, CodePtr OpPC) {
862   const Pointer &Ptr = S.Stk.pop<Pointer>();
863   if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
864     return false;
865 
866   return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr);
867 }
868 
869 template <IncDecOp Op, PushVal DoPush>
870 bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
871                        uint32_t FPOI) {
872   Floating Value = Ptr.deref<Floating>();
873   Floating Result;
874 
875   if constexpr (DoPush == PushVal::Yes)
876     S.Stk.push<Floating>(Value);
877 
878   FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
879   llvm::APFloat::opStatus Status;
880   if constexpr (Op == IncDecOp::Inc)
881     Status = Floating::increment(Value, getRoundingMode(FPO), &Result);
882   else
883     Status = Floating::decrement(Value, getRoundingMode(FPO), &Result);
884 
885   Ptr.deref<Floating>() = Result;
886 
887   return CheckFloatResult(S, OpPC, Result, Status, FPO);
888 }
889 
890 inline bool Incf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
891   const Pointer &Ptr = S.Stk.pop<Pointer>();
892   if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
893     return false;
894 
895   return IncDecFloatHelper<IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, FPOI);
896 }
897 
898 inline bool IncfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
899   const Pointer &Ptr = S.Stk.pop<Pointer>();
900   if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
901     return false;
902 
903   return IncDecFloatHelper<IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, FPOI);
904 }
905 
906 inline bool Decf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
907   const Pointer &Ptr = S.Stk.pop<Pointer>();
908   if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
909     return false;
910 
911   return IncDecFloatHelper<IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, FPOI);
912 }
913 
914 inline bool DecfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
915   const Pointer &Ptr = S.Stk.pop<Pointer>();
916   if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
917     return false;
918 
919   return IncDecFloatHelper<IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, FPOI);
920 }
921 
922 /// 1) Pops the value from the stack.
923 /// 2) Pushes the bitwise complemented value on the stack (~V).
924 template <PrimType Name, class T = typename PrimConv<Name>::T>
925 bool Comp(InterpState &S, CodePtr OpPC) {
926   const T &Val = S.Stk.pop<T>();
927   T Result;
928   if (!T::comp(Val, &Result)) {
929     S.Stk.push<T>(Result);
930     return true;
931   }
932 
933   return false;
934 }
935 
936 //===----------------------------------------------------------------------===//
937 // EQ, NE, GT, GE, LT, LE
938 //===----------------------------------------------------------------------===//
939 
940 using CompareFn = llvm::function_ref<bool(ComparisonCategoryResult)>;
941 
942 template <typename T>
943 bool CmpHelper(InterpState &S, CodePtr OpPC, CompareFn Fn) {
944   assert((!std::is_same_v<T, MemberPointer>) &&
945          "Non-equality comparisons on member pointer types should already be "
946          "rejected in Sema.");
947   using BoolT = PrimConv<PT_Bool>::T;
948   const T &RHS = S.Stk.pop<T>();
949   const T &LHS = S.Stk.pop<T>();
950   S.Stk.push<BoolT>(BoolT::from(Fn(LHS.compare(RHS))));
951   return true;
952 }
953 
954 template <typename T>
955 bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn) {
956   return CmpHelper<T>(S, OpPC, Fn);
957 }
958 
959 /// Function pointers cannot be compared in an ordered way.
960 template <>
961 inline bool CmpHelper<FunctionPointer>(InterpState &S, CodePtr OpPC,
962                                        CompareFn Fn) {
963   const auto &RHS = S.Stk.pop<FunctionPointer>();
964   const auto &LHS = S.Stk.pop<FunctionPointer>();
965 
966   const SourceInfo &Loc = S.Current->getSource(OpPC);
967   S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
968       << LHS.toDiagnosticString(S.getASTContext())
969       << RHS.toDiagnosticString(S.getASTContext());
970   return false;
971 }
972 
973 template <>
974 inline bool CmpHelperEQ<FunctionPointer>(InterpState &S, CodePtr OpPC,
975                                          CompareFn Fn) {
976   const auto &RHS = S.Stk.pop<FunctionPointer>();
977   const auto &LHS = S.Stk.pop<FunctionPointer>();
978 
979   // We cannot compare against weak declarations at compile time.
980   for (const auto &FP : {LHS, RHS}) {
981     if (FP.isWeak()) {
982       const SourceInfo &Loc = S.Current->getSource(OpPC);
983       S.FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison)
984           << FP.toDiagnosticString(S.getASTContext());
985       return false;
986     }
987   }
988 
989   S.Stk.push<Boolean>(Boolean::from(Fn(LHS.compare(RHS))));
990   return true;
991 }
992 
993 template <>
994 inline bool CmpHelper<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
995   using BoolT = PrimConv<PT_Bool>::T;
996   const Pointer &RHS = S.Stk.pop<Pointer>();
997   const Pointer &LHS = S.Stk.pop<Pointer>();
998 
999   if (!Pointer::hasSameBase(LHS, RHS)) {
1000     const SourceInfo &Loc = S.Current->getSource(OpPC);
1001     S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1002         << LHS.toDiagnosticString(S.getASTContext())
1003         << RHS.toDiagnosticString(S.getASTContext());
1004     return false;
1005   } else {
1006     unsigned VL = LHS.getByteOffset();
1007     unsigned VR = RHS.getByteOffset();
1008     S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
1009     return true;
1010   }
1011 }
1012 
1013 template <>
1014 inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
1015   using BoolT = PrimConv<PT_Bool>::T;
1016   const Pointer &RHS = S.Stk.pop<Pointer>();
1017   const Pointer &LHS = S.Stk.pop<Pointer>();
1018 
1019   if (LHS.isZero() && RHS.isZero()) {
1020     S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Equal)));
1021     return true;
1022   }
1023 
1024   // Reject comparisons to weak pointers.
1025   for (const auto &P : {LHS, RHS}) {
1026     if (P.isZero())
1027       continue;
1028     if (P.isWeak()) {
1029       const SourceInfo &Loc = S.Current->getSource(OpPC);
1030       S.FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison)
1031           << P.toDiagnosticString(S.getASTContext());
1032       return false;
1033     }
1034   }
1035 
1036   if (Pointer::hasSameBase(LHS, RHS)) {
1037     unsigned VL = LHS.getByteOffset();
1038     unsigned VR = RHS.getByteOffset();
1039 
1040     // In our Pointer class, a pointer to an array and a pointer to the first
1041     // element in the same array are NOT equal. They have the same Base value,
1042     // but a different Offset. This is a pretty rare case, so we fix this here
1043     // by comparing pointers to the first elements.
1044     if (!LHS.isZero() && LHS.isArrayRoot())
1045       VL = LHS.atIndex(0).getByteOffset();
1046     if (!RHS.isZero() && RHS.isArrayRoot())
1047       VR = RHS.atIndex(0).getByteOffset();
1048 
1049     S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
1050     return true;
1051   }
1052   // Otherwise we need to do a bunch of extra checks before returning Unordered.
1053   if (LHS.isOnePastEnd() && !RHS.isOnePastEnd() && !RHS.isZero() &&
1054       RHS.getOffset() == 0) {
1055     const SourceInfo &Loc = S.Current->getSource(OpPC);
1056     S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
1057         << LHS.toDiagnosticString(S.getASTContext());
1058     return false;
1059   } else if (RHS.isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() &&
1060              LHS.getOffset() == 0) {
1061     const SourceInfo &Loc = S.Current->getSource(OpPC);
1062     S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
1063         << RHS.toDiagnosticString(S.getASTContext());
1064     return false;
1065   }
1066 
1067   bool BothNonNull = !LHS.isZero() && !RHS.isZero();
1068   // Reject comparisons to literals.
1069   for (const auto &P : {LHS, RHS}) {
1070     if (P.isZero())
1071       continue;
1072     if (BothNonNull && P.pointsToLiteral()) {
1073       const SourceInfo &Loc = S.Current->getSource(OpPC);
1074       S.FFDiag(Loc, diag::note_constexpr_literal_comparison);
1075       return false;
1076     }
1077   }
1078 
1079   S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Unordered)));
1080   return true;
1081 }
1082 
1083 template <>
1084 inline bool CmpHelperEQ<MemberPointer>(InterpState &S, CodePtr OpPC,
1085                                        CompareFn Fn) {
1086   const auto &RHS = S.Stk.pop<MemberPointer>();
1087   const auto &LHS = S.Stk.pop<MemberPointer>();
1088 
1089   // If either operand is a pointer to a weak function, the comparison is not
1090   // constant.
1091   for (const auto &MP : {LHS, RHS}) {
1092     if (MP.isWeak()) {
1093       const SourceInfo &Loc = S.Current->getSource(OpPC);
1094       S.FFDiag(Loc, diag::note_constexpr_mem_pointer_weak_comparison)
1095           << MP.getMemberFunction();
1096       return false;
1097     }
1098   }
1099 
1100   // C++11 [expr.eq]p2:
1101   //   If both operands are null, they compare equal. Otherwise if only one is
1102   //   null, they compare unequal.
1103   if (LHS.isZero() && RHS.isZero()) {
1104     S.Stk.push<Boolean>(Fn(ComparisonCategoryResult::Equal));
1105     return true;
1106   }
1107   if (LHS.isZero() || RHS.isZero()) {
1108     S.Stk.push<Boolean>(Fn(ComparisonCategoryResult::Unordered));
1109     return true;
1110   }
1111 
1112   // We cannot compare against virtual declarations at compile time.
1113   for (const auto &MP : {LHS, RHS}) {
1114     if (const CXXMethodDecl *MD = MP.getMemberFunction();
1115         MD && MD->isVirtual()) {
1116       const SourceInfo &Loc = S.Current->getSource(OpPC);
1117       S.CCEDiag(Loc, diag::note_constexpr_compare_virtual_mem_ptr) << MD;
1118     }
1119   }
1120 
1121   S.Stk.push<Boolean>(Boolean::from(Fn(LHS.compare(RHS))));
1122   return true;
1123 }
1124 
1125 template <PrimType Name, class T = typename PrimConv<Name>::T>
1126 bool EQ(InterpState &S, CodePtr OpPC) {
1127   return CmpHelperEQ<T>(S, OpPC, [](ComparisonCategoryResult R) {
1128     return R == ComparisonCategoryResult::Equal;
1129   });
1130 }
1131 
1132 template <PrimType Name, class T = typename PrimConv<Name>::T>
1133 bool CMP3(InterpState &S, CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo) {
1134   const T &RHS = S.Stk.pop<T>();
1135   const T &LHS = S.Stk.pop<T>();
1136   const Pointer &P = S.Stk.peek<Pointer>();
1137 
1138   ComparisonCategoryResult CmpResult = LHS.compare(RHS);
1139   if (CmpResult == ComparisonCategoryResult::Unordered) {
1140     // This should only happen with pointers.
1141     const SourceInfo &Loc = S.Current->getSource(OpPC);
1142     S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1143         << LHS.toDiagnosticString(S.getASTContext())
1144         << RHS.toDiagnosticString(S.getASTContext());
1145     return false;
1146   }
1147 
1148   assert(CmpInfo);
1149   const auto *CmpValueInfo =
1150       CmpInfo->getValueInfo(CmpInfo->makeWeakResult(CmpResult));
1151   assert(CmpValueInfo);
1152   assert(CmpValueInfo->hasValidIntValue());
1153   return SetThreeWayComparisonField(S, OpPC, P, CmpValueInfo->getIntValue());
1154 }
1155 
1156 template <PrimType Name, class T = typename PrimConv<Name>::T>
1157 bool NE(InterpState &S, CodePtr OpPC) {
1158   return CmpHelperEQ<T>(S, OpPC, [](ComparisonCategoryResult R) {
1159     return R != ComparisonCategoryResult::Equal;
1160   });
1161 }
1162 
1163 template <PrimType Name, class T = typename PrimConv<Name>::T>
1164 bool LT(InterpState &S, CodePtr OpPC) {
1165   return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
1166     return R == ComparisonCategoryResult::Less;
1167   });
1168 }
1169 
1170 template <PrimType Name, class T = typename PrimConv<Name>::T>
1171 bool LE(InterpState &S, CodePtr OpPC) {
1172   return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
1173     return R == ComparisonCategoryResult::Less ||
1174            R == ComparisonCategoryResult::Equal;
1175   });
1176 }
1177 
1178 template <PrimType Name, class T = typename PrimConv<Name>::T>
1179 bool GT(InterpState &S, CodePtr OpPC) {
1180   return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
1181     return R == ComparisonCategoryResult::Greater;
1182   });
1183 }
1184 
1185 template <PrimType Name, class T = typename PrimConv<Name>::T>
1186 bool GE(InterpState &S, CodePtr OpPC) {
1187   return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
1188     return R == ComparisonCategoryResult::Greater ||
1189            R == ComparisonCategoryResult::Equal;
1190   });
1191 }
1192 
1193 //===----------------------------------------------------------------------===//
1194 // InRange
1195 //===----------------------------------------------------------------------===//
1196 
1197 template <PrimType Name, class T = typename PrimConv<Name>::T>
1198 bool InRange(InterpState &S, CodePtr OpPC) {
1199   const T RHS = S.Stk.pop<T>();
1200   const T LHS = S.Stk.pop<T>();
1201   const T Value = S.Stk.pop<T>();
1202 
1203   S.Stk.push<bool>(LHS <= Value && Value <= RHS);
1204   return true;
1205 }
1206 
1207 //===----------------------------------------------------------------------===//
1208 // Dup, Pop, Test
1209 //===----------------------------------------------------------------------===//
1210 
1211 template <PrimType Name, class T = typename PrimConv<Name>::T>
1212 bool Dup(InterpState &S, CodePtr OpPC) {
1213   S.Stk.push<T>(S.Stk.peek<T>());
1214   return true;
1215 }
1216 
1217 template <PrimType Name, class T = typename PrimConv<Name>::T>
1218 bool Pop(InterpState &S, CodePtr OpPC) {
1219   S.Stk.pop<T>();
1220   return true;
1221 }
1222 
1223 /// [Value1, Value2] -> [Value2, Value1]
1224 template <PrimType TopName, PrimType BottomName>
1225 bool Flip(InterpState &S, CodePtr OpPC) {
1226   using TopT = typename PrimConv<TopName>::T;
1227   using BottomT = typename PrimConv<BottomName>::T;
1228 
1229   const auto &Top = S.Stk.pop<TopT>();
1230   const auto &Bottom = S.Stk.pop<BottomT>();
1231 
1232   S.Stk.push<TopT>(Top);
1233   S.Stk.push<BottomT>(Bottom);
1234 
1235   return true;
1236 }
1237 
1238 //===----------------------------------------------------------------------===//
1239 // Const
1240 //===----------------------------------------------------------------------===//
1241 
1242 template <PrimType Name, class T = typename PrimConv<Name>::T>
1243 bool Const(InterpState &S, CodePtr OpPC, const T &Arg) {
1244   S.Stk.push<T>(Arg);
1245   return true;
1246 }
1247 
1248 //===----------------------------------------------------------------------===//
1249 // Get/Set Local/Param/Global/This
1250 //===----------------------------------------------------------------------===//
1251 
1252 template <PrimType Name, class T = typename PrimConv<Name>::T>
1253 bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
1254   const Pointer &Ptr = S.Current->getLocalPointer(I);
1255   if (!CheckLoad(S, OpPC, Ptr))
1256     return false;
1257   S.Stk.push<T>(Ptr.deref<T>());
1258   return true;
1259 }
1260 
1261 /// 1) Pops the value from the stack.
1262 /// 2) Writes the value to the local variable with the
1263 ///    given offset.
1264 template <PrimType Name, class T = typename PrimConv<Name>::T>
1265 bool SetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
1266   S.Current->setLocal<T>(I, S.Stk.pop<T>());
1267   return true;
1268 }
1269 
1270 template <PrimType Name, class T = typename PrimConv<Name>::T>
1271 bool GetParam(InterpState &S, CodePtr OpPC, uint32_t I) {
1272   if (S.checkingPotentialConstantExpression()) {
1273     return false;
1274   }
1275   S.Stk.push<T>(S.Current->getParam<T>(I));
1276   return true;
1277 }
1278 
1279 template <PrimType Name, class T = typename PrimConv<Name>::T>
1280 bool SetParam(InterpState &S, CodePtr OpPC, uint32_t I) {
1281   S.Current->setParam<T>(I, S.Stk.pop<T>());
1282   return true;
1283 }
1284 
1285 /// 1) Peeks a pointer on the stack
1286 /// 2) Pushes the value of the pointer's field on the stack
1287 template <PrimType Name, class T = typename PrimConv<Name>::T>
1288 bool GetField(InterpState &S, CodePtr OpPC, uint32_t I) {
1289   const Pointer &Obj = S.Stk.peek<Pointer>();
1290   if (!CheckNull(S, OpPC, Obj, CSK_Field))
1291     return false;
1292   if (!CheckRange(S, OpPC, Obj, CSK_Field))
1293     return false;
1294   const Pointer &Field = Obj.atField(I);
1295   if (!CheckLoad(S, OpPC, Field))
1296     return false;
1297   S.Stk.push<T>(Field.deref<T>());
1298   return true;
1299 }
1300 
1301 template <PrimType Name, class T = typename PrimConv<Name>::T>
1302 bool SetField(InterpState &S, CodePtr OpPC, uint32_t I) {
1303   const T &Value = S.Stk.pop<T>();
1304   const Pointer &Obj = S.Stk.peek<Pointer>();
1305   if (!CheckNull(S, OpPC, Obj, CSK_Field))
1306     return false;
1307   if (!CheckRange(S, OpPC, Obj, CSK_Field))
1308     return false;
1309   const Pointer &Field = Obj.atField(I);
1310   if (!CheckStore(S, OpPC, Field))
1311     return false;
1312   Field.initialize();
1313   Field.deref<T>() = Value;
1314   return true;
1315 }
1316 
1317 /// 1) Pops a pointer from the stack
1318 /// 2) Pushes the value of the pointer's field on the stack
1319 template <PrimType Name, class T = typename PrimConv<Name>::T>
1320 bool GetFieldPop(InterpState &S, CodePtr OpPC, uint32_t I) {
1321   const Pointer &Obj = S.Stk.pop<Pointer>();
1322   if (!CheckNull(S, OpPC, Obj, CSK_Field))
1323     return false;
1324   if (!CheckRange(S, OpPC, Obj, CSK_Field))
1325     return false;
1326   const Pointer &Field = Obj.atField(I);
1327   if (!CheckLoad(S, OpPC, Field))
1328     return false;
1329   S.Stk.push<T>(Field.deref<T>());
1330   return true;
1331 }
1332 
1333 template <PrimType Name, class T = typename PrimConv<Name>::T>
1334 bool GetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
1335   if (S.checkingPotentialConstantExpression())
1336     return false;
1337   const Pointer &This = S.Current->getThis();
1338   if (!CheckThis(S, OpPC, This))
1339     return false;
1340   const Pointer &Field = This.atField(I);
1341   if (!CheckLoad(S, OpPC, Field))
1342     return false;
1343   S.Stk.push<T>(Field.deref<T>());
1344   return true;
1345 }
1346 
1347 template <PrimType Name, class T = typename PrimConv<Name>::T>
1348 bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
1349   if (S.checkingPotentialConstantExpression())
1350     return false;
1351   const T &Value = S.Stk.pop<T>();
1352   const Pointer &This = S.Current->getThis();
1353   if (!CheckThis(S, OpPC, This))
1354     return false;
1355   const Pointer &Field = This.atField(I);
1356   if (!CheckStore(S, OpPC, Field))
1357     return false;
1358   Field.deref<T>() = Value;
1359   return true;
1360 }
1361 
1362 template <PrimType Name, class T = typename PrimConv<Name>::T>
1363 bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
1364   const Pointer &Ptr = S.P.getPtrGlobal(I);
1365   if (!CheckConstant(S, OpPC, Ptr.getFieldDesc()))
1366     return false;
1367   if (Ptr.isExtern())
1368     return false;
1369 
1370   // If a global variable is uninitialized, that means the initializer we've
1371   // compiled for it wasn't a constant expression. Diagnose that.
1372   if (!CheckGlobalInitialized(S, OpPC, Ptr))
1373     return false;
1374 
1375   S.Stk.push<T>(Ptr.deref<T>());
1376   return true;
1377 }
1378 
1379 /// Same as GetGlobal, but without the checks.
1380 template <PrimType Name, class T = typename PrimConv<Name>::T>
1381 bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I) {
1382   const Pointer &Ptr = S.P.getPtrGlobal(I);
1383   if (!Ptr.isInitialized())
1384     return false;
1385   S.Stk.push<T>(Ptr.deref<T>());
1386   return true;
1387 }
1388 
1389 template <PrimType Name, class T = typename PrimConv<Name>::T>
1390 bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
1391   // TODO: emit warning.
1392   return false;
1393 }
1394 
1395 template <PrimType Name, class T = typename PrimConv<Name>::T>
1396 bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
1397   const Pointer &P = S.P.getGlobal(I);
1398   P.deref<T>() = S.Stk.pop<T>();
1399   P.initialize();
1400   return true;
1401 }
1402 
1403 /// 1) Converts the value on top of the stack to an APValue
1404 /// 2) Sets that APValue on \Temp
1405 /// 3) Initializes global with index \I with that
1406 template <PrimType Name, class T = typename PrimConv<Name>::T>
1407 bool InitGlobalTemp(InterpState &S, CodePtr OpPC, uint32_t I,
1408                     const LifetimeExtendedTemporaryDecl *Temp) {
1409   const Pointer &Ptr = S.P.getGlobal(I);
1410 
1411   const T Value = S.Stk.peek<T>();
1412   APValue APV = Value.toAPValue(S.getASTContext());
1413   APValue *Cached = Temp->getOrCreateValue(true);
1414   *Cached = APV;
1415 
1416   assert(Ptr.getDeclDesc()->asExpr());
1417 
1418   S.SeenGlobalTemporaries.push_back(
1419       std::make_pair(Ptr.getDeclDesc()->asExpr(), Temp));
1420 
1421   Ptr.deref<T>() = S.Stk.pop<T>();
1422   Ptr.initialize();
1423   return true;
1424 }
1425 
1426 /// 1) Converts the value on top of the stack to an APValue
1427 /// 2) Sets that APValue on \Temp
1428 /// 3) Initialized global with index \I with that
1429 inline bool InitGlobalTempComp(InterpState &S, CodePtr OpPC,
1430                                const LifetimeExtendedTemporaryDecl *Temp) {
1431   assert(Temp);
1432   const Pointer &P = S.Stk.peek<Pointer>();
1433   APValue *Cached = Temp->getOrCreateValue(true);
1434 
1435   S.SeenGlobalTemporaries.push_back(
1436       std::make_pair(P.getDeclDesc()->asExpr(), Temp));
1437 
1438   if (std::optional<APValue> APV =
1439           P.toRValue(S.getASTContext(), Temp->getTemporaryExpr()->getType())) {
1440     *Cached = *APV;
1441     return true;
1442   }
1443 
1444   return false;
1445 }
1446 
1447 template <PrimType Name, class T = typename PrimConv<Name>::T>
1448 bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
1449   if (S.checkingPotentialConstantExpression())
1450     return false;
1451   const Pointer &This = S.Current->getThis();
1452   if (!CheckThis(S, OpPC, This))
1453     return false;
1454   const Pointer &Field = This.atField(I);
1455   Field.deref<T>() = S.Stk.pop<T>();
1456   Field.activate();
1457   Field.initialize();
1458   return true;
1459 }
1460 
1461 // FIXME: The Field pointer here is too much IMO and we could instead just
1462 // pass an Offset + BitWidth pair.
1463 template <PrimType Name, class T = typename PrimConv<Name>::T>
1464 bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F,
1465                       uint32_t FieldOffset) {
1466   assert(F->isBitField());
1467   if (S.checkingPotentialConstantExpression())
1468     return false;
1469   const Pointer &This = S.Current->getThis();
1470   if (!CheckThis(S, OpPC, This))
1471     return false;
1472   const Pointer &Field = This.atField(FieldOffset);
1473   const auto &Value = S.Stk.pop<T>();
1474   Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
1475   Field.initialize();
1476   return true;
1477 }
1478 
1479 /// 1) Pops the value from the stack
1480 /// 2) Peeks a pointer from the stack
1481 /// 3) Pushes the value to field I of the pointer on the stack
1482 template <PrimType Name, class T = typename PrimConv<Name>::T>
1483 bool InitField(InterpState &S, CodePtr OpPC, uint32_t I) {
1484   const T &Value = S.Stk.pop<T>();
1485   const Pointer &Field = S.Stk.peek<Pointer>().atField(I);
1486   Field.deref<T>() = Value;
1487   Field.activate();
1488   Field.initialize();
1489   return true;
1490 }
1491 
1492 template <PrimType Name, class T = typename PrimConv<Name>::T>
1493 bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
1494   assert(F->isBitField());
1495   const T &Value = S.Stk.pop<T>();
1496   const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset);
1497   Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
1498   Field.activate();
1499   Field.initialize();
1500   return true;
1501 }
1502 
1503 //===----------------------------------------------------------------------===//
1504 // GetPtr Local/Param/Global/Field/This
1505 //===----------------------------------------------------------------------===//
1506 
1507 inline bool GetPtrLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
1508   S.Stk.push<Pointer>(S.Current->getLocalPointer(I));
1509   return true;
1510 }
1511 
1512 inline bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t I) {
1513   if (S.checkingPotentialConstantExpression()) {
1514     return false;
1515   }
1516   S.Stk.push<Pointer>(S.Current->getParamPointer(I));
1517   return true;
1518 }
1519 
1520 inline bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
1521   S.Stk.push<Pointer>(S.P.getPtrGlobal(I));
1522   return true;
1523 }
1524 
1525 /// 1) Peeks a Pointer
1526 /// 2) Pushes Pointer.atField(Off) on the stack
1527 bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off);
1528 bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off);
1529 
1530 inline bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1531   if (S.checkingPotentialConstantExpression())
1532     return false;
1533   const Pointer &This = S.Current->getThis();
1534   if (!CheckThis(S, OpPC, This))
1535     return false;
1536   S.Stk.push<Pointer>(This.atField(Off));
1537   return true;
1538 }
1539 
1540 inline bool GetPtrActiveField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1541   const Pointer &Ptr = S.Stk.pop<Pointer>();
1542   if (!CheckNull(S, OpPC, Ptr, CSK_Field))
1543     return false;
1544   if (!CheckRange(S, OpPC, Ptr, CSK_Field))
1545     return false;
1546   Pointer Field = Ptr.atField(Off);
1547   Ptr.deactivate();
1548   Field.activate();
1549   S.Stk.push<Pointer>(std::move(Field));
1550   return true;
1551 }
1552 
1553 inline bool GetPtrActiveThisField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1554   if (S.checkingPotentialConstantExpression())
1555     return false;
1556   const Pointer &This = S.Current->getThis();
1557   if (!CheckThis(S, OpPC, This))
1558     return false;
1559   Pointer Field = This.atField(Off);
1560   This.deactivate();
1561   Field.activate();
1562   S.Stk.push<Pointer>(std::move(Field));
1563   return true;
1564 }
1565 
1566 inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
1567   const Pointer &Ptr = S.Stk.pop<Pointer>();
1568   if (!CheckNull(S, OpPC, Ptr, CSK_Derived))
1569     return false;
1570   if (!CheckSubobject(S, OpPC, Ptr, CSK_Derived))
1571     return false;
1572   if (!CheckDowncast(S, OpPC, Ptr, Off))
1573     return false;
1574 
1575   S.Stk.push<Pointer>(Ptr.atFieldSub(Off));
1576   return true;
1577 }
1578 
1579 inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
1580   const Pointer &Ptr = S.Stk.peek<Pointer>();
1581   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
1582     return false;
1583 
1584   if (!Ptr.isBlockPointer()) {
1585     S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.getASTContext(), Off));
1586     return true;
1587   }
1588 
1589   if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
1590     return false;
1591   const Pointer &Result = Ptr.atField(Off);
1592   if (Result.isPastEnd() || !Result.isBaseClass())
1593     return false;
1594   S.Stk.push<Pointer>(Result);
1595   return true;
1596 }
1597 
1598 inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off) {
1599   const Pointer &Ptr = S.Stk.pop<Pointer>();
1600 
1601   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
1602     return false;
1603 
1604   if (!Ptr.isBlockPointer()) {
1605     S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.getASTContext(), Off));
1606     return true;
1607   }
1608 
1609   if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
1610     return false;
1611   const Pointer &Result = Ptr.atField(Off);
1612   if (Result.isPastEnd() || !Result.isBaseClass())
1613     return false;
1614   S.Stk.push<Pointer>(Result);
1615   return true;
1616 }
1617 
1618 inline bool GetMemberPtrBasePop(InterpState &S, CodePtr OpPC, int32_t Off) {
1619   const auto &Ptr = S.Stk.pop<MemberPointer>();
1620   S.Stk.push<MemberPointer>(Ptr.atInstanceBase(Off));
1621   return true;
1622 }
1623 
1624 inline bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
1625   if (S.checkingPotentialConstantExpression())
1626     return false;
1627   const Pointer &This = S.Current->getThis();
1628   if (!CheckThis(S, OpPC, This))
1629     return false;
1630   S.Stk.push<Pointer>(This.atField(Off));
1631   return true;
1632 }
1633 
1634 inline bool FinishInitPop(InterpState &S, CodePtr OpPC) {
1635   const Pointer &Ptr = S.Stk.pop<Pointer>();
1636   if (Ptr.canBeInitialized()) {
1637     Ptr.initialize();
1638     Ptr.activate();
1639   }
1640   return true;
1641 }
1642 
1643 inline bool FinishInit(InterpState &S, CodePtr OpPC) {
1644   const Pointer &Ptr = S.Stk.peek<Pointer>();
1645   if (Ptr.canBeInitialized()) {
1646     Ptr.initialize();
1647     Ptr.activate();
1648   }
1649   return true;
1650 }
1651 
1652 inline bool Dump(InterpState &S, CodePtr OpPC) {
1653   S.Stk.dump();
1654   return true;
1655 }
1656 
1657 inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl,
1658                            const Pointer &Ptr) {
1659   Pointer Base = Ptr;
1660   while (Base.isBaseClass())
1661     Base = Base.getBase();
1662 
1663   const Record::Base *VirtBase = Base.getRecord()->getVirtualBase(Decl);
1664   S.Stk.push<Pointer>(Base.atField(VirtBase->Offset));
1665   return true;
1666 }
1667 
1668 inline bool GetPtrVirtBasePop(InterpState &S, CodePtr OpPC,
1669                               const RecordDecl *D) {
1670   assert(D);
1671   const Pointer &Ptr = S.Stk.pop<Pointer>();
1672   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
1673     return false;
1674   return VirtBaseHelper(S, OpPC, D, Ptr);
1675 }
1676 
1677 inline bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC,
1678                                const RecordDecl *D) {
1679   assert(D);
1680   if (S.checkingPotentialConstantExpression())
1681     return false;
1682   const Pointer &This = S.Current->getThis();
1683   if (!CheckThis(S, OpPC, This))
1684     return false;
1685   return VirtBaseHelper(S, OpPC, D, S.Current->getThis());
1686 }
1687 
1688 //===----------------------------------------------------------------------===//
1689 // Load, Store, Init
1690 //===----------------------------------------------------------------------===//
1691 
1692 template <PrimType Name, class T = typename PrimConv<Name>::T>
1693 bool Load(InterpState &S, CodePtr OpPC) {
1694   const Pointer &Ptr = S.Stk.peek<Pointer>();
1695   if (!CheckLoad(S, OpPC, Ptr))
1696     return false;
1697   if (!Ptr.isBlockPointer())
1698     return false;
1699   S.Stk.push<T>(Ptr.deref<T>());
1700   return true;
1701 }
1702 
1703 template <PrimType Name, class T = typename PrimConv<Name>::T>
1704 bool LoadPop(InterpState &S, CodePtr OpPC) {
1705   const Pointer &Ptr = S.Stk.pop<Pointer>();
1706   if (!CheckLoad(S, OpPC, Ptr))
1707     return false;
1708   if (!Ptr.isBlockPointer())
1709     return false;
1710   S.Stk.push<T>(Ptr.deref<T>());
1711   return true;
1712 }
1713 
1714 template <PrimType Name, class T = typename PrimConv<Name>::T>
1715 bool Store(InterpState &S, CodePtr OpPC) {
1716   const T &Value = S.Stk.pop<T>();
1717   const Pointer &Ptr = S.Stk.peek<Pointer>();
1718   if (!CheckStore(S, OpPC, Ptr))
1719     return false;
1720   if (Ptr.canBeInitialized()) {
1721     Ptr.initialize();
1722     Ptr.activate();
1723   }
1724   Ptr.deref<T>() = Value;
1725   return true;
1726 }
1727 
1728 template <PrimType Name, class T = typename PrimConv<Name>::T>
1729 bool StorePop(InterpState &S, CodePtr OpPC) {
1730   const T &Value = S.Stk.pop<T>();
1731   const Pointer &Ptr = S.Stk.pop<Pointer>();
1732   if (!CheckStore(S, OpPC, Ptr))
1733     return false;
1734   if (Ptr.canBeInitialized()) {
1735     Ptr.initialize();
1736     Ptr.activate();
1737   }
1738   Ptr.deref<T>() = Value;
1739   return true;
1740 }
1741 
1742 template <PrimType Name, class T = typename PrimConv<Name>::T>
1743 bool StoreBitField(InterpState &S, CodePtr OpPC) {
1744   const T &Value = S.Stk.pop<T>();
1745   const Pointer &Ptr = S.Stk.peek<Pointer>();
1746   if (!CheckStore(S, OpPC, Ptr))
1747     return false;
1748   if (Ptr.canBeInitialized())
1749     Ptr.initialize();
1750   if (const auto *FD = Ptr.getField())
1751     Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
1752   else
1753     Ptr.deref<T>() = Value;
1754   return true;
1755 }
1756 
1757 template <PrimType Name, class T = typename PrimConv<Name>::T>
1758 bool StoreBitFieldPop(InterpState &S, CodePtr OpPC) {
1759   const T &Value = S.Stk.pop<T>();
1760   const Pointer &Ptr = S.Stk.pop<Pointer>();
1761   if (!CheckStore(S, OpPC, Ptr))
1762     return false;
1763   if (Ptr.canBeInitialized())
1764     Ptr.initialize();
1765   if (const auto *FD = Ptr.getField())
1766     Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
1767   else
1768     Ptr.deref<T>() = Value;
1769   return true;
1770 }
1771 
1772 template <PrimType Name, class T = typename PrimConv<Name>::T>
1773 bool Init(InterpState &S, CodePtr OpPC) {
1774   const T &Value = S.Stk.pop<T>();
1775   const Pointer &Ptr = S.Stk.peek<Pointer>();
1776   if (!CheckInit(S, OpPC, Ptr)) {
1777     assert(false);
1778     return false;
1779   }
1780   Ptr.activate();
1781   Ptr.initialize();
1782   new (&Ptr.deref<T>()) T(Value);
1783   return true;
1784 }
1785 
1786 template <PrimType Name, class T = typename PrimConv<Name>::T>
1787 bool InitPop(InterpState &S, CodePtr OpPC) {
1788   const T &Value = S.Stk.pop<T>();
1789   const Pointer &Ptr = S.Stk.pop<Pointer>();
1790   if (!CheckInit(S, OpPC, Ptr))
1791     return false;
1792   Ptr.activate();
1793   Ptr.initialize();
1794   new (&Ptr.deref<T>()) T(Value);
1795   return true;
1796 }
1797 
1798 /// 1) Pops the value from the stack
1799 /// 2) Peeks a pointer and gets its index \Idx
1800 /// 3) Sets the value on the pointer, leaving the pointer on the stack.
1801 template <PrimType Name, class T = typename PrimConv<Name>::T>
1802 bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx) {
1803   const T &Value = S.Stk.pop<T>();
1804   const Pointer &Ptr = S.Stk.peek<Pointer>();
1805 
1806   if (Ptr.isUnknownSizeArray())
1807     return false;
1808 
1809   // In the unlikely event that we're initializing the first item of
1810   // a non-array, skip the atIndex().
1811   if (Idx == 0 && !Ptr.getFieldDesc()->isArray()) {
1812     Ptr.initialize();
1813     new (&Ptr.deref<T>()) T(Value);
1814     return true;
1815   }
1816 
1817   const Pointer &ElemPtr = Ptr.atIndex(Idx);
1818   if (!CheckInit(S, OpPC, ElemPtr))
1819     return false;
1820   ElemPtr.initialize();
1821   new (&ElemPtr.deref<T>()) T(Value);
1822   return true;
1823 }
1824 
1825 /// The same as InitElem, but pops the pointer as well.
1826 template <PrimType Name, class T = typename PrimConv<Name>::T>
1827 bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) {
1828   const T &Value = S.Stk.pop<T>();
1829   const Pointer &Ptr = S.Stk.pop<Pointer>();
1830   if (Ptr.isUnknownSizeArray())
1831     return false;
1832 
1833   // In the unlikely event that we're initializing the first item of
1834   // a non-array, skip the atIndex().
1835   if (Idx == 0 && !Ptr.getFieldDesc()->isArray()) {
1836     Ptr.initialize();
1837     new (&Ptr.deref<T>()) T(Value);
1838     return true;
1839   }
1840 
1841   const Pointer &ElemPtr = Ptr.atIndex(Idx);
1842   if (!CheckInit(S, OpPC, ElemPtr))
1843     return false;
1844   ElemPtr.initialize();
1845   new (&ElemPtr.deref<T>()) T(Value);
1846   return true;
1847 }
1848 
1849 inline bool Memcpy(InterpState &S, CodePtr OpPC) {
1850   const Pointer &Src = S.Stk.pop<Pointer>();
1851   Pointer &Dest = S.Stk.peek<Pointer>();
1852 
1853   if (!CheckLoad(S, OpPC, Src))
1854     return false;
1855 
1856   return DoMemcpy(S, OpPC, Src, Dest);
1857 }
1858 
1859 inline bool ToMemberPtr(InterpState &S, CodePtr OpPC) {
1860   const auto &Member = S.Stk.pop<MemberPointer>();
1861   const auto &Base = S.Stk.pop<Pointer>();
1862 
1863   S.Stk.push<MemberPointer>(Member.takeInstance(Base));
1864   return true;
1865 }
1866 
1867 inline bool CastMemberPtrPtr(InterpState &S, CodePtr OpPC) {
1868   const auto &MP = S.Stk.pop<MemberPointer>();
1869 
1870   if (std::optional<Pointer> Ptr = MP.toPointer(S.Ctx)) {
1871     S.Stk.push<Pointer>(*Ptr);
1872     return true;
1873   }
1874   return false;
1875 }
1876 
1877 //===----------------------------------------------------------------------===//
1878 // AddOffset, SubOffset
1879 //===----------------------------------------------------------------------===//
1880 
1881 template <class T, ArithOp Op>
1882 bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
1883                   const Pointer &Ptr, bool IsPointerArith = false) {
1884   // A zero offset does not change the pointer.
1885   if (Offset.isZero()) {
1886     S.Stk.push<Pointer>(Ptr);
1887     return true;
1888   }
1889 
1890   if (IsPointerArith && !CheckNull(S, OpPC, Ptr, CSK_ArrayIndex)) {
1891     // The CheckNull will have emitted a note already, but we only
1892     // abort in C++, since this is fine in C.
1893     if (S.getLangOpts().CPlusPlus)
1894       return false;
1895   }
1896 
1897   // Arrays of unknown bounds cannot have pointers into them.
1898   if (!CheckArray(S, OpPC, Ptr))
1899     return false;
1900 
1901   // This is much simpler for integral pointers, so handle them first.
1902   if (Ptr.isIntegralPointer()) {
1903     uint64_t V = Ptr.getIntegerRepresentation();
1904     uint64_t O = static_cast<uint64_t>(Offset) * Ptr.elemSize();
1905     if constexpr (Op == ArithOp::Add)
1906       S.Stk.push<Pointer>(V + O, Ptr.asIntPointer().Desc);
1907     else
1908       S.Stk.push<Pointer>(V - O, Ptr.asIntPointer().Desc);
1909     return true;
1910   } else if (Ptr.isFunctionPointer()) {
1911     uint64_t O = static_cast<uint64_t>(Offset);
1912     uint64_t N;
1913     if constexpr (Op == ArithOp::Add)
1914       N = Ptr.getByteOffset() + O;
1915     else
1916       N = Ptr.getByteOffset() - O;
1917 
1918     if (N > 1)
1919       S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
1920           << N << /*non-array*/ true << 0;
1921     S.Stk.push<Pointer>(Ptr.asFunctionPointer().getFunction(), N);
1922     return true;
1923   }
1924 
1925   assert(Ptr.isBlockPointer());
1926 
1927   uint64_t MaxIndex = static_cast<uint64_t>(Ptr.getNumElems());
1928   uint64_t Index;
1929   if (Ptr.isOnePastEnd())
1930     Index = MaxIndex;
1931   else
1932     Index = Ptr.getIndex();
1933 
1934   bool Invalid = false;
1935   // Helper to report an invalid offset, computed as APSInt.
1936   auto DiagInvalidOffset = [&]() -> void {
1937     const unsigned Bits = Offset.bitWidth();
1938     APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), /*IsUnsigend=*/false);
1939     APSInt APIndex(APInt(Bits + 2, Index, /*IsSigned=*/true),
1940                    /*IsUnsigned=*/false);
1941     APSInt NewIndex =
1942         (Op == ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
1943     S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
1944         << NewIndex << /*array*/ static_cast<int>(!Ptr.inArray()) << MaxIndex;
1945     Invalid = true;
1946   };
1947 
1948   if (Ptr.isBlockPointer()) {
1949     uint64_t IOffset = static_cast<uint64_t>(Offset);
1950     uint64_t MaxOffset = MaxIndex - Index;
1951 
1952     if constexpr (Op == ArithOp::Add) {
1953       // If the new offset would be negative, bail out.
1954       if (Offset.isNegative() && (Offset.isMin() || -IOffset > Index))
1955         DiagInvalidOffset();
1956 
1957       // If the new offset would be out of bounds, bail out.
1958       if (Offset.isPositive() && IOffset > MaxOffset)
1959         DiagInvalidOffset();
1960     } else {
1961       // If the new offset would be negative, bail out.
1962       if (Offset.isPositive() && Index < IOffset)
1963         DiagInvalidOffset();
1964 
1965       // If the new offset would be out of bounds, bail out.
1966       if (Offset.isNegative() && (Offset.isMin() || -IOffset > MaxOffset))
1967         DiagInvalidOffset();
1968     }
1969   }
1970 
1971   if (Invalid && S.getLangOpts().CPlusPlus)
1972     return false;
1973 
1974   // Offset is valid - compute it on unsigned.
1975   int64_t WideIndex = static_cast<int64_t>(Index);
1976   int64_t WideOffset = static_cast<int64_t>(Offset);
1977   int64_t Result;
1978   if constexpr (Op == ArithOp::Add)
1979     Result = WideIndex + WideOffset;
1980   else
1981     Result = WideIndex - WideOffset;
1982 
1983   // When the pointer is one-past-end, going back to index 0 is the only
1984   // useful thing we can do. Any other index has been diagnosed before and
1985   // we don't get here.
1986   if (Result == 0 && Ptr.isOnePastEnd()) {
1987     S.Stk.push<Pointer>(Ptr.asBlockPointer().Pointee,
1988                         Ptr.asBlockPointer().Base);
1989     return true;
1990   }
1991 
1992   S.Stk.push<Pointer>(Ptr.atIndex(static_cast<uint64_t>(Result)));
1993   return true;
1994 }
1995 
1996 template <PrimType Name, class T = typename PrimConv<Name>::T>
1997 bool AddOffset(InterpState &S, CodePtr OpPC) {
1998   const T &Offset = S.Stk.pop<T>();
1999   Pointer Ptr = S.Stk.pop<Pointer>();
2000   if (Ptr.isBlockPointer())
2001     Ptr = Ptr.expand();
2002   return OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr,
2003                                        /*IsPointerArith=*/true);
2004 }
2005 
2006 template <PrimType Name, class T = typename PrimConv<Name>::T>
2007 bool SubOffset(InterpState &S, CodePtr OpPC) {
2008   const T &Offset = S.Stk.pop<T>();
2009   const Pointer &Ptr = S.Stk.pop<Pointer>();
2010   return OffsetHelper<T, ArithOp::Sub>(S, OpPC, Offset, Ptr,
2011                                        /*IsPointerArith=*/true);
2012 }
2013 
2014 template <ArithOp Op>
2015 static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC,
2016                                    const Pointer &Ptr) {
2017   if (Ptr.isDummy())
2018     return false;
2019 
2020   using OneT = Integral<8, false>;
2021 
2022   const Pointer &P = Ptr.deref<Pointer>();
2023   if (!CheckNull(S, OpPC, P, CSK_ArrayIndex))
2024     return false;
2025 
2026   // Get the current value on the stack.
2027   S.Stk.push<Pointer>(P);
2028 
2029   // Now the current Ptr again and a constant 1.
2030   OneT One = OneT::from(1);
2031   if (!OffsetHelper<OneT, Op>(S, OpPC, One, P, /*IsPointerArith=*/true))
2032     return false;
2033 
2034   // Store the new value.
2035   Ptr.deref<Pointer>() = S.Stk.pop<Pointer>();
2036   return true;
2037 }
2038 
2039 static inline bool IncPtr(InterpState &S, CodePtr OpPC) {
2040   const Pointer &Ptr = S.Stk.pop<Pointer>();
2041 
2042   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
2043     return false;
2044 
2045   return IncDecPtrHelper<ArithOp::Add>(S, OpPC, Ptr);
2046 }
2047 
2048 static inline bool DecPtr(InterpState &S, CodePtr OpPC) {
2049   const Pointer &Ptr = S.Stk.pop<Pointer>();
2050 
2051   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
2052     return false;
2053 
2054   return IncDecPtrHelper<ArithOp::Sub>(S, OpPC, Ptr);
2055 }
2056 
2057 /// 1) Pops a Pointer from the stack.
2058 /// 2) Pops another Pointer from the stack.
2059 /// 3) Pushes the different of the indices of the two pointers on the stack.
2060 template <PrimType Name, class T = typename PrimConv<Name>::T>
2061 inline bool SubPtr(InterpState &S, CodePtr OpPC) {
2062   const Pointer &LHS = S.Stk.pop<Pointer>();
2063   const Pointer &RHS = S.Stk.pop<Pointer>();
2064 
2065   for (const Pointer &P : {LHS, RHS}) {
2066     if (P.isZeroSizeArray()) {
2067       QualType PtrT = P.getType();
2068       while (auto *AT = dyn_cast<ArrayType>(PtrT))
2069         PtrT = AT->getElementType();
2070 
2071       QualType ArrayTy = S.getASTContext().getConstantArrayType(
2072           PtrT, APInt::getZero(1), nullptr, ArraySizeModifier::Normal, 0);
2073       S.FFDiag(S.Current->getSource(OpPC),
2074                diag::note_constexpr_pointer_subtraction_zero_size)
2075           << ArrayTy;
2076 
2077       return false;
2078     }
2079   }
2080 
2081   if (RHS.isZero()) {
2082     S.Stk.push<T>(T::from(LHS.getIndex()));
2083     return true;
2084   }
2085 
2086   if (!Pointer::hasSameBase(LHS, RHS) && S.getLangOpts().CPlusPlus) {
2087     // TODO: Diagnose.
2088     return false;
2089   }
2090 
2091   if (LHS.isZero() && RHS.isZero()) {
2092     S.Stk.push<T>();
2093     return true;
2094   }
2095 
2096   T A = LHS.isBlockPointer()
2097             ? (LHS.isElementPastEnd() ? T::from(LHS.getNumElems())
2098                                       : T::from(LHS.getIndex()))
2099             : T::from(LHS.getIntegerRepresentation());
2100   T B = RHS.isBlockPointer()
2101             ? (RHS.isElementPastEnd() ? T::from(RHS.getNumElems())
2102                                       : T::from(RHS.getIndex()))
2103             : T::from(RHS.getIntegerRepresentation());
2104 
2105   return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, A.bitWidth(), A, B);
2106 }
2107 
2108 //===----------------------------------------------------------------------===//
2109 // Destroy
2110 //===----------------------------------------------------------------------===//
2111 
2112 inline bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I) {
2113   S.Current->destroy(I);
2114   return true;
2115 }
2116 
2117 inline bool InitScope(InterpState &S, CodePtr OpPC, uint32_t I) {
2118   S.Current->initScope(I);
2119   return true;
2120 }
2121 
2122 //===----------------------------------------------------------------------===//
2123 // Cast, CastFP
2124 //===----------------------------------------------------------------------===//
2125 
2126 template <PrimType TIn, PrimType TOut> bool Cast(InterpState &S, CodePtr OpPC) {
2127   using T = typename PrimConv<TIn>::T;
2128   using U = typename PrimConv<TOut>::T;
2129   S.Stk.push<U>(U::from(S.Stk.pop<T>()));
2130   return true;
2131 }
2132 
2133 /// 1) Pops a Floating from the stack.
2134 /// 2) Pushes a new floating on the stack that uses the given semantics.
2135 inline bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem,
2136                    llvm::RoundingMode RM) {
2137   Floating F = S.Stk.pop<Floating>();
2138   Floating Result = F.toSemantics(Sem, RM);
2139   S.Stk.push<Floating>(Result);
2140   return true;
2141 }
2142 
2143 inline bool CastFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS) {
2144   FixedPointSemantics TargetSemantics =
2145       FixedPointSemantics::getFromOpaqueInt(FPS);
2146   const auto &Source = S.Stk.pop<FixedPoint>();
2147 
2148   bool Overflow;
2149   FixedPoint Result = Source.toSemantics(TargetSemantics, &Overflow);
2150 
2151   if (Overflow && !handleFixedPointOverflow(S, OpPC, Result))
2152     return false;
2153 
2154   S.Stk.push<FixedPoint>(Result);
2155   return true;
2156 }
2157 
2158 /// Like Cast(), but we cast to an arbitrary-bitwidth integral, so we need
2159 /// to know what bitwidth the result should be.
2160 template <PrimType Name, class T = typename PrimConv<Name>::T>
2161 bool CastAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
2162   S.Stk.push<IntegralAP<false>>(
2163       IntegralAP<false>::from(S.Stk.pop<T>(), BitWidth));
2164   return true;
2165 }
2166 
2167 template <PrimType Name, class T = typename PrimConv<Name>::T>
2168 bool CastAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
2169   S.Stk.push<IntegralAP<true>>(
2170       IntegralAP<true>::from(S.Stk.pop<T>(), BitWidth));
2171   return true;
2172 }
2173 
2174 template <PrimType Name, class T = typename PrimConv<Name>::T>
2175 bool CastIntegralFloating(InterpState &S, CodePtr OpPC,
2176                           const llvm::fltSemantics *Sem, uint32_t FPOI) {
2177   const T &From = S.Stk.pop<T>();
2178   APSInt FromAP = From.toAPSInt();
2179   Floating Result;
2180 
2181   FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
2182   auto Status =
2183       Floating::fromIntegral(FromAP, *Sem, getRoundingMode(FPO), Result);
2184   S.Stk.push<Floating>(Result);
2185 
2186   return CheckFloatResult(S, OpPC, Result, Status, FPO);
2187 }
2188 
2189 template <PrimType Name, class T = typename PrimConv<Name>::T>
2190 bool CastFloatingIntegral(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
2191   const Floating &F = S.Stk.pop<Floating>();
2192 
2193   if constexpr (std::is_same_v<T, Boolean>) {
2194     S.Stk.push<T>(T(F.isNonZero()));
2195     return true;
2196   } else {
2197     APSInt Result(std::max(8u, T::bitWidth()),
2198                   /*IsUnsigned=*/!T::isSigned());
2199     auto Status = F.convertToInteger(Result);
2200 
2201     // Float-to-Integral overflow check.
2202     if ((Status & APFloat::opStatus::opInvalidOp)) {
2203       const Expr *E = S.Current->getExpr(OpPC);
2204       QualType Type = E->getType();
2205 
2206       S.CCEDiag(E, diag::note_constexpr_overflow) << F.getAPFloat() << Type;
2207       if (S.noteUndefinedBehavior()) {
2208         S.Stk.push<T>(T(Result));
2209         return true;
2210       }
2211       return false;
2212     }
2213 
2214     FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
2215     S.Stk.push<T>(T(Result));
2216     return CheckFloatResult(S, OpPC, F, Status, FPO);
2217   }
2218 }
2219 
2220 static inline bool CastFloatingIntegralAP(InterpState &S, CodePtr OpPC,
2221                                           uint32_t BitWidth, uint32_t FPOI) {
2222   const Floating &F = S.Stk.pop<Floating>();
2223 
2224   APSInt Result(BitWidth, /*IsUnsigned=*/true);
2225   auto Status = F.convertToInteger(Result);
2226 
2227   // Float-to-Integral overflow check.
2228   if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite())
2229     return handleOverflow(S, OpPC, F.getAPFloat());
2230 
2231   FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
2232   S.Stk.push<IntegralAP<true>>(IntegralAP<true>(Result));
2233   return CheckFloatResult(S, OpPC, F, Status, FPO);
2234 }
2235 
2236 static inline bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC,
2237                                            uint32_t BitWidth, uint32_t FPOI) {
2238   const Floating &F = S.Stk.pop<Floating>();
2239 
2240   APSInt Result(BitWidth, /*IsUnsigned=*/false);
2241   auto Status = F.convertToInteger(Result);
2242 
2243   // Float-to-Integral overflow check.
2244   if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite())
2245     return handleOverflow(S, OpPC, F.getAPFloat());
2246 
2247   FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
2248   S.Stk.push<IntegralAP<true>>(IntegralAP<true>(Result));
2249   return CheckFloatResult(S, OpPC, F, Status, FPO);
2250 }
2251 
2252 bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC,
2253                                 const Pointer &Ptr, unsigned BitWidth);
2254 bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth);
2255 bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth);
2256 
2257 template <PrimType Name, class T = typename PrimConv<Name>::T>
2258 bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
2259   const Pointer &Ptr = S.Stk.pop<Pointer>();
2260 
2261   if (!CheckPointerToIntegralCast(S, OpPC, Ptr, T::bitWidth()))
2262     return false;
2263 
2264   S.Stk.push<T>(T::from(Ptr.getIntegerRepresentation()));
2265   return true;
2266 }
2267 
2268 template <PrimType Name, class T = typename PrimConv<Name>::T>
2269 static inline bool CastIntegralFixedPoint(InterpState &S, CodePtr OpPC,
2270                                           uint32_t FPS) {
2271   const T &Int = S.Stk.pop<T>();
2272 
2273   FixedPointSemantics Sem = FixedPointSemantics::getFromOpaqueInt(FPS);
2274 
2275   bool Overflow;
2276   FixedPoint Result = FixedPoint::from(Int.toAPSInt(), Sem, &Overflow);
2277 
2278   if (Overflow && !handleFixedPointOverflow(S, OpPC, Result))
2279     return false;
2280 
2281   S.Stk.push<FixedPoint>(Result);
2282   return true;
2283 }
2284 
2285 static inline bool CastFloatingFixedPoint(InterpState &S, CodePtr OpPC,
2286                                           uint32_t FPS) {
2287   const auto &Float = S.Stk.pop<Floating>();
2288 
2289   FixedPointSemantics Sem = FixedPointSemantics::getFromOpaqueInt(FPS);
2290 
2291   bool Overflow;
2292   FixedPoint Result = FixedPoint::from(Float.getAPFloat(), Sem, &Overflow);
2293 
2294   if (Overflow && !handleFixedPointOverflow(S, OpPC, Result))
2295     return false;
2296 
2297   S.Stk.push<FixedPoint>(Result);
2298   return true;
2299 }
2300 
2301 static inline bool CastFixedPointFloating(InterpState &S, CodePtr OpPC,
2302                                           const llvm::fltSemantics *Sem) {
2303   const auto &Fixed = S.Stk.pop<FixedPoint>();
2304 
2305   S.Stk.push<Floating>(Fixed.toFloat(Sem));
2306   return true;
2307 }
2308 
2309 template <PrimType Name, class T = typename PrimConv<Name>::T>
2310 static inline bool CastFixedPointIntegral(InterpState &S, CodePtr OpPC) {
2311   const auto &Fixed = S.Stk.pop<FixedPoint>();
2312 
2313   bool Overflow;
2314   APSInt Int = Fixed.toInt(T::bitWidth(), T::isSigned(), &Overflow);
2315 
2316   if (Overflow && !handleOverflow(S, OpPC, Int))
2317     return false;
2318 
2319   S.Stk.push<T>(Int);
2320   return true;
2321 }
2322 
2323 static inline bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr) {
2324   const auto &Ptr = S.Stk.peek<Pointer>();
2325 
2326   if (SrcIsVoidPtr && S.getLangOpts().CPlusPlus) {
2327     bool HasValidResult = !Ptr.isZero();
2328 
2329     if (HasValidResult) {
2330       // FIXME: note_constexpr_invalid_void_star_cast
2331     } else if (!S.getLangOpts().CPlusPlus26) {
2332       const SourceInfo &E = S.Current->getSource(OpPC);
2333       S.CCEDiag(E, diag::note_constexpr_invalid_cast)
2334           << 3 << "'void *'" << S.Current->getRange(OpPC);
2335     }
2336   } else {
2337     const SourceInfo &E = S.Current->getSource(OpPC);
2338     S.CCEDiag(E, diag::note_constexpr_invalid_cast)
2339         << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
2340   }
2341 
2342   return true;
2343 }
2344 
2345 //===----------------------------------------------------------------------===//
2346 // Zero, Nullptr
2347 //===----------------------------------------------------------------------===//
2348 
2349 template <PrimType Name, class T = typename PrimConv<Name>::T>
2350 bool Zero(InterpState &S, CodePtr OpPC) {
2351   S.Stk.push<T>(T::zero());
2352   return true;
2353 }
2354 
2355 static inline bool ZeroIntAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
2356   S.Stk.push<IntegralAP<false>>(IntegralAP<false>::zero(BitWidth));
2357   return true;
2358 }
2359 
2360 static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
2361   S.Stk.push<IntegralAP<true>>(IntegralAP<true>::zero(BitWidth));
2362   return true;
2363 }
2364 
2365 template <PrimType Name, class T = typename PrimConv<Name>::T>
2366 inline bool Null(InterpState &S, CodePtr OpPC, uint64_t Value,
2367                  const Descriptor *Desc) {
2368   // FIXME(perf): This is a somewhat often-used function and the value of a
2369   // null pointer is almost always 0.
2370   S.Stk.push<T>(Value, Desc);
2371   return true;
2372 }
2373 
2374 template <PrimType Name, class T = typename PrimConv<Name>::T>
2375 inline bool IsNonNull(InterpState &S, CodePtr OpPC) {
2376   const auto &P = S.Stk.pop<T>();
2377   if (P.isWeak())
2378     return false;
2379   S.Stk.push<Boolean>(Boolean::from(!P.isZero()));
2380   return true;
2381 }
2382 
2383 //===----------------------------------------------------------------------===//
2384 // This, ImplicitThis
2385 //===----------------------------------------------------------------------===//
2386 
2387 inline bool This(InterpState &S, CodePtr OpPC) {
2388   // Cannot read 'this' in this mode.
2389   if (S.checkingPotentialConstantExpression()) {
2390     return false;
2391   }
2392 
2393   const Pointer &This = S.Current->getThis();
2394   if (!CheckThis(S, OpPC, This))
2395     return false;
2396 
2397   // Ensure the This pointer has been cast to the correct base.
2398   if (!This.isDummy()) {
2399     assert(isa<CXXMethodDecl>(S.Current->getFunction()->getDecl()));
2400     assert(This.getRecord());
2401     assert(
2402         This.getRecord()->getDecl() ==
2403         cast<CXXMethodDecl>(S.Current->getFunction()->getDecl())->getParent());
2404   }
2405 
2406   S.Stk.push<Pointer>(This);
2407   return true;
2408 }
2409 
2410 inline bool RVOPtr(InterpState &S, CodePtr OpPC) {
2411   assert(S.Current->getFunction()->hasRVO());
2412   if (S.checkingPotentialConstantExpression())
2413     return false;
2414   S.Stk.push<Pointer>(S.Current->getRVOPtr());
2415   return true;
2416 }
2417 
2418 //===----------------------------------------------------------------------===//
2419 // Shr, Shl
2420 //===----------------------------------------------------------------------===//
2421 
2422 template <class LT, class RT, ShiftDir Dir>
2423 inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) {
2424   const unsigned Bits = LHS.bitWidth();
2425 
2426   // OpenCL 6.3j: shift values are effectively % word size of LHS.
2427   if (S.getLangOpts().OpenCL)
2428     RT::bitAnd(RHS, RT::from(LHS.bitWidth() - 1, RHS.bitWidth()),
2429                RHS.bitWidth(), &RHS);
2430 
2431   if (RHS.isNegative()) {
2432     // During constant-folding, a negative shift is an opposite shift. Such a
2433     // shift is not a constant expression.
2434     const SourceInfo &Loc = S.Current->getSource(OpPC);
2435     S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
2436     if (!S.noteUndefinedBehavior())
2437       return false;
2438     RHS = -RHS;
2439     return DoShift<LT, RT,
2440                    Dir == ShiftDir::Left ? ShiftDir::Right : ShiftDir::Left>(
2441         S, OpPC, LHS, RHS);
2442   }
2443 
2444   if (!CheckShift<Dir>(S, OpPC, LHS, RHS, Bits))
2445     return false;
2446 
2447   // Limit the shift amount to Bits - 1. If this happened,
2448   // it has already been diagnosed by CheckShift() above,
2449   // but we still need to handle it.
2450   // Note that we have to be extra careful here since we're doing the shift in
2451   // any case, but we need to adjust the shift amount or the way we do the shift
2452   // for the potential error cases.
2453   typename LT::AsUnsigned R;
2454   unsigned MaxShiftAmount = LHS.bitWidth() - 1;
2455   if constexpr (Dir == ShiftDir::Left) {
2456     if (Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
2457         ComparisonCategoryResult::Greater) {
2458       if (LHS.isNegative())
2459         R = LT::AsUnsigned::zero(LHS.bitWidth());
2460       else {
2461         RHS = RT::from(LHS.countLeadingZeros(), RHS.bitWidth());
2462         LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
2463                                   LT::AsUnsigned::from(RHS, Bits), Bits, &R);
2464       }
2465     } else if (LHS.isNegative()) {
2466       if (LHS.isMin()) {
2467         R = LT::AsUnsigned::zero(LHS.bitWidth());
2468       } else {
2469         // If the LHS is negative, perform the cast and invert the result.
2470         typename LT::AsUnsigned LHSU = LT::AsUnsigned::from(-LHS);
2471         LT::AsUnsigned::shiftLeft(LHSU, LT::AsUnsigned::from(RHS, Bits), Bits,
2472                                   &R);
2473         R = -R;
2474       }
2475     } else {
2476       // The good case, a simple left shift.
2477       LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
2478                                 LT::AsUnsigned::from(RHS, Bits), Bits, &R);
2479     }
2480   } else {
2481     // Right shift.
2482     if (Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
2483         ComparisonCategoryResult::Greater) {
2484       R = LT::AsUnsigned::from(-1);
2485     } else {
2486       // Do the shift on potentially signed LT, then convert to unsigned type.
2487       LT A;
2488       LT::shiftRight(LHS, LT::from(RHS, Bits), Bits, &A);
2489       R = LT::AsUnsigned::from(A);
2490     }
2491   }
2492 
2493   S.Stk.push<LT>(LT::from(R));
2494   return true;
2495 }
2496 
2497 template <PrimType NameL, PrimType NameR>
2498 inline bool Shr(InterpState &S, CodePtr OpPC) {
2499   using LT = typename PrimConv<NameL>::T;
2500   using RT = typename PrimConv<NameR>::T;
2501   auto RHS = S.Stk.pop<RT>();
2502   auto LHS = S.Stk.pop<LT>();
2503 
2504   return DoShift<LT, RT, ShiftDir::Right>(S, OpPC, LHS, RHS);
2505 }
2506 
2507 template <PrimType NameL, PrimType NameR>
2508 inline bool Shl(InterpState &S, CodePtr OpPC) {
2509   using LT = typename PrimConv<NameL>::T;
2510   using RT = typename PrimConv<NameR>::T;
2511   auto RHS = S.Stk.pop<RT>();
2512   auto LHS = S.Stk.pop<LT>();
2513 
2514   return DoShift<LT, RT, ShiftDir::Left>(S, OpPC, LHS, RHS);
2515 }
2516 
2517 static inline bool ShiftFixedPoint(InterpState &S, CodePtr OpPC, bool Left) {
2518   const auto &RHS = S.Stk.pop<FixedPoint>();
2519   const auto &LHS = S.Stk.pop<FixedPoint>();
2520   llvm::FixedPointSemantics LHSSema = LHS.getSemantics();
2521 
2522   unsigned ShiftBitWidth =
2523       LHSSema.getWidth() - (unsigned)LHSSema.hasUnsignedPadding() - 1;
2524 
2525   // Embedded-C 4.1.6.2.2:
2526   //   The right operand must be nonnegative and less than the total number
2527   //   of (nonpadding) bits of the fixed-point operand ...
2528   if (RHS.isNegative()) {
2529     S.CCEDiag(S.Current->getLocation(OpPC), diag::note_constexpr_negative_shift)
2530         << RHS.toAPSInt();
2531   } else if (static_cast<unsigned>(RHS.toAPSInt().getLimitedValue(
2532                  ShiftBitWidth)) != RHS.toAPSInt()) {
2533     const Expr *E = S.Current->getExpr(OpPC);
2534     S.CCEDiag(E, diag::note_constexpr_large_shift)
2535         << RHS.toAPSInt() << E->getType() << ShiftBitWidth;
2536   }
2537 
2538   FixedPoint Result;
2539   if (Left) {
2540     if (FixedPoint::shiftLeft(LHS, RHS, ShiftBitWidth, &Result) &&
2541         !handleFixedPointOverflow(S, OpPC, Result))
2542       return false;
2543   } else {
2544     if (FixedPoint::shiftRight(LHS, RHS, ShiftBitWidth, &Result) &&
2545         !handleFixedPointOverflow(S, OpPC, Result))
2546       return false;
2547   }
2548 
2549   S.Stk.push<FixedPoint>(Result);
2550   return true;
2551 }
2552 
2553 //===----------------------------------------------------------------------===//
2554 // NoRet
2555 //===----------------------------------------------------------------------===//
2556 
2557 inline bool NoRet(InterpState &S, CodePtr OpPC) {
2558   SourceLocation EndLoc = S.Current->getCallee()->getEndLoc();
2559   S.FFDiag(EndLoc, diag::note_constexpr_no_return);
2560   return false;
2561 }
2562 
2563 //===----------------------------------------------------------------------===//
2564 // NarrowPtr, ExpandPtr
2565 //===----------------------------------------------------------------------===//
2566 
2567 inline bool NarrowPtr(InterpState &S, CodePtr OpPC) {
2568   const Pointer &Ptr = S.Stk.pop<Pointer>();
2569   S.Stk.push<Pointer>(Ptr.narrow());
2570   return true;
2571 }
2572 
2573 inline bool ExpandPtr(InterpState &S, CodePtr OpPC) {
2574   const Pointer &Ptr = S.Stk.pop<Pointer>();
2575   S.Stk.push<Pointer>(Ptr.expand());
2576   return true;
2577 }
2578 
2579 // 1) Pops an integral value from the stack
2580 // 2) Peeks a pointer
2581 // 3) Pushes a new pointer that's a narrowed array
2582 //   element of the peeked pointer with the value
2583 //   from 1) added as offset.
2584 //
2585 // This leaves the original pointer on the stack and pushes a new one
2586 // with the offset applied and narrowed.
2587 template <PrimType Name, class T = typename PrimConv<Name>::T>
2588 inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
2589   const T &Offset = S.Stk.pop<T>();
2590   const Pointer &Ptr = S.Stk.peek<Pointer>();
2591 
2592   if (!Ptr.isZero() && !Offset.isZero()) {
2593     if (!CheckArray(S, OpPC, Ptr))
2594       return false;
2595   }
2596 
2597   if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
2598     return false;
2599 
2600   return NarrowPtr(S, OpPC);
2601 }
2602 
2603 template <PrimType Name, class T = typename PrimConv<Name>::T>
2604 inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
2605   const T &Offset = S.Stk.pop<T>();
2606   const Pointer &Ptr = S.Stk.pop<Pointer>();
2607 
2608   if (!Ptr.isZero() && !Offset.isZero()) {
2609     if (!CheckArray(S, OpPC, Ptr))
2610       return false;
2611   }
2612 
2613   if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
2614     return false;
2615 
2616   return NarrowPtr(S, OpPC);
2617 }
2618 
2619 template <PrimType Name, class T = typename PrimConv<Name>::T>
2620 inline bool ArrayElem(InterpState &S, CodePtr OpPC, uint32_t Index) {
2621   const Pointer &Ptr = S.Stk.peek<Pointer>();
2622 
2623   if (!CheckLoad(S, OpPC, Ptr))
2624     return false;
2625 
2626   assert(Ptr.atIndex(Index).getFieldDesc()->getPrimType() == Name);
2627   S.Stk.push<T>(Ptr.atIndex(Index).deref<T>());
2628   return true;
2629 }
2630 
2631 template <PrimType Name, class T = typename PrimConv<Name>::T>
2632 inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) {
2633   const Pointer &Ptr = S.Stk.pop<Pointer>();
2634 
2635   if (!CheckLoad(S, OpPC, Ptr))
2636     return false;
2637 
2638   assert(Ptr.atIndex(Index).getFieldDesc()->getPrimType() == Name);
2639   S.Stk.push<T>(Ptr.atIndex(Index).deref<T>());
2640   return true;
2641 }
2642 
2643 template <PrimType Name, class T = typename PrimConv<Name>::T>
2644 inline bool CopyArray(InterpState &S, CodePtr OpPC, uint32_t SrcIndex,
2645                       uint32_t DestIndex, uint32_t Size) {
2646   const auto &SrcPtr = S.Stk.pop<Pointer>();
2647   const auto &DestPtr = S.Stk.peek<Pointer>();
2648 
2649   for (uint32_t I = 0; I != Size; ++I) {
2650     const Pointer &SP = SrcPtr.atIndex(SrcIndex + I);
2651 
2652     if (!CheckLoad(S, OpPC, SP))
2653       return false;
2654 
2655     const Pointer &DP = DestPtr.atIndex(DestIndex + I);
2656     DP.deref<T>() = SP.deref<T>();
2657     DP.initialize();
2658   }
2659   return true;
2660 }
2661 
2662 /// Just takes a pointer and checks if it's an incomplete
2663 /// array type.
2664 inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
2665   const Pointer &Ptr = S.Stk.pop<Pointer>();
2666 
2667   if (Ptr.isZero()) {
2668     S.Stk.push<Pointer>(Ptr);
2669     return true;
2670   }
2671 
2672   if (!CheckRange(S, OpPC, Ptr, CSK_ArrayToPointer))
2673     return false;
2674 
2675   if (Ptr.isRoot() || !Ptr.isUnknownSizeArray()) {
2676     S.Stk.push<Pointer>(Ptr.atIndex(0));
2677     return true;
2678   }
2679 
2680   const SourceInfo &E = S.Current->getSource(OpPC);
2681   S.FFDiag(E, diag::note_constexpr_unsupported_unsized_array);
2682 
2683   return false;
2684 }
2685 
2686 inline bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func) {
2687   assert(Func);
2688   S.Stk.push<FunctionPointer>(Func);
2689   return true;
2690 }
2691 
2692 template <PrimType Name, class T = typename PrimConv<Name>::T>
2693 inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
2694   const T &IntVal = S.Stk.pop<T>();
2695 
2696   if (Desc)
2697     S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast)
2698         << 2 << S.getLangOpts().CPlusPlus;
2699 
2700   S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Desc);
2701   return true;
2702 }
2703 
2704 inline bool GetMemberPtr(InterpState &S, CodePtr OpPC, const ValueDecl *D) {
2705   S.Stk.push<MemberPointer>(D);
2706   return true;
2707 }
2708 
2709 inline bool GetMemberPtrBase(InterpState &S, CodePtr OpPC) {
2710   const auto &MP = S.Stk.pop<MemberPointer>();
2711 
2712   S.Stk.push<Pointer>(MP.getBase());
2713   return true;
2714 }
2715 
2716 inline bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC) {
2717   const auto &MP = S.Stk.pop<MemberPointer>();
2718 
2719   const auto *FD = cast<FunctionDecl>(MP.getDecl());
2720   const auto *Func = S.getContext().getOrCreateFunction(FD);
2721 
2722   S.Stk.push<FunctionPointer>(Func);
2723   return true;
2724 }
2725 
2726 /// Just emit a diagnostic. The expression that caused emission of this
2727 /// op is not valid in a constant context.
2728 inline bool Invalid(InterpState &S, CodePtr OpPC) {
2729   const SourceLocation &Loc = S.Current->getLocation(OpPC);
2730   S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr)
2731       << S.Current->getRange(OpPC);
2732   return false;
2733 }
2734 
2735 inline bool Unsupported(InterpState &S, CodePtr OpPC) {
2736   const SourceLocation &Loc = S.Current->getLocation(OpPC);
2737   S.FFDiag(Loc, diag::note_constexpr_stmt_expr_unsupported)
2738       << S.Current->getRange(OpPC);
2739   return false;
2740 }
2741 
2742 /// Do nothing and just abort execution.
2743 inline bool Error(InterpState &S, CodePtr OpPC) { return false; }
2744 inline bool SideEffect(InterpState &S, CodePtr OpPC) {
2745   return S.noteSideEffect();
2746 }
2747 
2748 /// Same here, but only for casts.
2749 inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind,
2750                         bool Fatal) {
2751   const SourceLocation &Loc = S.Current->getLocation(OpPC);
2752 
2753   // FIXME: Support diagnosing other invalid cast kinds.
2754   if (Kind == CastKind::Reinterpret) {
2755     S.CCEDiag(Loc, diag::note_constexpr_invalid_cast)
2756         << static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
2757     return !Fatal;
2758   }
2759   return false;
2760 }
2761 
2762 inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR,
2763                            bool InitializerFailed) {
2764   assert(DR);
2765 
2766   if (InitializerFailed) {
2767     const SourceInfo &Loc = S.Current->getSource(OpPC);
2768     const auto *VD = cast<VarDecl>(DR->getDecl());
2769     S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
2770     S.Note(VD->getLocation(), diag::note_declared_at);
2771     return false;
2772   }
2773 
2774   return CheckDeclRef(S, OpPC, DR);
2775 }
2776 
2777 inline bool SizelessVectorElementSize(InterpState &S, CodePtr OpPC) {
2778   if (S.inConstantContext()) {
2779     const SourceRange &ArgRange = S.Current->getRange(OpPC);
2780     const Expr *E = S.Current->getExpr(OpPC);
2781     S.CCEDiag(E, diag::note_constexpr_non_const_vectorelements) << ArgRange;
2782   }
2783   return false;
2784 }
2785 
2786 inline bool Assume(InterpState &S, CodePtr OpPC) {
2787   const auto Val = S.Stk.pop<Boolean>();
2788 
2789   if (Val)
2790     return true;
2791 
2792   // Else, diagnose.
2793   const SourceLocation &Loc = S.Current->getLocation(OpPC);
2794   S.CCEDiag(Loc, diag::note_constexpr_assumption_failed);
2795   return false;
2796 }
2797 
2798 template <PrimType Name, class T = typename PrimConv<Name>::T>
2799 inline bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E) {
2800   llvm::SmallVector<int64_t> ArrayIndices;
2801   for (size_t I = 0; I != E->getNumExpressions(); ++I)
2802     ArrayIndices.emplace_back(S.Stk.pop<int64_t>());
2803 
2804   int64_t Result;
2805   if (!InterpretOffsetOf(S, OpPC, E, ArrayIndices, Result))
2806     return false;
2807 
2808   S.Stk.push<T>(T::from(Result));
2809 
2810   return true;
2811 }
2812 
2813 template <PrimType Name, class T = typename PrimConv<Name>::T>
2814 inline bool CheckNonNullArg(InterpState &S, CodePtr OpPC) {
2815   const T &Arg = S.Stk.peek<T>();
2816   if (!Arg.isZero())
2817     return true;
2818 
2819   const SourceLocation &Loc = S.Current->getLocation(OpPC);
2820   S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
2821 
2822   return false;
2823 }
2824 
2825 void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED,
2826                        const APSInt &Value);
2827 
2828 template <PrimType Name, class T = typename PrimConv<Name>::T>
2829 inline bool CheckEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED) {
2830   assert(ED);
2831   assert(!ED->isFixed());
2832   const APSInt Val = S.Stk.peek<T>().toAPSInt();
2833 
2834   if (S.inConstantContext())
2835     diagnoseEnumValue(S, OpPC, ED, Val);
2836   return true;
2837 }
2838 
2839 /// OldPtr -> Integer -> NewPtr.
2840 template <PrimType TIn, PrimType TOut>
2841 inline bool DecayPtr(InterpState &S, CodePtr OpPC) {
2842   static_assert(isPtrType(TIn) && isPtrType(TOut));
2843   using FromT = typename PrimConv<TIn>::T;
2844   using ToT = typename PrimConv<TOut>::T;
2845 
2846   const FromT &OldPtr = S.Stk.pop<FromT>();
2847 
2848   if constexpr (std::is_same_v<FromT, FunctionPointer> &&
2849                 std::is_same_v<ToT, Pointer>) {
2850     S.Stk.push<Pointer>(OldPtr.getFunction(), OldPtr.getOffset());
2851     return true;
2852   } else if constexpr (std::is_same_v<FromT, Pointer> &&
2853                        std::is_same_v<ToT, FunctionPointer>) {
2854     if (OldPtr.isFunctionPointer()) {
2855       S.Stk.push<FunctionPointer>(OldPtr.asFunctionPointer().getFunction(),
2856                                   OldPtr.getByteOffset());
2857       return true;
2858     }
2859   }
2860 
2861   S.Stk.push<ToT>(ToT(OldPtr.getIntegerRepresentation(), nullptr));
2862   return true;
2863 }
2864 
2865 inline bool CheckDecl(InterpState &S, CodePtr OpPC, const VarDecl *VD) {
2866   // An expression E is a core constant expression unless the evaluation of E
2867   // would evaluate one of the following: [C++23] - a control flow that passes
2868   // through a declaration of a variable with static or thread storage duration
2869   // unless that variable is usable in constant expressions.
2870   assert(VD->isLocalVarDecl() &&
2871          VD->isStaticLocal()); // Checked before emitting this.
2872 
2873   if (VD == S.EvaluatingDecl)
2874     return true;
2875 
2876   if (!VD->isUsableInConstantExpressions(S.getASTContext())) {
2877     S.CCEDiag(VD->getLocation(), diag::note_constexpr_static_local)
2878         << (VD->getTSCSpec() == TSCS_unspecified ? 0 : 1) << VD;
2879     return false;
2880   }
2881   return true;
2882 }
2883 
2884 inline bool Alloc(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
2885   assert(Desc);
2886 
2887   if (!CheckDynamicMemoryAllocation(S, OpPC))
2888     return false;
2889 
2890   DynamicAllocator &Allocator = S.getAllocator();
2891   Block *B = Allocator.allocate(Desc, S.Ctx.getEvalID(),
2892                                 DynamicAllocator::Form::NonArray);
2893   assert(B);
2894 
2895   S.Stk.push<Pointer>(B);
2896 
2897   return true;
2898 }
2899 
2900 template <PrimType Name, class SizeT = typename PrimConv<Name>::T>
2901 inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source,
2902                    bool IsNoThrow) {
2903   if (!CheckDynamicMemoryAllocation(S, OpPC))
2904     return false;
2905 
2906   SizeT NumElements = S.Stk.pop<SizeT>();
2907   if (!CheckArraySize(S, OpPC, &NumElements, primSize(T), IsNoThrow)) {
2908     if (!IsNoThrow)
2909       return false;
2910 
2911     // If this failed and is nothrow, just return a null ptr.
2912     S.Stk.push<Pointer>(0, nullptr);
2913     return true;
2914   }
2915 
2916   DynamicAllocator &Allocator = S.getAllocator();
2917   Block *B =
2918       Allocator.allocate(Source, T, static_cast<size_t>(NumElements),
2919                          S.Ctx.getEvalID(), DynamicAllocator::Form::Array);
2920   assert(B);
2921   S.Stk.push<Pointer>(B, sizeof(InlineDescriptor));
2922 
2923   return true;
2924 }
2925 
2926 template <PrimType Name, class SizeT = typename PrimConv<Name>::T>
2927 inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc,
2928                     bool IsNoThrow) {
2929   if (!CheckDynamicMemoryAllocation(S, OpPC))
2930     return false;
2931 
2932   SizeT NumElements = S.Stk.pop<SizeT>();
2933   if (!CheckArraySize(S, OpPC, &NumElements, ElementDesc->getSize(),
2934                       IsNoThrow)) {
2935     if (!IsNoThrow)
2936       return false;
2937 
2938     // If this failed and is nothrow, just return a null ptr.
2939     S.Stk.push<Pointer>(0, ElementDesc);
2940     return true;
2941   }
2942 
2943   DynamicAllocator &Allocator = S.getAllocator();
2944   Block *B =
2945       Allocator.allocate(ElementDesc, static_cast<size_t>(NumElements),
2946                          S.Ctx.getEvalID(), DynamicAllocator::Form::Array);
2947   assert(B);
2948 
2949   S.Stk.push<Pointer>(B, sizeof(InlineDescriptor));
2950 
2951   return true;
2952 }
2953 
2954 bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
2955           bool IsGlobalDelete);
2956 
2957 static inline bool IsConstantContext(InterpState &S, CodePtr OpPC) {
2958   S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
2959   return true;
2960 }
2961 
2962 static inline bool CheckAllocations(InterpState &S, CodePtr OpPC) {
2963   return S.maybeDiagnoseDanglingAllocations();
2964 }
2965 
2966 /// Check if the initializer and storage types of a placement-new expression
2967 /// match.
2968 bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
2969                           std::optional<uint64_t> ArraySize = std::nullopt);
2970 
2971 template <PrimType Name, class T = typename PrimConv<Name>::T>
2972 bool CheckNewTypeMismatchArray(InterpState &S, CodePtr OpPC, const Expr *E) {
2973   const auto &Size = S.Stk.pop<T>();
2974   return CheckNewTypeMismatch(S, OpPC, E, static_cast<uint64_t>(Size));
2975 }
2976 bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E);
2977 
2978 template <PrimType Name, class T = typename PrimConv<Name>::T>
2979 inline bool BitCastPrim(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte,
2980                         uint32_t ResultBitWidth,
2981                         const llvm::fltSemantics *Sem) {
2982   const Pointer &FromPtr = S.Stk.pop<Pointer>();
2983 
2984   if (!CheckLoad(S, OpPC, FromPtr))
2985     return false;
2986 
2987   if constexpr (std::is_same_v<T, Pointer>) {
2988     // The only pointer type we can validly bitcast to is nullptr_t.
2989     S.Stk.push<Pointer>();
2990     return true;
2991   } else {
2992 
2993     size_t BuffSize = ResultBitWidth / 8;
2994     llvm::SmallVector<std::byte> Buff(BuffSize);
2995     bool HasIndeterminateBits = false;
2996 
2997     Bits FullBitWidth(ResultBitWidth);
2998     Bits BitWidth = FullBitWidth;
2999 
3000     if constexpr (std::is_same_v<T, Floating>) {
3001       assert(Sem);
3002       BitWidth = Bits(llvm::APFloatBase::getSizeInBits(*Sem));
3003     }
3004 
3005     if (!DoBitCast(S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth,
3006                    HasIndeterminateBits))
3007       return false;
3008 
3009     if (!CheckBitCast(S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte))
3010       return false;
3011 
3012     if constexpr (std::is_same_v<T, Floating>) {
3013       assert(Sem);
3014       S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data(), *Sem));
3015     } else {
3016       assert(!Sem);
3017       S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
3018     }
3019     return true;
3020   }
3021 }
3022 
3023 inline bool BitCast(InterpState &S, CodePtr OpPC) {
3024   const Pointer &FromPtr = S.Stk.pop<Pointer>();
3025   Pointer &ToPtr = S.Stk.peek<Pointer>();
3026 
3027   if (!CheckLoad(S, OpPC, FromPtr))
3028     return false;
3029 
3030   if (!DoBitCastPtr(S, OpPC, FromPtr, ToPtr))
3031     return false;
3032 
3033   return true;
3034 }
3035 
3036 /// Typeid support.
3037 bool GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr,
3038                const Type *TypeInfoType);
3039 bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType);
3040 bool DiagTypeid(InterpState &S, CodePtr OpPC);
3041 
3042 //===----------------------------------------------------------------------===//
3043 // Read opcode arguments
3044 //===----------------------------------------------------------------------===//
3045 
3046 template <typename T> inline T ReadArg(InterpState &S, CodePtr &OpPC) {
3047   if constexpr (std::is_pointer<T>::value) {
3048     uint32_t ID = OpPC.read<uint32_t>();
3049     return reinterpret_cast<T>(S.P.getNativePointer(ID));
3050   } else {
3051     return OpPC.read<T>();
3052   }
3053 }
3054 
3055 template <> inline Floating ReadArg<Floating>(InterpState &S, CodePtr &OpPC) {
3056   Floating F = Floating::deserialize(*OpPC);
3057   OpPC += align(F.bytesToSerialize());
3058   return F;
3059 }
3060 
3061 template <>
3062 inline IntegralAP<false> ReadArg<IntegralAP<false>>(InterpState &S,
3063                                                     CodePtr &OpPC) {
3064   IntegralAP<false> I = IntegralAP<false>::deserialize(*OpPC);
3065   OpPC += align(I.bytesToSerialize());
3066   return I;
3067 }
3068 
3069 template <>
3070 inline IntegralAP<true> ReadArg<IntegralAP<true>>(InterpState &S,
3071                                                   CodePtr &OpPC) {
3072   IntegralAP<true> I = IntegralAP<true>::deserialize(*OpPC);
3073   OpPC += align(I.bytesToSerialize());
3074   return I;
3075 }
3076 
3077 template <>
3078 inline FixedPoint ReadArg<FixedPoint>(InterpState &S, CodePtr &OpPC) {
3079   FixedPoint FP = FixedPoint::deserialize(*OpPC);
3080   OpPC += align(FP.bytesToSerialize());
3081   return FP;
3082 }
3083 
3084 } // namespace interp
3085 } // namespace clang
3086 
3087 #endif
3088