xref: /freebsd/contrib/llvm-project/clang/lib/AST/Interp/Interp.h (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
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 "Boolean.h"
17 #include "Floating.h"
18 #include "Function.h"
19 #include "FunctionPointer.h"
20 #include "InterpFrame.h"
21 #include "InterpStack.h"
22 #include "InterpState.h"
23 #include "Opcode.h"
24 #include "PrimType.h"
25 #include "Program.h"
26 #include "State.h"
27 #include "clang/AST/ASTContext.h"
28 #include "clang/AST/ASTDiagnostic.h"
29 #include "clang/AST/CXXInheritance.h"
30 #include "clang/AST/Expr.h"
31 #include "llvm/ADT/APFloat.h"
32 #include "llvm/ADT/APSInt.h"
33 #include "llvm/Support/Endian.h"
34 #include <limits>
35 #include <type_traits>
36 
37 namespace clang {
38 namespace interp {
39 
40 using APSInt = llvm::APSInt;
41 
42 /// Convert a value to an APValue.
43 template <typename T> bool ReturnValue(const T &V, APValue &R) {
44   R = V.toAPValue();
45   return true;
46 }
47 
48 /// Checks if the variable has externally defined storage.
49 bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
50 
51 /// Checks if the array is offsetable.
52 bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
53 
54 /// Checks if a pointer is live and accessible.
55 bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
56                AccessKinds AK);
57 
58 /// Checks if a pointer is a dummy pointer.
59 bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
60 
61 /// Checks if a pointer is null.
62 bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
63                CheckSubobjectKind CSK);
64 
65 /// Checks if a pointer is in range.
66 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
67                 AccessKinds AK);
68 
69 /// Checks if a field from which a pointer is going to be derived is valid.
70 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
71                 CheckSubobjectKind CSK);
72 
73 /// Checks if Ptr is a one-past-the-end pointer.
74 bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
75                     CheckSubobjectKind CSK);
76 
77 /// Checks if a pointer points to const storage.
78 bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
79 
80 /// Checks if a pointer points to a mutable field.
81 bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
82 
83 /// Checks if a value can be loaded from a block.
84 bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
85 
86 bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
87                       AccessKinds AK);
88 
89 /// Checks if a value can be stored in a block.
90 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
91 
92 /// Checks if a method can be invoked on an object.
93 bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
94 
95 /// Checks if a value can be initialized.
96 bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
97 
98 /// Checks if a method can be called.
99 bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F);
100 
101 /// Checks if calling the currently active function would exceed
102 /// the allowed call depth.
103 bool CheckCallDepth(InterpState &S, CodePtr OpPC);
104 
105 /// Checks the 'this' pointer.
106 bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This);
107 
108 /// Checks if a method is pure virtual.
109 bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD);
110 
111 /// Checks that all fields are initialized after a constructor call.
112 bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This);
113 
114 /// Checks if reinterpret casts are legal in the current context.
115 bool CheckPotentialReinterpretCast(InterpState &S, CodePtr OpPC,
116                                    const Pointer &Ptr);
117 
118 /// Sets the given integral value to the pointer, which is of
119 /// a std::{weak,partial,strong}_ordering type.
120 bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,
121                                 const Pointer &Ptr, const APSInt &IntValue);
122 
123 /// Checks if the shift operation is legal.
124 template <typename LT, typename RT>
125 bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS,
126                 unsigned Bits) {
127   if (RHS.isNegative()) {
128     const SourceInfo &Loc = S.Current->getSource(OpPC);
129     S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
130     return false;
131   }
132 
133   // C++11 [expr.shift]p1: Shift width must be less than the bit width of
134   // the shifted type.
135   if (Bits > 1 && RHS >= RT::from(Bits, RHS.bitWidth())) {
136     const Expr *E = S.Current->getExpr(OpPC);
137     const APSInt Val = RHS.toAPSInt();
138     QualType Ty = E->getType();
139     S.CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty << Bits;
140     return false;
141   }
142 
143   if (LHS.isSigned() && !S.getLangOpts().CPlusPlus20) {
144     const Expr *E = S.Current->getExpr(OpPC);
145     // C++11 [expr.shift]p2: A signed left shift must have a non-negative
146     // operand, and must not overflow the corresponding unsigned type.
147     if (LHS.isNegative())
148       S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
149     else if (LHS.toUnsigned().countLeadingZeros() < static_cast<unsigned>(RHS))
150       S.CCEDiag(E, diag::note_constexpr_lshift_discards);
151   }
152 
153   // C++2a [expr.shift]p2: [P0907R4]:
154   //    E1 << E2 is the unique value congruent to
155   //    E1 x 2^E2 module 2^N.
156   return true;
157 }
158 
159 /// Checks if Div/Rem operation on LHS and RHS is valid.
160 template <typename T>
161 bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS) {
162   if (RHS.isZero()) {
163     const auto *Op = cast<BinaryOperator>(S.Current->getExpr(OpPC));
164     S.FFDiag(Op, diag::note_expr_divide_by_zero)
165         << Op->getRHS()->getSourceRange();
166     return false;
167   }
168 
169   if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) {
170     APSInt LHSInt = LHS.toAPSInt();
171     SmallString<32> Trunc;
172     (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10);
173     const SourceInfo &Loc = S.Current->getSource(OpPC);
174     const Expr *E = S.Current->getExpr(OpPC);
175     S.CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->getType();
176     return false;
177   }
178   return true;
179 }
180 
181 /// Checks if the result of a floating-point operation is valid
182 /// in the current context.
183 bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
184                       APFloat::opStatus Status);
185 
186 /// Checks why the given DeclRefExpr is invalid.
187 bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR);
188 
189 /// Interpreter entry point.
190 bool Interpret(InterpState &S, APValue &Result);
191 
192 /// Interpret a builtin function.
193 bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
194                       const CallExpr *Call);
195 
196 /// Interpret an offsetof operation.
197 bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
198                        llvm::ArrayRef<int64_t> ArrayIndices, int64_t &Result);
199 
200 enum class ArithOp { Add, Sub };
201 
202 //===----------------------------------------------------------------------===//
203 // Returning values
204 //===----------------------------------------------------------------------===//
205 
206 void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC);
207 
208 template <PrimType Name, class T = typename PrimConv<Name>::T>
209 bool Ret(InterpState &S, CodePtr &PC, APValue &Result) {
210   const T &Ret = S.Stk.pop<T>();
211 
212   // Make sure returned pointers are live. We might be trying to return a
213   // pointer or reference to a local variable.
214   // Just return false, since a diagnostic has already been emitted in Sema.
215   if constexpr (std::is_same_v<T, Pointer>) {
216     // FIXME: We could be calling isLive() here, but the emitted diagnostics
217     // seem a little weird, at least if the returned expression is of
218     // pointer type.
219     // Null pointers are considered live here.
220     if (!Ret.isZero() && !Ret.isLive())
221       return false;
222   }
223 
224   assert(S.Current);
225   assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
226   if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
227     cleanupAfterFunctionCall(S, PC);
228 
229   if (InterpFrame *Caller = S.Current->Caller) {
230     PC = S.Current->getRetPC();
231     delete S.Current;
232     S.Current = Caller;
233     S.Stk.push<T>(Ret);
234   } else {
235     delete S.Current;
236     S.Current = nullptr;
237     if (!ReturnValue<T>(Ret, Result))
238       return false;
239   }
240   return true;
241 }
242 
243 inline bool RetVoid(InterpState &S, CodePtr &PC, APValue &Result) {
244   assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
245 
246   if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
247     cleanupAfterFunctionCall(S, PC);
248 
249   if (InterpFrame *Caller = S.Current->Caller) {
250     PC = S.Current->getRetPC();
251     delete S.Current;
252     S.Current = Caller;
253   } else {
254     delete S.Current;
255     S.Current = nullptr;
256   }
257   return true;
258 }
259 
260 //===----------------------------------------------------------------------===//
261 // Add, Sub, Mul
262 //===----------------------------------------------------------------------===//
263 
264 template <typename T, bool (*OpFW)(T, T, unsigned, T *),
265           template <typename U> class OpAP>
266 bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS,
267                      const T &RHS) {
268   // Fast path - add the numbers with fixed width.
269   T Result;
270   if (!OpFW(LHS, RHS, Bits, &Result)) {
271     S.Stk.push<T>(Result);
272     return true;
273   }
274 
275   // If for some reason evaluation continues, use the truncated results.
276   S.Stk.push<T>(Result);
277 
278   // Slow path - compute the result using another bit of precision.
279   APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits));
280 
281   // Report undefined behaviour, stopping if required.
282   const Expr *E = S.Current->getExpr(OpPC);
283   QualType Type = E->getType();
284   if (S.checkingForUndefinedBehavior()) {
285     SmallString<32> Trunc;
286     Value.trunc(Result.bitWidth()).toString(Trunc, 10);
287     auto Loc = E->getExprLoc();
288     S.report(Loc, diag::warn_integer_constant_overflow)
289         << Trunc << Type << E->getSourceRange();
290     return true;
291   } else {
292     S.CCEDiag(E, diag::note_constexpr_overflow) << Value << Type;
293     if (!S.noteUndefinedBehavior()) {
294       S.Stk.pop<T>();
295       return false;
296     }
297     return true;
298   }
299 }
300 
301 template <PrimType Name, class T = typename PrimConv<Name>::T>
302 bool Add(InterpState &S, CodePtr OpPC) {
303   const T &RHS = S.Stk.pop<T>();
304   const T &LHS = S.Stk.pop<T>();
305   const unsigned Bits = RHS.bitWidth() + 1;
306   return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
307 }
308 
309 inline bool Addf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
310   const Floating &RHS = S.Stk.pop<Floating>();
311   const Floating &LHS = S.Stk.pop<Floating>();
312 
313   Floating Result;
314   auto Status = Floating::add(LHS, RHS, RM, &Result);
315   S.Stk.push<Floating>(Result);
316   return CheckFloatResult(S, OpPC, Result, Status);
317 }
318 
319 template <PrimType Name, class T = typename PrimConv<Name>::T>
320 bool Sub(InterpState &S, CodePtr OpPC) {
321   const T &RHS = S.Stk.pop<T>();
322   const T &LHS = S.Stk.pop<T>();
323   const unsigned Bits = RHS.bitWidth() + 1;
324   return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS);
325 }
326 
327 inline bool Subf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
328   const Floating &RHS = S.Stk.pop<Floating>();
329   const Floating &LHS = S.Stk.pop<Floating>();
330 
331   Floating Result;
332   auto Status = Floating::sub(LHS, RHS, RM, &Result);
333   S.Stk.push<Floating>(Result);
334   return CheckFloatResult(S, OpPC, Result, Status);
335 }
336 
337 template <PrimType Name, class T = typename PrimConv<Name>::T>
338 bool Mul(InterpState &S, CodePtr OpPC) {
339   const T &RHS = S.Stk.pop<T>();
340   const T &LHS = S.Stk.pop<T>();
341   const unsigned Bits = RHS.bitWidth() * 2;
342   return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS);
343 }
344 
345 inline bool Mulf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
346   const Floating &RHS = S.Stk.pop<Floating>();
347   const Floating &LHS = S.Stk.pop<Floating>();
348 
349   Floating Result;
350   auto Status = Floating::mul(LHS, RHS, RM, &Result);
351   S.Stk.push<Floating>(Result);
352   return CheckFloatResult(S, OpPC, Result, Status);
353 }
354 /// 1) Pops the RHS from the stack.
355 /// 2) Pops the LHS from the stack.
356 /// 3) Pushes 'LHS & RHS' on the stack
357 template <PrimType Name, class T = typename PrimConv<Name>::T>
358 bool BitAnd(InterpState &S, CodePtr OpPC) {
359   const T &RHS = S.Stk.pop<T>();
360   const T &LHS = S.Stk.pop<T>();
361 
362   unsigned Bits = RHS.bitWidth();
363   T Result;
364   if (!T::bitAnd(LHS, RHS, Bits, &Result)) {
365     S.Stk.push<T>(Result);
366     return true;
367   }
368   return false;
369 }
370 
371 /// 1) Pops the RHS from the stack.
372 /// 2) Pops the LHS from the stack.
373 /// 3) Pushes 'LHS | RHS' on the stack
374 template <PrimType Name, class T = typename PrimConv<Name>::T>
375 bool BitOr(InterpState &S, CodePtr OpPC) {
376   const T &RHS = S.Stk.pop<T>();
377   const T &LHS = S.Stk.pop<T>();
378 
379   unsigned Bits = RHS.bitWidth();
380   T Result;
381   if (!T::bitOr(LHS, RHS, Bits, &Result)) {
382     S.Stk.push<T>(Result);
383     return true;
384   }
385   return false;
386 }
387 
388 /// 1) Pops the RHS from the stack.
389 /// 2) Pops the LHS from the stack.
390 /// 3) Pushes 'LHS ^ RHS' on the stack
391 template <PrimType Name, class T = typename PrimConv<Name>::T>
392 bool BitXor(InterpState &S, CodePtr OpPC) {
393   const T &RHS = S.Stk.pop<T>();
394   const T &LHS = S.Stk.pop<T>();
395 
396   unsigned Bits = RHS.bitWidth();
397   T Result;
398   if (!T::bitXor(LHS, RHS, Bits, &Result)) {
399     S.Stk.push<T>(Result);
400     return true;
401   }
402   return false;
403 }
404 
405 /// 1) Pops the RHS from the stack.
406 /// 2) Pops the LHS from the stack.
407 /// 3) Pushes 'LHS % RHS' on the stack (the remainder of dividing LHS by RHS).
408 template <PrimType Name, class T = typename PrimConv<Name>::T>
409 bool Rem(InterpState &S, CodePtr OpPC) {
410   const T &RHS = S.Stk.pop<T>();
411   const T &LHS = S.Stk.pop<T>();
412 
413   if (!CheckDivRem(S, OpPC, LHS, RHS))
414     return false;
415 
416   const unsigned Bits = RHS.bitWidth() * 2;
417   T Result;
418   if (!T::rem(LHS, RHS, Bits, &Result)) {
419     S.Stk.push<T>(Result);
420     return true;
421   }
422   return false;
423 }
424 
425 /// 1) Pops the RHS from the stack.
426 /// 2) Pops the LHS from the stack.
427 /// 3) Pushes 'LHS / RHS' on the stack
428 template <PrimType Name, class T = typename PrimConv<Name>::T>
429 bool Div(InterpState &S, CodePtr OpPC) {
430   const T &RHS = S.Stk.pop<T>();
431   const T &LHS = S.Stk.pop<T>();
432 
433   if (!CheckDivRem(S, OpPC, LHS, RHS))
434     return false;
435 
436   const unsigned Bits = RHS.bitWidth() * 2;
437   T Result;
438   if (!T::div(LHS, RHS, Bits, &Result)) {
439     S.Stk.push<T>(Result);
440     return true;
441   }
442   return false;
443 }
444 
445 inline bool Divf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
446   const Floating &RHS = S.Stk.pop<Floating>();
447   const Floating &LHS = S.Stk.pop<Floating>();
448 
449   if (!CheckDivRem(S, OpPC, LHS, RHS))
450     return false;
451 
452   Floating Result;
453   auto Status = Floating::div(LHS, RHS, RM, &Result);
454   S.Stk.push<Floating>(Result);
455   return CheckFloatResult(S, OpPC, Result, Status);
456 }
457 
458 //===----------------------------------------------------------------------===//
459 // Inv
460 //===----------------------------------------------------------------------===//
461 
462 template <PrimType Name, class T = typename PrimConv<Name>::T>
463 bool Inv(InterpState &S, CodePtr OpPC) {
464   using BoolT = PrimConv<PT_Bool>::T;
465   const T &Val = S.Stk.pop<T>();
466   const unsigned Bits = Val.bitWidth();
467   Boolean R;
468   Boolean::inv(BoolT::from(Val, Bits), &R);
469 
470   S.Stk.push<BoolT>(R);
471   return true;
472 }
473 
474 //===----------------------------------------------------------------------===//
475 // Neg
476 //===----------------------------------------------------------------------===//
477 
478 template <PrimType Name, class T = typename PrimConv<Name>::T>
479 bool Neg(InterpState &S, CodePtr OpPC) {
480   const T &Value = S.Stk.pop<T>();
481   T Result;
482 
483   if (!T::neg(Value, &Result)) {
484     S.Stk.push<T>(Result);
485     return true;
486   }
487 
488   assert(isIntegralType(Name) &&
489          "don't expect other types to fail at constexpr negation");
490   S.Stk.push<T>(Result);
491 
492   APSInt NegatedValue = -Value.toAPSInt(Value.bitWidth() + 1);
493   const Expr *E = S.Current->getExpr(OpPC);
494   QualType Type = E->getType();
495 
496   if (S.checkingForUndefinedBehavior()) {
497     SmallString<32> Trunc;
498     NegatedValue.trunc(Result.bitWidth()).toString(Trunc, 10);
499     auto Loc = E->getExprLoc();
500     S.report(Loc, diag::warn_integer_constant_overflow)
501         << Trunc << Type << E->getSourceRange();
502     return true;
503   }
504 
505   S.CCEDiag(E, diag::note_constexpr_overflow) << NegatedValue << Type;
506   return S.noteUndefinedBehavior();
507 }
508 
509 enum class PushVal : bool {
510   No,
511   Yes,
512 };
513 enum class IncDecOp {
514   Inc,
515   Dec,
516 };
517 
518 template <typename T, IncDecOp Op, PushVal DoPush>
519 bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
520   const T &Value = Ptr.deref<T>();
521   T Result;
522 
523   if constexpr (DoPush == PushVal::Yes)
524     S.Stk.push<T>(Value);
525 
526   if constexpr (Op == IncDecOp::Inc) {
527     if (!T::increment(Value, &Result)) {
528       Ptr.deref<T>() = Result;
529       return true;
530     }
531   } else {
532     if (!T::decrement(Value, &Result)) {
533       Ptr.deref<T>() = Result;
534       return true;
535     }
536   }
537 
538   // Something went wrong with the previous operation. Compute the
539   // result with another bit of precision.
540   unsigned Bits = Value.bitWidth() + 1;
541   APSInt APResult;
542   if constexpr (Op == IncDecOp::Inc)
543     APResult = ++Value.toAPSInt(Bits);
544   else
545     APResult = --Value.toAPSInt(Bits);
546 
547   // Report undefined behaviour, stopping if required.
548   const Expr *E = S.Current->getExpr(OpPC);
549   QualType Type = E->getType();
550   if (S.checkingForUndefinedBehavior()) {
551     SmallString<32> Trunc;
552     APResult.trunc(Result.bitWidth()).toString(Trunc, 10);
553     auto Loc = E->getExprLoc();
554     S.report(Loc, diag::warn_integer_constant_overflow)
555         << Trunc << Type << E->getSourceRange();
556     return true;
557   }
558 
559   S.CCEDiag(E, diag::note_constexpr_overflow) << APResult << Type;
560   return S.noteUndefinedBehavior();
561 }
562 
563 /// 1) Pops a pointer from the stack
564 /// 2) Load the value from the pointer
565 /// 3) Writes the value increased by one back to the pointer
566 /// 4) Pushes the original (pre-inc) value on the stack.
567 template <PrimType Name, class T = typename PrimConv<Name>::T>
568 bool Inc(InterpState &S, CodePtr OpPC) {
569   const Pointer &Ptr = S.Stk.pop<Pointer>();
570 
571   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
572     return false;
573 
574   return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr);
575 }
576 
577 /// 1) Pops a pointer from the stack
578 /// 2) Load the value from the pointer
579 /// 3) Writes the value increased by one back to the pointer
580 template <PrimType Name, class T = typename PrimConv<Name>::T>
581 bool IncPop(InterpState &S, CodePtr OpPC) {
582   const Pointer &Ptr = S.Stk.pop<Pointer>();
583 
584   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
585     return false;
586 
587   return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr);
588 }
589 
590 /// 1) Pops a pointer from the stack
591 /// 2) Load the value from the pointer
592 /// 3) Writes the value decreased by one back to the pointer
593 /// 4) Pushes the original (pre-dec) value on the stack.
594 template <PrimType Name, class T = typename PrimConv<Name>::T>
595 bool Dec(InterpState &S, CodePtr OpPC) {
596   const Pointer &Ptr = S.Stk.pop<Pointer>();
597 
598   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
599     return false;
600 
601   return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr);
602 }
603 
604 /// 1) Pops a pointer from the stack
605 /// 2) Load the value from the pointer
606 /// 3) Writes the value decreased by one back to the pointer
607 template <PrimType Name, class T = typename PrimConv<Name>::T>
608 bool DecPop(InterpState &S, CodePtr OpPC) {
609   const Pointer &Ptr = S.Stk.pop<Pointer>();
610 
611   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
612     return false;
613 
614   return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr);
615 }
616 
617 template <IncDecOp Op, PushVal DoPush>
618 bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
619                        llvm::RoundingMode RM) {
620   Floating Value = Ptr.deref<Floating>();
621   Floating Result;
622 
623   if constexpr (DoPush == PushVal::Yes)
624     S.Stk.push<Floating>(Value);
625 
626   llvm::APFloat::opStatus Status;
627   if constexpr (Op == IncDecOp::Inc)
628     Status = Floating::increment(Value, RM, &Result);
629   else
630     Status = Floating::decrement(Value, RM, &Result);
631 
632   Ptr.deref<Floating>() = Result;
633 
634   return CheckFloatResult(S, OpPC, Result, Status);
635 }
636 
637 inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
638   const Pointer &Ptr = S.Stk.pop<Pointer>();
639 
640   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
641     return false;
642 
643   return IncDecFloatHelper<IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, RM);
644 }
645 
646 inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
647   const Pointer &Ptr = S.Stk.pop<Pointer>();
648 
649   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
650     return false;
651 
652   return IncDecFloatHelper<IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, RM);
653 }
654 
655 inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
656   const Pointer &Ptr = S.Stk.pop<Pointer>();
657 
658   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
659     return false;
660 
661   return IncDecFloatHelper<IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, RM);
662 }
663 
664 inline bool DecfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
665   const Pointer &Ptr = S.Stk.pop<Pointer>();
666 
667   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
668     return false;
669 
670   return IncDecFloatHelper<IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, RM);
671 }
672 
673 /// 1) Pops the value from the stack.
674 /// 2) Pushes the bitwise complemented value on the stack (~V).
675 template <PrimType Name, class T = typename PrimConv<Name>::T>
676 bool Comp(InterpState &S, CodePtr OpPC) {
677   const T &Val = S.Stk.pop<T>();
678   T Result;
679   if (!T::comp(Val, &Result)) {
680     S.Stk.push<T>(Result);
681     return true;
682   }
683 
684   return false;
685 }
686 
687 //===----------------------------------------------------------------------===//
688 // EQ, NE, GT, GE, LT, LE
689 //===----------------------------------------------------------------------===//
690 
691 using CompareFn = llvm::function_ref<bool(ComparisonCategoryResult)>;
692 
693 template <typename T>
694 bool CmpHelper(InterpState &S, CodePtr OpPC, CompareFn Fn) {
695   using BoolT = PrimConv<PT_Bool>::T;
696   const T &RHS = S.Stk.pop<T>();
697   const T &LHS = S.Stk.pop<T>();
698   S.Stk.push<BoolT>(BoolT::from(Fn(LHS.compare(RHS))));
699   return true;
700 }
701 
702 template <typename T>
703 bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn) {
704   return CmpHelper<T>(S, OpPC, Fn);
705 }
706 
707 /// Function pointers cannot be compared in an ordered way.
708 template <>
709 inline bool CmpHelper<FunctionPointer>(InterpState &S, CodePtr OpPC,
710                                        CompareFn Fn) {
711   const auto &RHS = S.Stk.pop<FunctionPointer>();
712   const auto &LHS = S.Stk.pop<FunctionPointer>();
713 
714   const SourceInfo &Loc = S.Current->getSource(OpPC);
715   S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
716       << LHS.toDiagnosticString(S.getCtx())
717       << RHS.toDiagnosticString(S.getCtx());
718   return false;
719 }
720 
721 template <>
722 inline bool CmpHelperEQ<FunctionPointer>(InterpState &S, CodePtr OpPC,
723                                          CompareFn Fn) {
724   const auto &RHS = S.Stk.pop<FunctionPointer>();
725   const auto &LHS = S.Stk.pop<FunctionPointer>();
726   S.Stk.push<Boolean>(Boolean::from(Fn(LHS.compare(RHS))));
727   return true;
728 }
729 
730 template <>
731 inline bool CmpHelper<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
732   using BoolT = PrimConv<PT_Bool>::T;
733   const Pointer &RHS = S.Stk.pop<Pointer>();
734   const Pointer &LHS = S.Stk.pop<Pointer>();
735 
736   if (!Pointer::hasSameBase(LHS, RHS)) {
737     const SourceInfo &Loc = S.Current->getSource(OpPC);
738     S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
739         << LHS.toDiagnosticString(S.getCtx())
740         << RHS.toDiagnosticString(S.getCtx());
741     return false;
742   } else {
743     unsigned VL = LHS.getByteOffset();
744     unsigned VR = RHS.getByteOffset();
745     S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
746     return true;
747   }
748 }
749 
750 template <>
751 inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
752   using BoolT = PrimConv<PT_Bool>::T;
753   const Pointer &RHS = S.Stk.pop<Pointer>();
754   const Pointer &LHS = S.Stk.pop<Pointer>();
755 
756   if (LHS.isZero() && RHS.isZero()) {
757     S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Equal)));
758     return true;
759   }
760 
761   if (!Pointer::hasSameBase(LHS, RHS)) {
762     S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Unordered)));
763     return true;
764   } else {
765     unsigned VL = LHS.getByteOffset();
766     unsigned VR = RHS.getByteOffset();
767 
768     // In our Pointer class, a pointer to an array and a pointer to the first
769     // element in the same array are NOT equal. They have the same Base value,
770     // but a different Offset. This is a pretty rare case, so we fix this here
771     // by comparing pointers to the first elements.
772     if (LHS.isArrayRoot())
773       VL = LHS.atIndex(0).getByteOffset();
774     if (RHS.isArrayRoot())
775       VR = RHS.atIndex(0).getByteOffset();
776 
777     S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
778     return true;
779   }
780 }
781 
782 template <PrimType Name, class T = typename PrimConv<Name>::T>
783 bool EQ(InterpState &S, CodePtr OpPC) {
784   return CmpHelperEQ<T>(S, OpPC, [](ComparisonCategoryResult R) {
785     return R == ComparisonCategoryResult::Equal;
786   });
787 }
788 
789 template <PrimType Name, class T = typename PrimConv<Name>::T>
790 bool CMP3(InterpState &S, CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo) {
791   const T &RHS = S.Stk.pop<T>();
792   const T &LHS = S.Stk.pop<T>();
793   const Pointer &P = S.Stk.peek<Pointer>();
794 
795   ComparisonCategoryResult CmpResult = LHS.compare(RHS);
796   if (CmpResult == ComparisonCategoryResult::Unordered) {
797     // This should only happen with pointers.
798     const SourceInfo &Loc = S.Current->getSource(OpPC);
799     S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
800         << LHS.toDiagnosticString(S.getCtx())
801         << RHS.toDiagnosticString(S.getCtx());
802     return false;
803   }
804 
805   assert(CmpInfo);
806   const auto *CmpValueInfo = CmpInfo->getValueInfo(CmpResult);
807   assert(CmpValueInfo);
808   assert(CmpValueInfo->hasValidIntValue());
809   APSInt IntValue = CmpValueInfo->getIntValue();
810   return SetThreeWayComparisonField(S, OpPC, P, IntValue);
811 }
812 
813 template <PrimType Name, class T = typename PrimConv<Name>::T>
814 bool NE(InterpState &S, CodePtr OpPC) {
815   return CmpHelperEQ<T>(S, OpPC, [](ComparisonCategoryResult R) {
816     return R != ComparisonCategoryResult::Equal;
817   });
818 }
819 
820 template <PrimType Name, class T = typename PrimConv<Name>::T>
821 bool LT(InterpState &S, CodePtr OpPC) {
822   return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
823     return R == ComparisonCategoryResult::Less;
824   });
825 }
826 
827 template <PrimType Name, class T = typename PrimConv<Name>::T>
828 bool LE(InterpState &S, CodePtr OpPC) {
829   return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
830     return R == ComparisonCategoryResult::Less ||
831            R == ComparisonCategoryResult::Equal;
832   });
833 }
834 
835 template <PrimType Name, class T = typename PrimConv<Name>::T>
836 bool GT(InterpState &S, CodePtr OpPC) {
837   return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
838     return R == ComparisonCategoryResult::Greater;
839   });
840 }
841 
842 template <PrimType Name, class T = typename PrimConv<Name>::T>
843 bool GE(InterpState &S, CodePtr OpPC) {
844   return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
845     return R == ComparisonCategoryResult::Greater ||
846            R == ComparisonCategoryResult::Equal;
847   });
848 }
849 
850 //===----------------------------------------------------------------------===//
851 // InRange
852 //===----------------------------------------------------------------------===//
853 
854 template <PrimType Name, class T = typename PrimConv<Name>::T>
855 bool InRange(InterpState &S, CodePtr OpPC) {
856   const T RHS = S.Stk.pop<T>();
857   const T LHS = S.Stk.pop<T>();
858   const T Value = S.Stk.pop<T>();
859 
860   S.Stk.push<bool>(LHS <= Value && Value <= RHS);
861   return true;
862 }
863 
864 //===----------------------------------------------------------------------===//
865 // Dup, Pop, Test
866 //===----------------------------------------------------------------------===//
867 
868 template <PrimType Name, class T = typename PrimConv<Name>::T>
869 bool Dup(InterpState &S, CodePtr OpPC) {
870   S.Stk.push<T>(S.Stk.peek<T>());
871   return true;
872 }
873 
874 template <PrimType Name, class T = typename PrimConv<Name>::T>
875 bool Pop(InterpState &S, CodePtr OpPC) {
876   S.Stk.pop<T>();
877   return true;
878 }
879 
880 //===----------------------------------------------------------------------===//
881 // Const
882 //===----------------------------------------------------------------------===//
883 
884 template <PrimType Name, class T = typename PrimConv<Name>::T>
885 bool Const(InterpState &S, CodePtr OpPC, const T &Arg) {
886   S.Stk.push<T>(Arg);
887   return true;
888 }
889 
890 //===----------------------------------------------------------------------===//
891 // Get/Set Local/Param/Global/This
892 //===----------------------------------------------------------------------===//
893 
894 template <PrimType Name, class T = typename PrimConv<Name>::T>
895 bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
896   const Pointer &Ptr = S.Current->getLocalPointer(I);
897   if (!CheckLoad(S, OpPC, Ptr))
898     return false;
899   S.Stk.push<T>(Ptr.deref<T>());
900   return true;
901 }
902 
903 /// 1) Pops the value from the stack.
904 /// 2) Writes the value to the local variable with the
905 ///    given offset.
906 template <PrimType Name, class T = typename PrimConv<Name>::T>
907 bool SetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
908   S.Current->setLocal<T>(I, S.Stk.pop<T>());
909   return true;
910 }
911 
912 template <PrimType Name, class T = typename PrimConv<Name>::T>
913 bool GetParam(InterpState &S, CodePtr OpPC, uint32_t I) {
914   if (S.checkingPotentialConstantExpression()) {
915     return false;
916   }
917   S.Stk.push<T>(S.Current->getParam<T>(I));
918   return true;
919 }
920 
921 template <PrimType Name, class T = typename PrimConv<Name>::T>
922 bool SetParam(InterpState &S, CodePtr OpPC, uint32_t I) {
923   S.Current->setParam<T>(I, S.Stk.pop<T>());
924   return true;
925 }
926 
927 /// 1) Peeks a pointer on the stack
928 /// 2) Pushes the value of the pointer's field on the stack
929 template <PrimType Name, class T = typename PrimConv<Name>::T>
930 bool GetField(InterpState &S, CodePtr OpPC, uint32_t I) {
931   const Pointer &Obj = S.Stk.peek<Pointer>();
932   if (!CheckNull(S, OpPC, Obj, CSK_Field))
933       return false;
934   if (!CheckRange(S, OpPC, Obj, CSK_Field))
935     return false;
936   const Pointer &Field = Obj.atField(I);
937   if (!CheckLoad(S, OpPC, Field))
938     return false;
939   S.Stk.push<T>(Field.deref<T>());
940   return true;
941 }
942 
943 template <PrimType Name, class T = typename PrimConv<Name>::T>
944 bool SetField(InterpState &S, CodePtr OpPC, uint32_t I) {
945   const T &Value = S.Stk.pop<T>();
946   const Pointer &Obj = S.Stk.peek<Pointer>();
947   if (!CheckNull(S, OpPC, Obj, CSK_Field))
948     return false;
949   if (!CheckRange(S, OpPC, Obj, CSK_Field))
950     return false;
951   const Pointer &Field = Obj.atField(I);
952   if (!CheckStore(S, OpPC, Field))
953     return false;
954   Field.initialize();
955   Field.deref<T>() = Value;
956   return true;
957 }
958 
959 /// 1) Pops a pointer from the stack
960 /// 2) Pushes the value of the pointer's field on the stack
961 template <PrimType Name, class T = typename PrimConv<Name>::T>
962 bool GetFieldPop(InterpState &S, CodePtr OpPC, uint32_t I) {
963   const Pointer &Obj = S.Stk.pop<Pointer>();
964   if (!CheckNull(S, OpPC, Obj, CSK_Field))
965     return false;
966   if (!CheckRange(S, OpPC, Obj, CSK_Field))
967     return false;
968   const Pointer &Field = Obj.atField(I);
969   if (!CheckLoad(S, OpPC, Field))
970     return false;
971   S.Stk.push<T>(Field.deref<T>());
972   return true;
973 }
974 
975 template <PrimType Name, class T = typename PrimConv<Name>::T>
976 bool GetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
977   if (S.checkingPotentialConstantExpression())
978     return false;
979   const Pointer &This = S.Current->getThis();
980   if (!CheckThis(S, OpPC, This))
981     return false;
982   const Pointer &Field = This.atField(I);
983   if (!CheckLoad(S, OpPC, Field))
984     return false;
985   S.Stk.push<T>(Field.deref<T>());
986   return true;
987 }
988 
989 template <PrimType Name, class T = typename PrimConv<Name>::T>
990 bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
991   if (S.checkingPotentialConstantExpression())
992     return false;
993   const T &Value = S.Stk.pop<T>();
994   const Pointer &This = S.Current->getThis();
995   if (!CheckThis(S, OpPC, This))
996     return false;
997   const Pointer &Field = This.atField(I);
998   if (!CheckStore(S, OpPC, Field))
999     return false;
1000   Field.deref<T>() = Value;
1001   return true;
1002 }
1003 
1004 template <PrimType Name, class T = typename PrimConv<Name>::T>
1005 bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
1006   const Block *B = S.P.getGlobal(I);
1007   if (B->isExtern())
1008     return false;
1009   S.Stk.push<T>(B->deref<T>());
1010   return true;
1011 }
1012 
1013 template <PrimType Name, class T = typename PrimConv<Name>::T>
1014 bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
1015   // TODO: emit warning.
1016   return false;
1017 }
1018 
1019 template <PrimType Name, class T = typename PrimConv<Name>::T>
1020 bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
1021   S.P.getGlobal(I)->deref<T>() = S.Stk.pop<T>();
1022   return true;
1023 }
1024 
1025 /// 1) Converts the value on top of the stack to an APValue
1026 /// 2) Sets that APValue on \Temp
1027 /// 3) Initialized global with index \I with that
1028 template <PrimType Name, class T = typename PrimConv<Name>::T>
1029 bool InitGlobalTemp(InterpState &S, CodePtr OpPC, uint32_t I,
1030                     const LifetimeExtendedTemporaryDecl *Temp) {
1031   assert(Temp);
1032   const T Value = S.Stk.peek<T>();
1033   APValue APV = Value.toAPValue();
1034   APValue *Cached = Temp->getOrCreateValue(true);
1035   *Cached = APV;
1036 
1037   S.P.getGlobal(I)->deref<T>() = S.Stk.pop<T>();
1038   return true;
1039 }
1040 
1041 /// 1) Converts the value on top of the stack to an APValue
1042 /// 2) Sets that APValue on \Temp
1043 /// 3) Initialized global with index \I with that
1044 inline bool InitGlobalTempComp(InterpState &S, CodePtr OpPC,
1045                                const LifetimeExtendedTemporaryDecl *Temp) {
1046   assert(Temp);
1047   const Pointer &P = S.Stk.peek<Pointer>();
1048   APValue *Cached = Temp->getOrCreateValue(true);
1049 
1050   *Cached = P.toRValue(S.getCtx());
1051   return true;
1052 }
1053 
1054 template <PrimType Name, class T = typename PrimConv<Name>::T>
1055 bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
1056   if (S.checkingPotentialConstantExpression())
1057     return false;
1058   const Pointer &This = S.Current->getThis();
1059   if (!CheckThis(S, OpPC, This))
1060     return false;
1061   const Pointer &Field = This.atField(I);
1062   Field.deref<T>() = S.Stk.pop<T>();
1063   Field.initialize();
1064   return true;
1065 }
1066 
1067 template <PrimType Name, class T = typename PrimConv<Name>::T>
1068 bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
1069   assert(F->isBitField());
1070   if (S.checkingPotentialConstantExpression())
1071     return false;
1072   const Pointer &This = S.Current->getThis();
1073   if (!CheckThis(S, OpPC, This))
1074     return false;
1075   const Pointer &Field = This.atField(F->Offset);
1076   const auto &Value = S.Stk.pop<T>();
1077   Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
1078   Field.initialize();
1079   return true;
1080 }
1081 
1082 template <PrimType Name, class T = typename PrimConv<Name>::T>
1083 bool InitThisFieldActive(InterpState &S, CodePtr OpPC, uint32_t I) {
1084   if (S.checkingPotentialConstantExpression())
1085     return false;
1086   const Pointer &This = S.Current->getThis();
1087   if (!CheckThis(S, OpPC, This))
1088     return false;
1089   const Pointer &Field = This.atField(I);
1090   Field.deref<T>() = S.Stk.pop<T>();
1091   Field.activate();
1092   Field.initialize();
1093   return true;
1094 }
1095 
1096 /// 1) Pops the value from the stack
1097 /// 2) Peeks a pointer from the stack
1098 /// 3) Pushes the value to field I of the pointer on the stack
1099 template <PrimType Name, class T = typename PrimConv<Name>::T>
1100 bool InitField(InterpState &S, CodePtr OpPC, uint32_t I) {
1101   const T &Value = S.Stk.pop<T>();
1102   const Pointer &Field = S.Stk.peek<Pointer>().atField(I);
1103   Field.deref<T>() = Value;
1104   Field.activate();
1105   Field.initialize();
1106   return true;
1107 }
1108 
1109 template <PrimType Name, class T = typename PrimConv<Name>::T>
1110 bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
1111   assert(F->isBitField());
1112   const T &Value = S.Stk.pop<T>();
1113   const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset);
1114   Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
1115   Field.activate();
1116   Field.initialize();
1117   return true;
1118 }
1119 
1120 template <PrimType Name, class T = typename PrimConv<Name>::T>
1121 bool InitFieldActive(InterpState &S, CodePtr OpPC, uint32_t I) {
1122   const T &Value = S.Stk.pop<T>();
1123   const Pointer &Ptr = S.Stk.pop<Pointer>();
1124   const Pointer &Field = Ptr.atField(I);
1125   Field.deref<T>() = Value;
1126   Field.activate();
1127   Field.initialize();
1128   return true;
1129 }
1130 
1131 //===----------------------------------------------------------------------===//
1132 // GetPtr Local/Param/Global/Field/This
1133 //===----------------------------------------------------------------------===//
1134 
1135 inline bool GetPtrLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
1136   S.Stk.push<Pointer>(S.Current->getLocalPointer(I));
1137   return true;
1138 }
1139 
1140 inline bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t I) {
1141   if (S.checkingPotentialConstantExpression()) {
1142     return false;
1143   }
1144   S.Stk.push<Pointer>(S.Current->getParamPointer(I));
1145   return true;
1146 }
1147 
1148 inline bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
1149   S.Stk.push<Pointer>(S.P.getPtrGlobal(I));
1150   return true;
1151 }
1152 
1153 /// 1) Pops a Pointer from the stack
1154 /// 2) Pushes Pointer.atField(Off) on the stack
1155 inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1156   const Pointer &Ptr = S.Stk.pop<Pointer>();
1157   if (S.inConstantContext() && !CheckNull(S, OpPC, Ptr, CSK_Field))
1158     return false;
1159   if (!CheckExtern(S, OpPC, Ptr))
1160     return false;
1161   if (!CheckRange(S, OpPC, Ptr, CSK_Field))
1162     return false;
1163   if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
1164     return false;
1165 
1166   S.Stk.push<Pointer>(Ptr.atField(Off));
1167   return true;
1168 }
1169 
1170 inline bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1171   if (S.checkingPotentialConstantExpression())
1172     return false;
1173   const Pointer &This = S.Current->getThis();
1174   if (!CheckThis(S, OpPC, This))
1175     return false;
1176   S.Stk.push<Pointer>(This.atField(Off));
1177   return true;
1178 }
1179 
1180 inline bool GetPtrActiveField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1181   const Pointer &Ptr = S.Stk.pop<Pointer>();
1182   if (!CheckNull(S, OpPC, Ptr, CSK_Field))
1183     return false;
1184   if (!CheckRange(S, OpPC, Ptr, CSK_Field))
1185     return false;
1186   Pointer Field = Ptr.atField(Off);
1187   Ptr.deactivate();
1188   Field.activate();
1189   S.Stk.push<Pointer>(std::move(Field));
1190   return true;
1191 }
1192 
1193 inline bool GetPtrActiveThisField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1194  if (S.checkingPotentialConstantExpression())
1195     return false;
1196   const Pointer &This = S.Current->getThis();
1197   if (!CheckThis(S, OpPC, This))
1198     return false;
1199   Pointer Field = This.atField(Off);
1200   This.deactivate();
1201   Field.activate();
1202   S.Stk.push<Pointer>(std::move(Field));
1203   return true;
1204 }
1205 
1206 inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
1207   const Pointer &Ptr = S.Stk.pop<Pointer>();
1208   if (!CheckNull(S, OpPC, Ptr, CSK_Derived))
1209     return false;
1210   if (!CheckSubobject(S, OpPC, Ptr, CSK_Derived))
1211     return false;
1212   S.Stk.push<Pointer>(Ptr.atFieldSub(Off));
1213   return true;
1214 }
1215 
1216 inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
1217   const Pointer &Ptr = S.Stk.peek<Pointer>();
1218   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
1219     return false;
1220   if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
1221     return false;
1222   S.Stk.push<Pointer>(Ptr.atField(Off));
1223   return true;
1224 }
1225 
1226 inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off) {
1227   const Pointer &Ptr = S.Stk.pop<Pointer>();
1228   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
1229     return false;
1230   if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
1231     return false;
1232   S.Stk.push<Pointer>(Ptr.atField(Off));
1233   return true;
1234 }
1235 
1236 inline bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
1237   if (S.checkingPotentialConstantExpression())
1238     return false;
1239   const Pointer &This = S.Current->getThis();
1240   if (!CheckThis(S, OpPC, This))
1241     return false;
1242   S.Stk.push<Pointer>(This.atField(Off));
1243   return true;
1244 }
1245 
1246 inline bool InitPtrPop(InterpState &S, CodePtr OpPC) {
1247   const Pointer &Ptr = S.Stk.pop<Pointer>();
1248   Ptr.initialize();
1249   return true;
1250 }
1251 
1252 inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl,
1253                            const Pointer &Ptr) {
1254   Pointer Base = Ptr;
1255   while (Base.isBaseClass())
1256     Base = Base.getBase();
1257 
1258   auto *Field = Base.getRecord()->getVirtualBase(Decl);
1259   S.Stk.push<Pointer>(Base.atField(Field->Offset));
1260   return true;
1261 }
1262 
1263 inline bool GetPtrVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D) {
1264   const Pointer &Ptr = S.Stk.pop<Pointer>();
1265   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
1266     return false;
1267   return VirtBaseHelper(S, OpPC, D, Ptr);
1268 }
1269 
1270 inline bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC,
1271                                const RecordDecl *D) {
1272   if (S.checkingPotentialConstantExpression())
1273     return false;
1274   const Pointer &This = S.Current->getThis();
1275   if (!CheckThis(S, OpPC, This))
1276     return false;
1277   return VirtBaseHelper(S, OpPC, D, S.Current->getThis());
1278 }
1279 
1280 //===----------------------------------------------------------------------===//
1281 // Load, Store, Init
1282 //===----------------------------------------------------------------------===//
1283 
1284 template <PrimType Name, class T = typename PrimConv<Name>::T>
1285 bool Load(InterpState &S, CodePtr OpPC) {
1286   const Pointer &Ptr = S.Stk.peek<Pointer>();
1287   if (!CheckLoad(S, OpPC, Ptr))
1288     return false;
1289   S.Stk.push<T>(Ptr.deref<T>());
1290   return true;
1291 }
1292 
1293 template <PrimType Name, class T = typename PrimConv<Name>::T>
1294 bool LoadPop(InterpState &S, CodePtr OpPC) {
1295   const Pointer &Ptr = S.Stk.pop<Pointer>();
1296   if (!CheckLoad(S, OpPC, Ptr))
1297     return false;
1298   S.Stk.push<T>(Ptr.deref<T>());
1299   return true;
1300 }
1301 
1302 template <PrimType Name, class T = typename PrimConv<Name>::T>
1303 bool Store(InterpState &S, CodePtr OpPC) {
1304   const T &Value = S.Stk.pop<T>();
1305   const Pointer &Ptr = S.Stk.peek<Pointer>();
1306   if (!CheckStore(S, OpPC, Ptr))
1307     return false;
1308   if (!Ptr.isRoot())
1309     Ptr.initialize();
1310   Ptr.deref<T>() = Value;
1311   return true;
1312 }
1313 
1314 template <PrimType Name, class T = typename PrimConv<Name>::T>
1315 bool StorePop(InterpState &S, CodePtr OpPC) {
1316   const T &Value = S.Stk.pop<T>();
1317   const Pointer &Ptr = S.Stk.pop<Pointer>();
1318   if (!CheckStore(S, OpPC, Ptr))
1319     return false;
1320   if (!Ptr.isRoot())
1321     Ptr.initialize();
1322   Ptr.deref<T>() = Value;
1323   return true;
1324 }
1325 
1326 template <PrimType Name, class T = typename PrimConv<Name>::T>
1327 bool StoreBitField(InterpState &S, CodePtr OpPC) {
1328   const T &Value = S.Stk.pop<T>();
1329   const Pointer &Ptr = S.Stk.peek<Pointer>();
1330   if (!CheckStore(S, OpPC, Ptr))
1331     return false;
1332   if (!Ptr.isRoot())
1333     Ptr.initialize();
1334   if (const auto *FD = Ptr.getField())
1335     Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getCtx()));
1336   else
1337     Ptr.deref<T>() = Value;
1338   return true;
1339 }
1340 
1341 template <PrimType Name, class T = typename PrimConv<Name>::T>
1342 bool StoreBitFieldPop(InterpState &S, CodePtr OpPC) {
1343   const T &Value = S.Stk.pop<T>();
1344   const Pointer &Ptr = S.Stk.pop<Pointer>();
1345   if (!CheckStore(S, OpPC, Ptr))
1346     return false;
1347   if (!Ptr.isRoot())
1348     Ptr.initialize();
1349   if (const auto *FD = Ptr.getField())
1350     Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getCtx()));
1351   else
1352     Ptr.deref<T>() = Value;
1353   return true;
1354 }
1355 
1356 template <PrimType Name, class T = typename PrimConv<Name>::T>
1357 bool InitPop(InterpState &S, CodePtr OpPC) {
1358   const T &Value = S.Stk.pop<T>();
1359   const Pointer &Ptr = S.Stk.pop<Pointer>();
1360   if (!CheckInit(S, OpPC, Ptr))
1361     return false;
1362   Ptr.initialize();
1363   new (&Ptr.deref<T>()) T(Value);
1364   return true;
1365 }
1366 
1367 /// 1) Pops the value from the stack
1368 /// 2) Peeks a pointer and gets its index \Idx
1369 /// 3) Sets the value on the pointer, leaving the pointer on the stack.
1370 template <PrimType Name, class T = typename PrimConv<Name>::T>
1371 bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx) {
1372   const T &Value = S.Stk.pop<T>();
1373   const Pointer &Ptr = S.Stk.peek<Pointer>().atIndex(Idx);
1374   if (!CheckInit(S, OpPC, Ptr))
1375     return false;
1376   Ptr.initialize();
1377   new (&Ptr.deref<T>()) T(Value);
1378   return true;
1379 }
1380 
1381 /// The same as InitElem, but pops the pointer as well.
1382 template <PrimType Name, class T = typename PrimConv<Name>::T>
1383 bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) {
1384   const T &Value = S.Stk.pop<T>();
1385   const Pointer &Ptr = S.Stk.pop<Pointer>().atIndex(Idx);
1386   if (!CheckInit(S, OpPC, Ptr))
1387     return false;
1388   Ptr.initialize();
1389   new (&Ptr.deref<T>()) T(Value);
1390   return true;
1391 }
1392 
1393 //===----------------------------------------------------------------------===//
1394 // AddOffset, SubOffset
1395 //===----------------------------------------------------------------------===//
1396 
1397 template <class T, ArithOp Op>
1398 bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
1399                   const Pointer &Ptr) {
1400   if (!CheckRange(S, OpPC, Ptr, CSK_ArrayToPointer))
1401     return false;
1402 
1403   // A zero offset does not change the pointer.
1404   if (Offset.isZero()) {
1405     S.Stk.push<Pointer>(Ptr);
1406     return true;
1407   }
1408 
1409   if (!CheckNull(S, OpPC, Ptr, CSK_ArrayIndex))
1410     return false;
1411 
1412   // Arrays of unknown bounds cannot have pointers into them.
1413   if (!CheckArray(S, OpPC, Ptr))
1414     return false;
1415 
1416   // Get a version of the index comparable to the type.
1417   T Index = T::from(Ptr.getIndex(), Offset.bitWidth());
1418   // Compute the largest index into the array.
1419   T MaxIndex = T::from(Ptr.getNumElems(), Offset.bitWidth());
1420 
1421   bool Invalid = false;
1422   // Helper to report an invalid offset, computed as APSInt.
1423   auto DiagInvalidOffset = [&]() -> void {
1424     const unsigned Bits = Offset.bitWidth();
1425     APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), false);
1426     APSInt APIndex(Index.toAPSInt().extend(Bits + 2), false);
1427     APSInt NewIndex =
1428         (Op == ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
1429     S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
1430         << NewIndex
1431         << /*array*/ static_cast<int>(!Ptr.inArray())
1432         << static_cast<unsigned>(MaxIndex);
1433     Invalid = true;
1434   };
1435 
1436   T MaxOffset = T::from(MaxIndex - Index, Offset.bitWidth());
1437   if constexpr (Op == ArithOp::Add) {
1438     // If the new offset would be negative, bail out.
1439     if (Offset.isNegative() && (Offset.isMin() || -Offset > Index))
1440       DiagInvalidOffset();
1441 
1442     // If the new offset would be out of bounds, bail out.
1443     if (Offset.isPositive() && Offset > MaxOffset)
1444       DiagInvalidOffset();
1445   } else {
1446     // If the new offset would be negative, bail out.
1447     if (Offset.isPositive() && Index < Offset)
1448       DiagInvalidOffset();
1449 
1450     // If the new offset would be out of bounds, bail out.
1451     if (Offset.isNegative() && (Offset.isMin() || -Offset > MaxOffset))
1452       DiagInvalidOffset();
1453   }
1454 
1455   if (Invalid && !Ptr.isDummy() && S.getLangOpts().CPlusPlus)
1456     return false;
1457 
1458   // Offset is valid - compute it on unsigned.
1459   int64_t WideIndex = static_cast<int64_t>(Index);
1460   int64_t WideOffset = static_cast<int64_t>(Offset);
1461   int64_t Result;
1462   if constexpr (Op == ArithOp::Add)
1463     Result = WideIndex + WideOffset;
1464   else
1465     Result = WideIndex - WideOffset;
1466 
1467   S.Stk.push<Pointer>(Ptr.atIndex(static_cast<unsigned>(Result)));
1468   return true;
1469 }
1470 
1471 template <PrimType Name, class T = typename PrimConv<Name>::T>
1472 bool AddOffset(InterpState &S, CodePtr OpPC) {
1473   const T &Offset = S.Stk.pop<T>();
1474   const Pointer &Ptr = S.Stk.pop<Pointer>();
1475   return OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr);
1476 }
1477 
1478 template <PrimType Name, class T = typename PrimConv<Name>::T>
1479 bool SubOffset(InterpState &S, CodePtr OpPC) {
1480   const T &Offset = S.Stk.pop<T>();
1481   const Pointer &Ptr = S.Stk.pop<Pointer>();
1482   return OffsetHelper<T, ArithOp::Sub>(S, OpPC, Offset, Ptr);
1483 }
1484 
1485 template <ArithOp Op>
1486 static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC,
1487                                    const Pointer &Ptr) {
1488   using OneT = Integral<8, false>;
1489 
1490   const Pointer &P = Ptr.deref<Pointer>();
1491   if (!CheckNull(S, OpPC, P, CSK_ArrayIndex))
1492     return false;
1493 
1494   // Get the current value on the stack.
1495   S.Stk.push<Pointer>(P);
1496 
1497   // Now the current Ptr again and a constant 1.
1498   OneT One = OneT::from(1);
1499   if (!OffsetHelper<OneT, Op>(S, OpPC, One, P))
1500     return false;
1501 
1502   // Store the new value.
1503   Ptr.deref<Pointer>() = S.Stk.pop<Pointer>();
1504   return true;
1505 }
1506 
1507 static inline bool IncPtr(InterpState &S, CodePtr OpPC) {
1508   const Pointer &Ptr = S.Stk.pop<Pointer>();
1509 
1510   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
1511     return false;
1512 
1513   return IncDecPtrHelper<ArithOp::Add>(S, OpPC, Ptr);
1514 }
1515 
1516 static inline bool DecPtr(InterpState &S, CodePtr OpPC) {
1517   const Pointer &Ptr = S.Stk.pop<Pointer>();
1518 
1519   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
1520     return false;
1521 
1522   return IncDecPtrHelper<ArithOp::Sub>(S, OpPC, Ptr);
1523 }
1524 
1525 /// 1) Pops a Pointer from the stack.
1526 /// 2) Pops another Pointer from the stack.
1527 /// 3) Pushes the different of the indices of the two pointers on the stack.
1528 template <PrimType Name, class T = typename PrimConv<Name>::T>
1529 inline bool SubPtr(InterpState &S, CodePtr OpPC) {
1530   const Pointer &LHS = S.Stk.pop<Pointer>();
1531   const Pointer &RHS = S.Stk.pop<Pointer>();
1532 
1533   if (!Pointer::hasSameBase(LHS, RHS) && S.getLangOpts().CPlusPlus) {
1534     // TODO: Diagnose.
1535     return false;
1536   }
1537 
1538   T A = T::from(LHS.getIndex());
1539   T B = T::from(RHS.getIndex());
1540   return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, A.bitWidth(), A, B);
1541 }
1542 
1543 //===----------------------------------------------------------------------===//
1544 // Destroy
1545 //===----------------------------------------------------------------------===//
1546 
1547 inline bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I) {
1548   S.Current->destroy(I);
1549   return true;
1550 }
1551 
1552 //===----------------------------------------------------------------------===//
1553 // Cast, CastFP
1554 //===----------------------------------------------------------------------===//
1555 
1556 template <PrimType TIn, PrimType TOut> bool Cast(InterpState &S, CodePtr OpPC) {
1557   using T = typename PrimConv<TIn>::T;
1558   using U = typename PrimConv<TOut>::T;
1559   S.Stk.push<U>(U::from(S.Stk.pop<T>()));
1560   return true;
1561 }
1562 
1563 /// 1) Pops a Floating from the stack.
1564 /// 2) Pushes a new floating on the stack that uses the given semantics.
1565 inline bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem,
1566             llvm::RoundingMode RM) {
1567   Floating F = S.Stk.pop<Floating>();
1568   Floating Result = F.toSemantics(Sem, RM);
1569   S.Stk.push<Floating>(Result);
1570   return true;
1571 }
1572 
1573 /// Like Cast(), but we cast to an arbitrary-bitwidth integral, so we need
1574 /// to know what bitwidth the result should be.
1575 template <PrimType Name, class T = typename PrimConv<Name>::T>
1576 bool CastAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
1577   S.Stk.push<IntegralAP<false>>(
1578       IntegralAP<false>::from(S.Stk.pop<T>(), BitWidth));
1579   return true;
1580 }
1581 
1582 template <PrimType Name, class T = typename PrimConv<Name>::T>
1583 bool CastAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
1584   S.Stk.push<IntegralAP<true>>(
1585       IntegralAP<true>::from(S.Stk.pop<T>(), BitWidth));
1586   return true;
1587 }
1588 
1589 template <PrimType Name, class T = typename PrimConv<Name>::T>
1590 bool CastIntegralFloating(InterpState &S, CodePtr OpPC,
1591                           const llvm::fltSemantics *Sem,
1592                           llvm::RoundingMode RM) {
1593   const T &From = S.Stk.pop<T>();
1594   APSInt FromAP = From.toAPSInt();
1595   Floating Result;
1596 
1597   auto Status = Floating::fromIntegral(FromAP, *Sem, RM, Result);
1598   S.Stk.push<Floating>(Result);
1599 
1600   return CheckFloatResult(S, OpPC, Result, Status);
1601 }
1602 
1603 template <PrimType Name, class T = typename PrimConv<Name>::T>
1604 bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) {
1605   const Floating &F = S.Stk.pop<Floating>();
1606 
1607   if constexpr (std::is_same_v<T, Boolean>) {
1608     S.Stk.push<T>(T(F.isNonZero()));
1609     return true;
1610   } else {
1611     APSInt Result(std::max(8u, T::bitWidth()),
1612                   /*IsUnsigned=*/!T::isSigned());
1613     auto Status = F.convertToInteger(Result);
1614 
1615     // Float-to-Integral overflow check.
1616     if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite()) {
1617       const Expr *E = S.Current->getExpr(OpPC);
1618       QualType Type = E->getType();
1619 
1620       S.CCEDiag(E, diag::note_constexpr_overflow) << F.getAPFloat() << Type;
1621       if (S.noteUndefinedBehavior()) {
1622         S.Stk.push<T>(T(Result));
1623         return true;
1624       }
1625       return false;
1626     }
1627 
1628     S.Stk.push<T>(T(Result));
1629     return CheckFloatResult(S, OpPC, F, Status);
1630   }
1631 }
1632 
1633 static inline bool CastFloatingIntegralAP(InterpState &S, CodePtr OpPC,
1634                                           uint32_t BitWidth) {
1635   const Floating &F = S.Stk.pop<Floating>();
1636 
1637   APSInt Result(BitWidth, /*IsUnsigned=*/true);
1638   auto Status = F.convertToInteger(Result);
1639 
1640   // Float-to-Integral overflow check.
1641   if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite()) {
1642     const Expr *E = S.Current->getExpr(OpPC);
1643     QualType Type = E->getType();
1644 
1645     S.CCEDiag(E, diag::note_constexpr_overflow) << F.getAPFloat() << Type;
1646     return S.noteUndefinedBehavior();
1647   }
1648 
1649   S.Stk.push<IntegralAP<true>>(IntegralAP<true>(Result));
1650   return CheckFloatResult(S, OpPC, F, Status);
1651 }
1652 
1653 static inline bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC,
1654                                            uint32_t BitWidth) {
1655   const Floating &F = S.Stk.pop<Floating>();
1656 
1657   APSInt Result(BitWidth, /*IsUnsigned=*/false);
1658   auto Status = F.convertToInteger(Result);
1659 
1660   // Float-to-Integral overflow check.
1661   if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite()) {
1662     const Expr *E = S.Current->getExpr(OpPC);
1663     QualType Type = E->getType();
1664 
1665     S.CCEDiag(E, diag::note_constexpr_overflow) << F.getAPFloat() << Type;
1666     return S.noteUndefinedBehavior();
1667   }
1668 
1669   S.Stk.push<IntegralAP<true>>(IntegralAP<true>(Result));
1670   return CheckFloatResult(S, OpPC, F, Status);
1671 }
1672 
1673 template <PrimType Name, class T = typename PrimConv<Name>::T>
1674 bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
1675   const Pointer &Ptr = S.Stk.pop<Pointer>();
1676 
1677   if (!CheckPotentialReinterpretCast(S, OpPC, Ptr))
1678     return false;
1679 
1680   S.Stk.push<T>(T::from(Ptr.getIntegerRepresentation()));
1681   return true;
1682 }
1683 
1684 //===----------------------------------------------------------------------===//
1685 // Zero, Nullptr
1686 //===----------------------------------------------------------------------===//
1687 
1688 template <PrimType Name, class T = typename PrimConv<Name>::T>
1689 bool Zero(InterpState &S, CodePtr OpPC) {
1690   S.Stk.push<T>(T::zero());
1691   return true;
1692 }
1693 
1694 static inline bool ZeroIntAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
1695   S.Stk.push<IntegralAP<false>>(IntegralAP<false>::zero(BitWidth));
1696   return true;
1697 }
1698 
1699 static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
1700   S.Stk.push<IntegralAP<true>>(IntegralAP<true>::zero(BitWidth));
1701   return true;
1702 }
1703 
1704 template <PrimType Name, class T = typename PrimConv<Name>::T>
1705 inline bool Null(InterpState &S, CodePtr OpPC) {
1706   S.Stk.push<T>();
1707   return true;
1708 }
1709 
1710 //===----------------------------------------------------------------------===//
1711 // This, ImplicitThis
1712 //===----------------------------------------------------------------------===//
1713 
1714 inline bool This(InterpState &S, CodePtr OpPC) {
1715   // Cannot read 'this' in this mode.
1716   if (S.checkingPotentialConstantExpression()) {
1717     return false;
1718   }
1719 
1720   const Pointer &This = S.Current->getThis();
1721   if (!CheckThis(S, OpPC, This))
1722     return false;
1723 
1724   S.Stk.push<Pointer>(This);
1725   return true;
1726 }
1727 
1728 inline bool RVOPtr(InterpState &S, CodePtr OpPC) {
1729   assert(S.Current->getFunction()->hasRVO());
1730   if (S.checkingPotentialConstantExpression())
1731     return false;
1732   S.Stk.push<Pointer>(S.Current->getRVOPtr());
1733   return true;
1734 }
1735 
1736 //===----------------------------------------------------------------------===//
1737 // Shr, Shl
1738 //===----------------------------------------------------------------------===//
1739 
1740 template <PrimType NameL, PrimType NameR>
1741 inline bool Shr(InterpState &S, CodePtr OpPC) {
1742   using LT = typename PrimConv<NameL>::T;
1743   using RT = typename PrimConv<NameR>::T;
1744   const auto &RHS = S.Stk.pop<RT>();
1745   const auto &LHS = S.Stk.pop<LT>();
1746   const unsigned Bits = LHS.bitWidth();
1747 
1748   if (!CheckShift(S, OpPC, LHS, RHS, Bits))
1749     return false;
1750 
1751   typename LT::AsUnsigned R;
1752   LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),
1753                              LT::AsUnsigned::from(RHS), Bits, &R);
1754   S.Stk.push<LT>(LT::from(R));
1755 
1756   return true;
1757 }
1758 
1759 template <PrimType NameL, PrimType NameR>
1760 inline bool Shl(InterpState &S, CodePtr OpPC) {
1761   using LT = typename PrimConv<NameL>::T;
1762   using RT = typename PrimConv<NameR>::T;
1763   const auto &RHS = S.Stk.pop<RT>();
1764   const auto &LHS = S.Stk.pop<LT>();
1765   const unsigned Bits = LHS.bitWidth();
1766 
1767   if (!CheckShift(S, OpPC, LHS, RHS, Bits))
1768     return false;
1769 
1770   typename LT::AsUnsigned R;
1771   LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
1772                             LT::AsUnsigned::from(RHS, Bits), Bits, &R);
1773   S.Stk.push<LT>(LT::from(R));
1774   return true;
1775 }
1776 
1777 //===----------------------------------------------------------------------===//
1778 // NoRet
1779 //===----------------------------------------------------------------------===//
1780 
1781 inline bool NoRet(InterpState &S, CodePtr OpPC) {
1782   SourceLocation EndLoc = S.Current->getCallee()->getEndLoc();
1783   S.FFDiag(EndLoc, diag::note_constexpr_no_return);
1784   return false;
1785 }
1786 
1787 //===----------------------------------------------------------------------===//
1788 // NarrowPtr, ExpandPtr
1789 //===----------------------------------------------------------------------===//
1790 
1791 inline bool NarrowPtr(InterpState &S, CodePtr OpPC) {
1792   const Pointer &Ptr = S.Stk.pop<Pointer>();
1793   S.Stk.push<Pointer>(Ptr.narrow());
1794   return true;
1795 }
1796 
1797 inline bool ExpandPtr(InterpState &S, CodePtr OpPC) {
1798   const Pointer &Ptr = S.Stk.pop<Pointer>();
1799   S.Stk.push<Pointer>(Ptr.expand());
1800   return true;
1801 }
1802 
1803 // 1) Pops an integral value from the stack
1804 // 2) Peeks a pointer
1805 // 3) Pushes a new pointer that's a narrowed array
1806 //   element of the peeked pointer with the value
1807 //   from 1) added as offset.
1808 //
1809 // This leaves the original pointer on the stack and pushes a new one
1810 // with the offset applied and narrowed.
1811 template <PrimType Name, class T = typename PrimConv<Name>::T>
1812 inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
1813   const T &Offset = S.Stk.pop<T>();
1814   const Pointer &Ptr = S.Stk.peek<Pointer>();
1815 
1816   if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
1817     return false;
1818 
1819   return NarrowPtr(S, OpPC);
1820 }
1821 
1822 /// Just takes a pointer and checks if its' an incomplete
1823 /// array type.
1824 inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
1825   const Pointer &Ptr = S.Stk.pop<Pointer>();
1826 
1827   if (!Ptr.isUnknownSizeArray()) {
1828     S.Stk.push<Pointer>(Ptr.atIndex(0));
1829     return true;
1830   }
1831 
1832   const SourceInfo &E = S.Current->getSource(OpPC);
1833   S.FFDiag(E, diag::note_constexpr_unsupported_unsized_array);
1834 
1835   return false;
1836 }
1837 
1838 template <PrimType Name, class T = typename PrimConv<Name>::T>
1839 inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
1840   const T &Offset = S.Stk.pop<T>();
1841   const Pointer &Ptr = S.Stk.pop<Pointer>();
1842 
1843   if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
1844     return false;
1845 
1846   return NarrowPtr(S, OpPC);
1847 }
1848 
1849 inline bool CheckGlobalCtor(InterpState &S, CodePtr OpPC) {
1850   const Pointer &Obj = S.Stk.peek<Pointer>();
1851   return CheckCtorCall(S, OpPC, Obj);
1852 }
1853 
1854 inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func) {
1855   if (Func->hasThisPointer()) {
1856     size_t ThisOffset =
1857         Func->getArgSize() - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1858 
1859     const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1860 
1861     // If the current function is a lambda static invoker and
1862     // the function we're about to call is a lambda call operator,
1863     // skip the CheckInvoke, since the ThisPtr is a null pointer
1864     // anyway.
1865     if (!(S.Current->getFunction() &&
1866           S.Current->getFunction()->isLambdaStaticInvoker() &&
1867           Func->isLambdaCallOperator())) {
1868       if (!CheckInvoke(S, OpPC, ThisPtr))
1869         return false;
1870     }
1871 
1872     if (S.checkingPotentialConstantExpression())
1873       return false;
1874   }
1875 
1876   if (!CheckCallable(S, OpPC, Func))
1877     return false;
1878 
1879   if (!CheckCallDepth(S, OpPC))
1880     return false;
1881 
1882   auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC);
1883   InterpFrame *FrameBefore = S.Current;
1884   S.Current = NewFrame.get();
1885 
1886   APValue CallResult;
1887   // Note that we cannot assert(CallResult.hasValue()) here since
1888   // Ret() above only sets the APValue if the curent frame doesn't
1889   // have a caller set.
1890   if (Interpret(S, CallResult)) {
1891     NewFrame.release(); // Frame was delete'd already.
1892     assert(S.Current == FrameBefore);
1893     return true;
1894   }
1895 
1896   // Interpreting the function failed somehow. Reset to
1897   // previous state.
1898   S.Current = FrameBefore;
1899   return false;
1900 }
1901 
1902 inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func) {
1903   assert(Func->hasThisPointer());
1904   assert(Func->isVirtual());
1905   size_t ThisOffset =
1906       Func->getArgSize() - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1907   Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1908 
1909   const CXXRecordDecl *DynamicDecl =
1910       ThisPtr.getDeclDesc()->getType()->getAsCXXRecordDecl();
1911   const auto *StaticDecl = cast<CXXRecordDecl>(Func->getParentDecl());
1912   const auto *InitialFunction = cast<CXXMethodDecl>(Func->getDecl());
1913   const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
1914       DynamicDecl, StaticDecl, InitialFunction);
1915 
1916   if (Overrider != InitialFunction) {
1917     // DR1872: An instantiated virtual constexpr function can't be called in a
1918     // constant expression (prior to C++20). We can still constant-fold such a
1919     // call.
1920     if (!S.getLangOpts().CPlusPlus20 && Overrider->isVirtual()) {
1921       const Expr *E = S.Current->getExpr(OpPC);
1922       S.CCEDiag(E, diag::note_constexpr_virtual_call) << E->getSourceRange();
1923     }
1924 
1925     Func = S.getContext().getOrCreateFunction(Overrider);
1926 
1927     const CXXRecordDecl *ThisFieldDecl =
1928         ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
1929     if (Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
1930       // If the function we call is further DOWN the hierarchy than the
1931       // FieldDesc of our pointer, just get the DeclDesc instead, which
1932       // is the furthest we might go up in the hierarchy.
1933       ThisPtr = ThisPtr.getDeclPtr();
1934     }
1935   }
1936 
1937   return Call(S, OpPC, Func);
1938 }
1939 
1940 inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func,
1941                    const CallExpr *CE) {
1942   auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);
1943 
1944   InterpFrame *FrameBefore = S.Current;
1945   S.Current = NewFrame.get();
1946 
1947   if (InterpretBuiltin(S, PC, Func, CE)) {
1948     NewFrame.release();
1949     return true;
1950   }
1951   S.Current = FrameBefore;
1952   return false;
1953 }
1954 
1955 inline bool CallPtr(InterpState &S, CodePtr OpPC) {
1956   const FunctionPointer &FuncPtr = S.Stk.pop<FunctionPointer>();
1957 
1958   const Function *F = FuncPtr.getFunction();
1959   if (!F || !F->isConstexpr())
1960     return false;
1961 
1962   if (F->isVirtual())
1963     return CallVirt(S, OpPC, F);
1964 
1965   return Call(S, OpPC, F);
1966 }
1967 
1968 inline bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func) {
1969   assert(Func);
1970   S.Stk.push<FunctionPointer>(Func);
1971   return true;
1972 }
1973 
1974 /// Just emit a diagnostic. The expression that caused emission of this
1975 /// op is not valid in a constant context.
1976 inline bool Invalid(InterpState &S, CodePtr OpPC) {
1977   const SourceLocation &Loc = S.Current->getLocation(OpPC);
1978   S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr)
1979       << S.Current->getRange(OpPC);
1980   return false;
1981 }
1982 
1983 /// Same here, but only for casts.
1984 inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind) {
1985   const SourceLocation &Loc = S.Current->getLocation(OpPC);
1986   S.FFDiag(Loc, diag::note_constexpr_invalid_cast)
1987       << static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
1988   return false;
1989 }
1990 
1991 inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC,
1992                            const DeclRefExpr *DR) {
1993   assert(DR);
1994   return CheckDeclRef(S, OpPC, DR);
1995 }
1996 
1997 template <PrimType Name, class T = typename PrimConv<Name>::T>
1998 inline bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E) {
1999   llvm::SmallVector<int64_t> ArrayIndices;
2000   for (size_t I = 0; I != E->getNumExpressions(); ++I)
2001     ArrayIndices.emplace_back(S.Stk.pop<int64_t>());
2002 
2003   int64_t Result;
2004   if (!InterpretOffsetOf(S, OpPC, E, ArrayIndices, Result))
2005     return false;
2006 
2007   S.Stk.push<T>(T::from(Result));
2008 
2009   return true;
2010 }
2011 
2012 //===----------------------------------------------------------------------===//
2013 // Read opcode arguments
2014 //===----------------------------------------------------------------------===//
2015 
2016 template <typename T> inline T ReadArg(InterpState &S, CodePtr &OpPC) {
2017   if constexpr (std::is_pointer<T>::value) {
2018     uint32_t ID = OpPC.read<uint32_t>();
2019     return reinterpret_cast<T>(S.P.getNativePointer(ID));
2020   } else {
2021     return OpPC.read<T>();
2022   }
2023 }
2024 
2025 template <> inline Floating ReadArg<Floating>(InterpState &S, CodePtr &OpPC) {
2026   Floating F = Floating::deserialize(*OpPC);
2027   OpPC += align(F.bytesToSerialize());
2028   return F;
2029 }
2030 
2031 } // namespace interp
2032 } // namespace clang
2033 
2034 #endif
2035