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