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 the Descriptor is of a constexpr or const global variable.
81 bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc);
82 
83 /// Checks if a pointer points to a mutable field.
84 bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
85 
86 /// Checks if a value can be loaded from a block.
87 bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
88 
89 bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
90                       AccessKinds AK);
91 
92 /// Checks if a value can be stored in a block.
93 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
94 
95 /// Checks if a method can be invoked on an object.
96 bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
97 
98 /// Checks if a value can be initialized.
99 bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
100 
101 /// Checks if a method can be called.
102 bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F);
103 
104 /// Checks if calling the currently active function would exceed
105 /// the allowed call depth.
106 bool CheckCallDepth(InterpState &S, CodePtr OpPC);
107 
108 /// Checks the 'this' pointer.
109 bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This);
110 
111 /// Checks if a method is pure virtual.
112 bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD);
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 
1008   if (!CheckConstant(S, OpPC, B->getDescriptor()))
1009     return false;
1010   if (B->isExtern())
1011     return false;
1012   S.Stk.push<T>(B->deref<T>());
1013   return true;
1014 }
1015 
1016 /// Same as GetGlobal, but without the checks.
1017 template <PrimType Name, class T = typename PrimConv<Name>::T>
1018 bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I) {
1019   auto *B = S.P.getGlobal(I);
1020   S.Stk.push<T>(B->deref<T>());
1021   return true;
1022 }
1023 
1024 template <PrimType Name, class T = typename PrimConv<Name>::T>
1025 bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
1026   // TODO: emit warning.
1027   return false;
1028 }
1029 
1030 template <PrimType Name, class T = typename PrimConv<Name>::T>
1031 bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
1032   S.P.getGlobal(I)->deref<T>() = S.Stk.pop<T>();
1033   return true;
1034 }
1035 
1036 /// 1) Converts the value on top of the stack to an APValue
1037 /// 2) Sets that APValue on \Temp
1038 /// 3) Initialized global with index \I with that
1039 template <PrimType Name, class T = typename PrimConv<Name>::T>
1040 bool InitGlobalTemp(InterpState &S, CodePtr OpPC, uint32_t I,
1041                     const LifetimeExtendedTemporaryDecl *Temp) {
1042   assert(Temp);
1043   const T Value = S.Stk.peek<T>();
1044   APValue APV = Value.toAPValue();
1045   APValue *Cached = Temp->getOrCreateValue(true);
1046   *Cached = APV;
1047 
1048   S.P.getGlobal(I)->deref<T>() = S.Stk.pop<T>();
1049   return true;
1050 }
1051 
1052 /// 1) Converts the value on top of the stack to an APValue
1053 /// 2) Sets that APValue on \Temp
1054 /// 3) Initialized global with index \I with that
1055 inline bool InitGlobalTempComp(InterpState &S, CodePtr OpPC,
1056                                const LifetimeExtendedTemporaryDecl *Temp) {
1057   assert(Temp);
1058   const Pointer &P = S.Stk.peek<Pointer>();
1059   APValue *Cached = Temp->getOrCreateValue(true);
1060 
1061   if (std::optional<APValue> APV = P.toRValue(S.getCtx())) {
1062     *Cached = *APV;
1063     return true;
1064   }
1065 
1066   return false;
1067 }
1068 
1069 template <PrimType Name, class T = typename PrimConv<Name>::T>
1070 bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
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(I);
1077   Field.deref<T>() = S.Stk.pop<T>();
1078   Field.initialize();
1079   return true;
1080 }
1081 
1082 // FIXME: The Field pointer here is too much IMO and we could instead just
1083 // pass an Offset + BitWidth pair.
1084 template <PrimType Name, class T = typename PrimConv<Name>::T>
1085 bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F,
1086                       uint32_t FieldOffset) {
1087   assert(F->isBitField());
1088   if (S.checkingPotentialConstantExpression())
1089     return false;
1090   const Pointer &This = S.Current->getThis();
1091   if (!CheckThis(S, OpPC, This))
1092     return false;
1093   const Pointer &Field = This.atField(FieldOffset);
1094   const auto &Value = S.Stk.pop<T>();
1095   Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
1096   Field.initialize();
1097   return true;
1098 }
1099 
1100 template <PrimType Name, class T = typename PrimConv<Name>::T>
1101 bool InitThisFieldActive(InterpState &S, CodePtr OpPC, uint32_t I) {
1102   if (S.checkingPotentialConstantExpression())
1103     return false;
1104   const Pointer &This = S.Current->getThis();
1105   if (!CheckThis(S, OpPC, This))
1106     return false;
1107   const Pointer &Field = This.atField(I);
1108   Field.deref<T>() = S.Stk.pop<T>();
1109   Field.activate();
1110   Field.initialize();
1111   return true;
1112 }
1113 
1114 /// 1) Pops the value from the stack
1115 /// 2) Peeks a pointer from the stack
1116 /// 3) Pushes the value to field I of the pointer on the stack
1117 template <PrimType Name, class T = typename PrimConv<Name>::T>
1118 bool InitField(InterpState &S, CodePtr OpPC, uint32_t I) {
1119   const T &Value = S.Stk.pop<T>();
1120   const Pointer &Field = S.Stk.peek<Pointer>().atField(I);
1121   Field.deref<T>() = Value;
1122   Field.activate();
1123   Field.initialize();
1124   return true;
1125 }
1126 
1127 template <PrimType Name, class T = typename PrimConv<Name>::T>
1128 bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
1129   assert(F->isBitField());
1130   const T &Value = S.Stk.pop<T>();
1131   const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset);
1132   Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
1133   Field.activate();
1134   Field.initialize();
1135   return true;
1136 }
1137 
1138 template <PrimType Name, class T = typename PrimConv<Name>::T>
1139 bool InitFieldActive(InterpState &S, CodePtr OpPC, uint32_t I) {
1140   const T &Value = S.Stk.pop<T>();
1141   const Pointer &Ptr = S.Stk.pop<Pointer>();
1142   const Pointer &Field = Ptr.atField(I);
1143   Field.deref<T>() = Value;
1144   Field.activate();
1145   Field.initialize();
1146   return true;
1147 }
1148 
1149 //===----------------------------------------------------------------------===//
1150 // GetPtr Local/Param/Global/Field/This
1151 //===----------------------------------------------------------------------===//
1152 
1153 inline bool GetPtrLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
1154   S.Stk.push<Pointer>(S.Current->getLocalPointer(I));
1155   return true;
1156 }
1157 
1158 inline bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t I) {
1159   if (S.checkingPotentialConstantExpression()) {
1160     return false;
1161   }
1162   S.Stk.push<Pointer>(S.Current->getParamPointer(I));
1163   return true;
1164 }
1165 
1166 inline bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
1167   S.Stk.push<Pointer>(S.P.getPtrGlobal(I));
1168   return true;
1169 }
1170 
1171 /// 1) Pops a Pointer from the stack
1172 /// 2) Pushes Pointer.atField(Off) on the stack
1173 inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1174   const Pointer &Ptr = S.Stk.pop<Pointer>();
1175   if (S.inConstantContext() && !CheckNull(S, OpPC, Ptr, CSK_Field))
1176     return false;
1177   if (!CheckExtern(S, OpPC, Ptr))
1178     return false;
1179   if (!CheckRange(S, OpPC, Ptr, CSK_Field))
1180     return false;
1181   if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
1182     return false;
1183 
1184   S.Stk.push<Pointer>(Ptr.atField(Off));
1185   return true;
1186 }
1187 
1188 inline bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1189   if (S.checkingPotentialConstantExpression())
1190     return false;
1191   const Pointer &This = S.Current->getThis();
1192   if (!CheckThis(S, OpPC, This))
1193     return false;
1194   S.Stk.push<Pointer>(This.atField(Off));
1195   return true;
1196 }
1197 
1198 inline bool GetPtrActiveField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1199   const Pointer &Ptr = S.Stk.pop<Pointer>();
1200   if (!CheckNull(S, OpPC, Ptr, CSK_Field))
1201     return false;
1202   if (!CheckRange(S, OpPC, Ptr, CSK_Field))
1203     return false;
1204   Pointer Field = Ptr.atField(Off);
1205   Ptr.deactivate();
1206   Field.activate();
1207   S.Stk.push<Pointer>(std::move(Field));
1208   return true;
1209 }
1210 
1211 inline bool GetPtrActiveThisField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1212  if (S.checkingPotentialConstantExpression())
1213     return false;
1214   const Pointer &This = S.Current->getThis();
1215   if (!CheckThis(S, OpPC, This))
1216     return false;
1217   Pointer Field = This.atField(Off);
1218   This.deactivate();
1219   Field.activate();
1220   S.Stk.push<Pointer>(std::move(Field));
1221   return true;
1222 }
1223 
1224 inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
1225   const Pointer &Ptr = S.Stk.pop<Pointer>();
1226   if (!CheckNull(S, OpPC, Ptr, CSK_Derived))
1227     return false;
1228   if (!CheckSubobject(S, OpPC, Ptr, CSK_Derived))
1229     return false;
1230   S.Stk.push<Pointer>(Ptr.atFieldSub(Off));
1231   return true;
1232 }
1233 
1234 inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
1235   const Pointer &Ptr = S.Stk.peek<Pointer>();
1236   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
1237     return false;
1238   if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
1239     return false;
1240   S.Stk.push<Pointer>(Ptr.atField(Off));
1241   return true;
1242 }
1243 
1244 inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off) {
1245   const Pointer &Ptr = S.Stk.pop<Pointer>();
1246   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
1247     return false;
1248   if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
1249     return false;
1250   S.Stk.push<Pointer>(Ptr.atField(Off));
1251   return true;
1252 }
1253 
1254 inline bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
1255   if (S.checkingPotentialConstantExpression())
1256     return false;
1257   const Pointer &This = S.Current->getThis();
1258   if (!CheckThis(S, OpPC, This))
1259     return false;
1260   S.Stk.push<Pointer>(This.atField(Off));
1261   return true;
1262 }
1263 
1264 inline bool InitPtrPop(InterpState &S, CodePtr OpPC) {
1265   const Pointer &Ptr = S.Stk.pop<Pointer>();
1266   Ptr.initialize();
1267   return true;
1268 }
1269 
1270 inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl,
1271                            const Pointer &Ptr) {
1272   Pointer Base = Ptr;
1273   while (Base.isBaseClass())
1274     Base = Base.getBase();
1275 
1276   auto *Field = Base.getRecord()->getVirtualBase(Decl);
1277   S.Stk.push<Pointer>(Base.atField(Field->Offset));
1278   return true;
1279 }
1280 
1281 inline bool GetPtrVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D) {
1282   const Pointer &Ptr = S.Stk.pop<Pointer>();
1283   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
1284     return false;
1285   return VirtBaseHelper(S, OpPC, D, Ptr);
1286 }
1287 
1288 inline bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC,
1289                                const RecordDecl *D) {
1290   if (S.checkingPotentialConstantExpression())
1291     return false;
1292   const Pointer &This = S.Current->getThis();
1293   if (!CheckThis(S, OpPC, This))
1294     return false;
1295   return VirtBaseHelper(S, OpPC, D, S.Current->getThis());
1296 }
1297 
1298 //===----------------------------------------------------------------------===//
1299 // Load, Store, Init
1300 //===----------------------------------------------------------------------===//
1301 
1302 template <PrimType Name, class T = typename PrimConv<Name>::T>
1303 bool Load(InterpState &S, CodePtr OpPC) {
1304   const Pointer &Ptr = S.Stk.peek<Pointer>();
1305   if (!CheckLoad(S, OpPC, Ptr))
1306     return false;
1307   S.Stk.push<T>(Ptr.deref<T>());
1308   return true;
1309 }
1310 
1311 template <PrimType Name, class T = typename PrimConv<Name>::T>
1312 bool LoadPop(InterpState &S, CodePtr OpPC) {
1313   const Pointer &Ptr = S.Stk.pop<Pointer>();
1314   if (!CheckLoad(S, OpPC, Ptr))
1315     return false;
1316   S.Stk.push<T>(Ptr.deref<T>());
1317   return true;
1318 }
1319 
1320 template <PrimType Name, class T = typename PrimConv<Name>::T>
1321 bool Store(InterpState &S, CodePtr OpPC) {
1322   const T &Value = S.Stk.pop<T>();
1323   const Pointer &Ptr = S.Stk.peek<Pointer>();
1324   if (!CheckStore(S, OpPC, Ptr))
1325     return false;
1326   if (!Ptr.isRoot())
1327     Ptr.initialize();
1328   Ptr.deref<T>() = Value;
1329   return true;
1330 }
1331 
1332 template <PrimType Name, class T = typename PrimConv<Name>::T>
1333 bool StorePop(InterpState &S, CodePtr OpPC) {
1334   const T &Value = S.Stk.pop<T>();
1335   const Pointer &Ptr = S.Stk.pop<Pointer>();
1336   if (!CheckStore(S, OpPC, Ptr))
1337     return false;
1338   if (!Ptr.isRoot())
1339     Ptr.initialize();
1340   Ptr.deref<T>() = Value;
1341   return true;
1342 }
1343 
1344 template <PrimType Name, class T = typename PrimConv<Name>::T>
1345 bool StoreBitField(InterpState &S, CodePtr OpPC) {
1346   const T &Value = S.Stk.pop<T>();
1347   const Pointer &Ptr = S.Stk.peek<Pointer>();
1348   if (!CheckStore(S, OpPC, Ptr))
1349     return false;
1350   if (!Ptr.isRoot())
1351     Ptr.initialize();
1352   if (const auto *FD = Ptr.getField())
1353     Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getCtx()));
1354   else
1355     Ptr.deref<T>() = Value;
1356   return true;
1357 }
1358 
1359 template <PrimType Name, class T = typename PrimConv<Name>::T>
1360 bool StoreBitFieldPop(InterpState &S, CodePtr OpPC) {
1361   const T &Value = S.Stk.pop<T>();
1362   const Pointer &Ptr = S.Stk.pop<Pointer>();
1363   if (!CheckStore(S, OpPC, Ptr))
1364     return false;
1365   if (!Ptr.isRoot())
1366     Ptr.initialize();
1367   if (const auto *FD = Ptr.getField())
1368     Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getCtx()));
1369   else
1370     Ptr.deref<T>() = Value;
1371   return true;
1372 }
1373 
1374 template <PrimType Name, class T = typename PrimConv<Name>::T>
1375 bool InitPop(InterpState &S, CodePtr OpPC) {
1376   const T &Value = S.Stk.pop<T>();
1377   const Pointer &Ptr = S.Stk.pop<Pointer>();
1378   if (!CheckInit(S, OpPC, Ptr))
1379     return false;
1380   Ptr.initialize();
1381   new (&Ptr.deref<T>()) T(Value);
1382   return true;
1383 }
1384 
1385 /// 1) Pops the value from the stack
1386 /// 2) Peeks a pointer and gets its index \Idx
1387 /// 3) Sets the value on the pointer, leaving the pointer on the stack.
1388 template <PrimType Name, class T = typename PrimConv<Name>::T>
1389 bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx) {
1390   const T &Value = S.Stk.pop<T>();
1391   const Pointer &Ptr = S.Stk.peek<Pointer>().atIndex(Idx);
1392   if (!CheckInit(S, OpPC, Ptr))
1393     return false;
1394   Ptr.initialize();
1395   new (&Ptr.deref<T>()) T(Value);
1396   return true;
1397 }
1398 
1399 /// The same as InitElem, but pops the pointer as well.
1400 template <PrimType Name, class T = typename PrimConv<Name>::T>
1401 bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) {
1402   const T &Value = S.Stk.pop<T>();
1403   const Pointer &Ptr = S.Stk.pop<Pointer>().atIndex(Idx);
1404   if (!CheckInit(S, OpPC, Ptr))
1405     return false;
1406   Ptr.initialize();
1407   new (&Ptr.deref<T>()) T(Value);
1408   return true;
1409 }
1410 
1411 //===----------------------------------------------------------------------===//
1412 // AddOffset, SubOffset
1413 //===----------------------------------------------------------------------===//
1414 
1415 template <class T, ArithOp Op>
1416 bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
1417                   const Pointer &Ptr) {
1418   if (!CheckRange(S, OpPC, Ptr, CSK_ArrayToPointer))
1419     return false;
1420 
1421   // A zero offset does not change the pointer.
1422   if (Offset.isZero()) {
1423     S.Stk.push<Pointer>(Ptr);
1424     return true;
1425   }
1426 
1427   if (!CheckNull(S, OpPC, Ptr, CSK_ArrayIndex))
1428     return false;
1429 
1430   // Arrays of unknown bounds cannot have pointers into them.
1431   if (!CheckArray(S, OpPC, Ptr))
1432     return false;
1433 
1434   // Get a version of the index comparable to the type.
1435   T Index = T::from(Ptr.getIndex(), Offset.bitWidth());
1436   // Compute the largest index into the array.
1437   T MaxIndex = T::from(Ptr.getNumElems(), Offset.bitWidth());
1438 
1439   bool Invalid = false;
1440   // Helper to report an invalid offset, computed as APSInt.
1441   auto DiagInvalidOffset = [&]() -> void {
1442     const unsigned Bits = Offset.bitWidth();
1443     APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), false);
1444     APSInt APIndex(Index.toAPSInt().extend(Bits + 2), false);
1445     APSInt NewIndex =
1446         (Op == ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
1447     S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
1448         << NewIndex
1449         << /*array*/ static_cast<int>(!Ptr.inArray())
1450         << static_cast<unsigned>(MaxIndex);
1451     Invalid = true;
1452   };
1453 
1454   T MaxOffset = T::from(MaxIndex - Index, Offset.bitWidth());
1455   if constexpr (Op == ArithOp::Add) {
1456     // If the new offset would be negative, bail out.
1457     if (Offset.isNegative() && (Offset.isMin() || -Offset > Index))
1458       DiagInvalidOffset();
1459 
1460     // If the new offset would be out of bounds, bail out.
1461     if (Offset.isPositive() && Offset > MaxOffset)
1462       DiagInvalidOffset();
1463   } else {
1464     // If the new offset would be negative, bail out.
1465     if (Offset.isPositive() && Index < Offset)
1466       DiagInvalidOffset();
1467 
1468     // If the new offset would be out of bounds, bail out.
1469     if (Offset.isNegative() && (Offset.isMin() || -Offset > MaxOffset))
1470       DiagInvalidOffset();
1471   }
1472 
1473   if (Invalid && !Ptr.isDummy() && S.getLangOpts().CPlusPlus)
1474     return false;
1475 
1476   // Offset is valid - compute it on unsigned.
1477   int64_t WideIndex = static_cast<int64_t>(Index);
1478   int64_t WideOffset = static_cast<int64_t>(Offset);
1479   int64_t Result;
1480   if constexpr (Op == ArithOp::Add)
1481     Result = WideIndex + WideOffset;
1482   else
1483     Result = WideIndex - WideOffset;
1484 
1485   S.Stk.push<Pointer>(Ptr.atIndex(static_cast<unsigned>(Result)));
1486   return true;
1487 }
1488 
1489 template <PrimType Name, class T = typename PrimConv<Name>::T>
1490 bool AddOffset(InterpState &S, CodePtr OpPC) {
1491   const T &Offset = S.Stk.pop<T>();
1492   const Pointer &Ptr = S.Stk.pop<Pointer>();
1493   return OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr);
1494 }
1495 
1496 template <PrimType Name, class T = typename PrimConv<Name>::T>
1497 bool SubOffset(InterpState &S, CodePtr OpPC) {
1498   const T &Offset = S.Stk.pop<T>();
1499   const Pointer &Ptr = S.Stk.pop<Pointer>();
1500   return OffsetHelper<T, ArithOp::Sub>(S, OpPC, Offset, Ptr);
1501 }
1502 
1503 template <ArithOp Op>
1504 static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC,
1505                                    const Pointer &Ptr) {
1506   using OneT = Integral<8, false>;
1507 
1508   const Pointer &P = Ptr.deref<Pointer>();
1509   if (!CheckNull(S, OpPC, P, CSK_ArrayIndex))
1510     return false;
1511 
1512   // Get the current value on the stack.
1513   S.Stk.push<Pointer>(P);
1514 
1515   // Now the current Ptr again and a constant 1.
1516   OneT One = OneT::from(1);
1517   if (!OffsetHelper<OneT, Op>(S, OpPC, One, P))
1518     return false;
1519 
1520   // Store the new value.
1521   Ptr.deref<Pointer>() = S.Stk.pop<Pointer>();
1522   return true;
1523 }
1524 
1525 static inline bool IncPtr(InterpState &S, CodePtr OpPC) {
1526   const Pointer &Ptr = S.Stk.pop<Pointer>();
1527 
1528   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
1529     return false;
1530 
1531   return IncDecPtrHelper<ArithOp::Add>(S, OpPC, Ptr);
1532 }
1533 
1534 static inline bool DecPtr(InterpState &S, CodePtr OpPC) {
1535   const Pointer &Ptr = S.Stk.pop<Pointer>();
1536 
1537   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
1538     return false;
1539 
1540   return IncDecPtrHelper<ArithOp::Sub>(S, OpPC, Ptr);
1541 }
1542 
1543 /// 1) Pops a Pointer from the stack.
1544 /// 2) Pops another Pointer from the stack.
1545 /// 3) Pushes the different of the indices of the two pointers on the stack.
1546 template <PrimType Name, class T = typename PrimConv<Name>::T>
1547 inline bool SubPtr(InterpState &S, CodePtr OpPC) {
1548   const Pointer &LHS = S.Stk.pop<Pointer>();
1549   const Pointer &RHS = S.Stk.pop<Pointer>();
1550 
1551   if (!Pointer::hasSameBase(LHS, RHS) && S.getLangOpts().CPlusPlus) {
1552     // TODO: Diagnose.
1553     return false;
1554   }
1555 
1556   T A = T::from(LHS.getIndex());
1557   T B = T::from(RHS.getIndex());
1558   return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, A.bitWidth(), A, B);
1559 }
1560 
1561 //===----------------------------------------------------------------------===//
1562 // Destroy
1563 //===----------------------------------------------------------------------===//
1564 
1565 inline bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I) {
1566   S.Current->destroy(I);
1567   return true;
1568 }
1569 
1570 //===----------------------------------------------------------------------===//
1571 // Cast, CastFP
1572 //===----------------------------------------------------------------------===//
1573 
1574 template <PrimType TIn, PrimType TOut> bool Cast(InterpState &S, CodePtr OpPC) {
1575   using T = typename PrimConv<TIn>::T;
1576   using U = typename PrimConv<TOut>::T;
1577   S.Stk.push<U>(U::from(S.Stk.pop<T>()));
1578   return true;
1579 }
1580 
1581 /// 1) Pops a Floating from the stack.
1582 /// 2) Pushes a new floating on the stack that uses the given semantics.
1583 inline bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem,
1584             llvm::RoundingMode RM) {
1585   Floating F = S.Stk.pop<Floating>();
1586   Floating Result = F.toSemantics(Sem, RM);
1587   S.Stk.push<Floating>(Result);
1588   return true;
1589 }
1590 
1591 /// Like Cast(), but we cast to an arbitrary-bitwidth integral, so we need
1592 /// to know what bitwidth the result should be.
1593 template <PrimType Name, class T = typename PrimConv<Name>::T>
1594 bool CastAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
1595   S.Stk.push<IntegralAP<false>>(
1596       IntegralAP<false>::from(S.Stk.pop<T>(), BitWidth));
1597   return true;
1598 }
1599 
1600 template <PrimType Name, class T = typename PrimConv<Name>::T>
1601 bool CastAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
1602   S.Stk.push<IntegralAP<true>>(
1603       IntegralAP<true>::from(S.Stk.pop<T>(), BitWidth));
1604   return true;
1605 }
1606 
1607 template <PrimType Name, class T = typename PrimConv<Name>::T>
1608 bool CastIntegralFloating(InterpState &S, CodePtr OpPC,
1609                           const llvm::fltSemantics *Sem,
1610                           llvm::RoundingMode RM) {
1611   const T &From = S.Stk.pop<T>();
1612   APSInt FromAP = From.toAPSInt();
1613   Floating Result;
1614 
1615   auto Status = Floating::fromIntegral(FromAP, *Sem, RM, Result);
1616   S.Stk.push<Floating>(Result);
1617 
1618   return CheckFloatResult(S, OpPC, Result, Status);
1619 }
1620 
1621 template <PrimType Name, class T = typename PrimConv<Name>::T>
1622 bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) {
1623   const Floating &F = S.Stk.pop<Floating>();
1624 
1625   if constexpr (std::is_same_v<T, Boolean>) {
1626     S.Stk.push<T>(T(F.isNonZero()));
1627     return true;
1628   } else {
1629     APSInt Result(std::max(8u, T::bitWidth()),
1630                   /*IsUnsigned=*/!T::isSigned());
1631     auto Status = F.convertToInteger(Result);
1632 
1633     // Float-to-Integral overflow check.
1634     if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite()) {
1635       const Expr *E = S.Current->getExpr(OpPC);
1636       QualType Type = E->getType();
1637 
1638       S.CCEDiag(E, diag::note_constexpr_overflow) << F.getAPFloat() << Type;
1639       if (S.noteUndefinedBehavior()) {
1640         S.Stk.push<T>(T(Result));
1641         return true;
1642       }
1643       return false;
1644     }
1645 
1646     S.Stk.push<T>(T(Result));
1647     return CheckFloatResult(S, OpPC, F, Status);
1648   }
1649 }
1650 
1651 static inline bool CastFloatingIntegralAP(InterpState &S, CodePtr OpPC,
1652                                           uint32_t BitWidth) {
1653   const Floating &F = S.Stk.pop<Floating>();
1654 
1655   APSInt Result(BitWidth, /*IsUnsigned=*/true);
1656   auto Status = F.convertToInteger(Result);
1657 
1658   // Float-to-Integral overflow check.
1659   if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite()) {
1660     const Expr *E = S.Current->getExpr(OpPC);
1661     QualType Type = E->getType();
1662 
1663     S.CCEDiag(E, diag::note_constexpr_overflow) << F.getAPFloat() << Type;
1664     return S.noteUndefinedBehavior();
1665   }
1666 
1667   S.Stk.push<IntegralAP<true>>(IntegralAP<true>(Result));
1668   return CheckFloatResult(S, OpPC, F, Status);
1669 }
1670 
1671 static inline bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC,
1672                                            uint32_t BitWidth) {
1673   const Floating &F = S.Stk.pop<Floating>();
1674 
1675   APSInt Result(BitWidth, /*IsUnsigned=*/false);
1676   auto Status = F.convertToInteger(Result);
1677 
1678   // Float-to-Integral overflow check.
1679   if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite()) {
1680     const Expr *E = S.Current->getExpr(OpPC);
1681     QualType Type = E->getType();
1682 
1683     S.CCEDiag(E, diag::note_constexpr_overflow) << F.getAPFloat() << Type;
1684     return S.noteUndefinedBehavior();
1685   }
1686 
1687   S.Stk.push<IntegralAP<true>>(IntegralAP<true>(Result));
1688   return CheckFloatResult(S, OpPC, F, Status);
1689 }
1690 
1691 template <PrimType Name, class T = typename PrimConv<Name>::T>
1692 bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
1693   const Pointer &Ptr = S.Stk.pop<Pointer>();
1694 
1695   if (!CheckPotentialReinterpretCast(S, OpPC, Ptr))
1696     return false;
1697 
1698   S.Stk.push<T>(T::from(Ptr.getIntegerRepresentation()));
1699   return true;
1700 }
1701 
1702 //===----------------------------------------------------------------------===//
1703 // Zero, Nullptr
1704 //===----------------------------------------------------------------------===//
1705 
1706 template <PrimType Name, class T = typename PrimConv<Name>::T>
1707 bool Zero(InterpState &S, CodePtr OpPC) {
1708   S.Stk.push<T>(T::zero());
1709   return true;
1710 }
1711 
1712 static inline bool ZeroIntAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
1713   S.Stk.push<IntegralAP<false>>(IntegralAP<false>::zero(BitWidth));
1714   return true;
1715 }
1716 
1717 static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
1718   S.Stk.push<IntegralAP<true>>(IntegralAP<true>::zero(BitWidth));
1719   return true;
1720 }
1721 
1722 template <PrimType Name, class T = typename PrimConv<Name>::T>
1723 inline bool Null(InterpState &S, CodePtr OpPC) {
1724   S.Stk.push<T>();
1725   return true;
1726 }
1727 
1728 //===----------------------------------------------------------------------===//
1729 // This, ImplicitThis
1730 //===----------------------------------------------------------------------===//
1731 
1732 inline bool This(InterpState &S, CodePtr OpPC) {
1733   // Cannot read 'this' in this mode.
1734   if (S.checkingPotentialConstantExpression()) {
1735     return false;
1736   }
1737 
1738   const Pointer &This = S.Current->getThis();
1739   if (!CheckThis(S, OpPC, This))
1740     return false;
1741 
1742   S.Stk.push<Pointer>(This);
1743   return true;
1744 }
1745 
1746 inline bool RVOPtr(InterpState &S, CodePtr OpPC) {
1747   assert(S.Current->getFunction()->hasRVO());
1748   if (S.checkingPotentialConstantExpression())
1749     return false;
1750   S.Stk.push<Pointer>(S.Current->getRVOPtr());
1751   return true;
1752 }
1753 
1754 //===----------------------------------------------------------------------===//
1755 // Shr, Shl
1756 //===----------------------------------------------------------------------===//
1757 
1758 template <PrimType NameL, PrimType NameR>
1759 inline bool Shr(InterpState &S, CodePtr OpPC) {
1760   using LT = typename PrimConv<NameL>::T;
1761   using RT = typename PrimConv<NameR>::T;
1762   const auto &RHS = S.Stk.pop<RT>();
1763   const auto &LHS = S.Stk.pop<LT>();
1764   const unsigned Bits = LHS.bitWidth();
1765 
1766   if (!CheckShift(S, OpPC, LHS, RHS, Bits))
1767     return false;
1768 
1769   typename LT::AsUnsigned R;
1770   LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),
1771                              LT::AsUnsigned::from(RHS), Bits, &R);
1772   S.Stk.push<LT>(LT::from(R));
1773 
1774   return true;
1775 }
1776 
1777 template <PrimType NameL, PrimType NameR>
1778 inline bool Shl(InterpState &S, CodePtr OpPC) {
1779   using LT = typename PrimConv<NameL>::T;
1780   using RT = typename PrimConv<NameR>::T;
1781   const auto &RHS = S.Stk.pop<RT>();
1782   const auto &LHS = S.Stk.pop<LT>();
1783   const unsigned Bits = LHS.bitWidth();
1784 
1785   if (!CheckShift(S, OpPC, LHS, RHS, Bits))
1786     return false;
1787 
1788   typename LT::AsUnsigned R;
1789   LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
1790                             LT::AsUnsigned::from(RHS, Bits), Bits, &R);
1791   S.Stk.push<LT>(LT::from(R));
1792   return true;
1793 }
1794 
1795 //===----------------------------------------------------------------------===//
1796 // NoRet
1797 //===----------------------------------------------------------------------===//
1798 
1799 inline bool NoRet(InterpState &S, CodePtr OpPC) {
1800   SourceLocation EndLoc = S.Current->getCallee()->getEndLoc();
1801   S.FFDiag(EndLoc, diag::note_constexpr_no_return);
1802   return false;
1803 }
1804 
1805 //===----------------------------------------------------------------------===//
1806 // NarrowPtr, ExpandPtr
1807 //===----------------------------------------------------------------------===//
1808 
1809 inline bool NarrowPtr(InterpState &S, CodePtr OpPC) {
1810   const Pointer &Ptr = S.Stk.pop<Pointer>();
1811   S.Stk.push<Pointer>(Ptr.narrow());
1812   return true;
1813 }
1814 
1815 inline bool ExpandPtr(InterpState &S, CodePtr OpPC) {
1816   const Pointer &Ptr = S.Stk.pop<Pointer>();
1817   S.Stk.push<Pointer>(Ptr.expand());
1818   return true;
1819 }
1820 
1821 // 1) Pops an integral value from the stack
1822 // 2) Peeks a pointer
1823 // 3) Pushes a new pointer that's a narrowed array
1824 //   element of the peeked pointer with the value
1825 //   from 1) added as offset.
1826 //
1827 // This leaves the original pointer on the stack and pushes a new one
1828 // with the offset applied and narrowed.
1829 template <PrimType Name, class T = typename PrimConv<Name>::T>
1830 inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
1831   const T &Offset = S.Stk.pop<T>();
1832   const Pointer &Ptr = S.Stk.peek<Pointer>();
1833 
1834   if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
1835     return false;
1836 
1837   return NarrowPtr(S, OpPC);
1838 }
1839 
1840 /// Just takes a pointer and checks if its' an incomplete
1841 /// array type.
1842 inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
1843   const Pointer &Ptr = S.Stk.pop<Pointer>();
1844 
1845   if (!Ptr.isUnknownSizeArray()) {
1846     S.Stk.push<Pointer>(Ptr.atIndex(0));
1847     return true;
1848   }
1849 
1850   const SourceInfo &E = S.Current->getSource(OpPC);
1851   S.FFDiag(E, diag::note_constexpr_unsupported_unsized_array);
1852 
1853   return false;
1854 }
1855 
1856 template <PrimType Name, class T = typename PrimConv<Name>::T>
1857 inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
1858   const T &Offset = S.Stk.pop<T>();
1859   const Pointer &Ptr = S.Stk.pop<Pointer>();
1860 
1861   if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
1862     return false;
1863 
1864   return NarrowPtr(S, OpPC);
1865 }
1866 
1867 inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func) {
1868   if (Func->hasThisPointer()) {
1869     size_t ThisOffset =
1870         Func->getArgSize() - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1871 
1872     const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1873 
1874     // If the current function is a lambda static invoker and
1875     // the function we're about to call is a lambda call operator,
1876     // skip the CheckInvoke, since the ThisPtr is a null pointer
1877     // anyway.
1878     if (!(S.Current->getFunction() &&
1879           S.Current->getFunction()->isLambdaStaticInvoker() &&
1880           Func->isLambdaCallOperator())) {
1881       if (!CheckInvoke(S, OpPC, ThisPtr))
1882         return false;
1883     }
1884 
1885     if (S.checkingPotentialConstantExpression())
1886       return false;
1887   }
1888 
1889   if (!CheckCallable(S, OpPC, Func))
1890     return false;
1891 
1892   if (!CheckCallDepth(S, OpPC))
1893     return false;
1894 
1895   auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC);
1896   InterpFrame *FrameBefore = S.Current;
1897   S.Current = NewFrame.get();
1898 
1899   APValue CallResult;
1900   // Note that we cannot assert(CallResult.hasValue()) here since
1901   // Ret() above only sets the APValue if the curent frame doesn't
1902   // have a caller set.
1903   if (Interpret(S, CallResult)) {
1904     NewFrame.release(); // Frame was delete'd already.
1905     assert(S.Current == FrameBefore);
1906     return true;
1907   }
1908 
1909   // Interpreting the function failed somehow. Reset to
1910   // previous state.
1911   S.Current = FrameBefore;
1912   return false;
1913 }
1914 
1915 inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func) {
1916   assert(Func->hasThisPointer());
1917   assert(Func->isVirtual());
1918   size_t ThisOffset =
1919       Func->getArgSize() - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1920   Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1921 
1922   const CXXRecordDecl *DynamicDecl =
1923       ThisPtr.getDeclDesc()->getType()->getAsCXXRecordDecl();
1924   const auto *StaticDecl = cast<CXXRecordDecl>(Func->getParentDecl());
1925   const auto *InitialFunction = cast<CXXMethodDecl>(Func->getDecl());
1926   const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
1927       DynamicDecl, StaticDecl, InitialFunction);
1928 
1929   if (Overrider != InitialFunction) {
1930     // DR1872: An instantiated virtual constexpr function can't be called in a
1931     // constant expression (prior to C++20). We can still constant-fold such a
1932     // call.
1933     if (!S.getLangOpts().CPlusPlus20 && Overrider->isVirtual()) {
1934       const Expr *E = S.Current->getExpr(OpPC);
1935       S.CCEDiag(E, diag::note_constexpr_virtual_call) << E->getSourceRange();
1936     }
1937 
1938     Func = S.getContext().getOrCreateFunction(Overrider);
1939 
1940     const CXXRecordDecl *ThisFieldDecl =
1941         ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
1942     if (Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
1943       // If the function we call is further DOWN the hierarchy than the
1944       // FieldDesc of our pointer, just get the DeclDesc instead, which
1945       // is the furthest we might go up in the hierarchy.
1946       ThisPtr = ThisPtr.getDeclPtr();
1947     }
1948   }
1949 
1950   return Call(S, OpPC, Func);
1951 }
1952 
1953 inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func,
1954                    const CallExpr *CE) {
1955   auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);
1956 
1957   InterpFrame *FrameBefore = S.Current;
1958   S.Current = NewFrame.get();
1959 
1960   if (InterpretBuiltin(S, PC, Func, CE)) {
1961     NewFrame.release();
1962     return true;
1963   }
1964   S.Current = FrameBefore;
1965   return false;
1966 }
1967 
1968 inline bool CallPtr(InterpState &S, CodePtr OpPC) {
1969   const FunctionPointer &FuncPtr = S.Stk.pop<FunctionPointer>();
1970 
1971   const Function *F = FuncPtr.getFunction();
1972   if (!F || !F->isConstexpr())
1973     return false;
1974 
1975   if (F->isVirtual())
1976     return CallVirt(S, OpPC, F);
1977 
1978   return Call(S, OpPC, F);
1979 }
1980 
1981 inline bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func) {
1982   assert(Func);
1983   S.Stk.push<FunctionPointer>(Func);
1984   return true;
1985 }
1986 
1987 /// Just emit a diagnostic. The expression that caused emission of this
1988 /// op is not valid in a constant context.
1989 inline bool Invalid(InterpState &S, CodePtr OpPC) {
1990   const SourceLocation &Loc = S.Current->getLocation(OpPC);
1991   S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr)
1992       << S.Current->getRange(OpPC);
1993   return false;
1994 }
1995 
1996 /// Same here, but only for casts.
1997 inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind) {
1998   const SourceLocation &Loc = S.Current->getLocation(OpPC);
1999   S.FFDiag(Loc, diag::note_constexpr_invalid_cast)
2000       << static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
2001   return false;
2002 }
2003 
2004 inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC,
2005                            const DeclRefExpr *DR) {
2006   assert(DR);
2007   return CheckDeclRef(S, OpPC, DR);
2008 }
2009 
2010 template <PrimType Name, class T = typename PrimConv<Name>::T>
2011 inline bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E) {
2012   llvm::SmallVector<int64_t> ArrayIndices;
2013   for (size_t I = 0; I != E->getNumExpressions(); ++I)
2014     ArrayIndices.emplace_back(S.Stk.pop<int64_t>());
2015 
2016   int64_t Result;
2017   if (!InterpretOffsetOf(S, OpPC, E, ArrayIndices, Result))
2018     return false;
2019 
2020   S.Stk.push<T>(T::from(Result));
2021 
2022   return true;
2023 }
2024 
2025 //===----------------------------------------------------------------------===//
2026 // Read opcode arguments
2027 //===----------------------------------------------------------------------===//
2028 
2029 template <typename T> inline T ReadArg(InterpState &S, CodePtr &OpPC) {
2030   if constexpr (std::is_pointer<T>::value) {
2031     uint32_t ID = OpPC.read<uint32_t>();
2032     return reinterpret_cast<T>(S.P.getNativePointer(ID));
2033   } else {
2034     return OpPC.read<T>();
2035   }
2036 }
2037 
2038 template <> inline Floating ReadArg<Floating>(InterpState &S, CodePtr &OpPC) {
2039   Floating F = Floating::deserialize(*OpPC);
2040   OpPC += align(F.bytesToSerialize());
2041   return F;
2042 }
2043 
2044 } // namespace interp
2045 } // namespace clang
2046 
2047 #endif
2048