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