clang  10.0.0git
Interp.h
Go to the documentation of this file.
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 <limits>
17 #include <vector>
18 #include "Function.h"
19 #include "InterpFrame.h"
20 #include "InterpStack.h"
21 #include "InterpState.h"
22 #include "Opcode.h"
23 #include "PrimType.h"
24 #include "Program.h"
25 #include "State.h"
26 #include "clang/AST/ASTContext.h"
29 #include "clang/AST/Expr.h"
30 #include "llvm/ADT/APFloat.h"
31 #include "llvm/ADT/APSInt.h"
32 #include "llvm/Support/Endian.h"
33 
34 namespace clang {
35 namespace interp {
36 
37 using APInt = llvm::APInt;
38 using APSInt = llvm::APSInt;
39 
40 /// Convers a value to an APValue.
41 template <typename T> bool ReturnValue(const T &V, APValue &R) {
42  R = V.toAPValue();
43  return true;
44 }
45 
46 /// Checks if the variable has externally defined storage.
47 bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
48 
49 /// Checks if the array is offsetable.
50 bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
51 
52 /// Checks if a pointer is live and accesible.
53 bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
54  AccessKinds AK);
55 /// Checks if a pointer is null.
56 bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
57  CheckSubobjectKind CSK);
58 
59 /// Checks if a pointer is in range.
60 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
61  AccessKinds AK);
62 
63 /// Checks if a field from which a pointer is going to be derived is valid.
64 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
65  CheckSubobjectKind CSK);
66 
67 /// Checks if a pointer points to const storage.
68 bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
69 
70 /// Checks if a pointer points to a mutable field.
71 bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
72 
73 /// Checks if a value can be loaded from a block.
74 bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
75 
76 /// Checks if a value can be stored in a block.
77 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
78 
79 /// Checks if a method can be invoked on an object.
80 bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
81 
82 /// Checks if a value can be initialized.
83 bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
84 
85 /// Checks if a method can be called.
86 bool CheckCallable(InterpState &S, CodePtr OpPC, Function *F);
87 
88 /// Checks the 'this' pointer.
89 bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This);
90 
91 /// Checks if a method is pure virtual.
92 bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD);
93 
94 template <typename T> inline bool IsTrue(const T &V) { return !V.isZero(); }
95 
96 //===----------------------------------------------------------------------===//
97 // Add, Sub, Mul
98 //===----------------------------------------------------------------------===//
99 
100 template <typename T, bool (*OpFW)(T, T, unsigned, T *),
101  template <typename U> class OpAP>
102 bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS,
103  const T &RHS) {
104  // Fast path - add the numbers with fixed width.
105  T Result;
106  if (!OpFW(LHS, RHS, Bits, &Result)) {
107  S.Stk.push<T>(Result);
108  return true;
109  }
110 
111  // If for some reason evaluation continues, use the truncated results.
112  S.Stk.push<T>(Result);
113 
114  // Slow path - compute the result using another bit of precision.
115  APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits));
116 
117  // Report undefined behaviour, stopping if required.
118  const Expr *E = S.Current->getExpr(OpPC);
119  QualType Type = E->getType();
121  auto Trunc = Value.trunc(Result.bitWidth()).toString(10);
122  auto Loc = E->getExprLoc();
123  S.report(Loc, diag::warn_integer_constant_overflow) << Trunc << Type;
124  return true;
125  } else {
126  S.CCEDiag(E, diag::note_constexpr_overflow) << Value << Type;
127  return S.noteUndefinedBehavior();
128  }
129 }
130 
131 template <PrimType Name, class T = typename PrimConv<Name>::T>
132 bool Add(InterpState &S, CodePtr OpPC) {
133  const T &RHS = S.Stk.pop<T>();
134  const T &LHS = S.Stk.pop<T>();
135  const unsigned Bits = RHS.bitWidth() + 1;
136  return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
137 }
138 
139 template <PrimType Name, class T = typename PrimConv<Name>::T>
140 bool Sub(InterpState &S, CodePtr OpPC) {
141  const T &RHS = S.Stk.pop<T>();
142  const T &LHS = S.Stk.pop<T>();
143  const unsigned Bits = RHS.bitWidth() + 1;
144  return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS);
145 }
146 
147 template <PrimType Name, class T = typename PrimConv<Name>::T>
148 bool Mul(InterpState &S, CodePtr OpPC) {
149  const T &RHS = S.Stk.pop<T>();
150  const T &LHS = S.Stk.pop<T>();
151  const unsigned Bits = RHS.bitWidth() * 2;
152  return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS);
153 }
154 
155 //===----------------------------------------------------------------------===//
156 // EQ, NE, GT, GE, LT, LE
157 //===----------------------------------------------------------------------===//
158 
159 using CompareFn = llvm::function_ref<bool(ComparisonCategoryResult)>;
160 
161 template <typename T>
163  using BoolT = PrimConv<PT_Bool>::T;
164  const T &RHS = S.Stk.pop<T>();
165  const T &LHS = S.Stk.pop<T>();
166  S.Stk.push<BoolT>(BoolT::from(Fn(LHS.compare(RHS))));
167  return true;
168 }
169 
170 template <typename T>
172  return CmpHelper<T>(S, OpPC, Fn);
173 }
174 
175 template <>
176 inline bool CmpHelper<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
177  using BoolT = PrimConv<PT_Bool>::T;
178  const Pointer &RHS = S.Stk.pop<Pointer>();
179  const Pointer &LHS = S.Stk.pop<Pointer>();
180 
181  if (!Pointer::hasSameBase(LHS, RHS)) {
182  const SourceInfo &Loc = S.Current->getSource(OpPC);
183  S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
184  return false;
185  } else {
186  unsigned VL = LHS.getByteOffset();
187  unsigned VR = RHS.getByteOffset();
188  S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
189  return true;
190  }
191 }
192 
193 template <>
195  using BoolT = PrimConv<PT_Bool>::T;
196  const Pointer &RHS = S.Stk.pop<Pointer>();
197  const Pointer &LHS = S.Stk.pop<Pointer>();
198 
199  if (LHS.isZero() && RHS.isZero()) {
200  S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Equal)));
201  return true;
202  }
203 
204  if (!Pointer::hasSameBase(LHS, RHS)) {
205  S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Unordered)));
206  return true;
207  } else {
208  unsigned VL = LHS.getByteOffset();
209  unsigned VR = RHS.getByteOffset();
210  S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
211  return true;
212  }
213 }
214 
215 template <PrimType Name, class T = typename PrimConv<Name>::T>
216 bool EQ(InterpState &S, CodePtr OpPC) {
217  return CmpHelperEQ<T>(S, OpPC, [](ComparisonCategoryResult R) {
219  });
220 }
221 
222 template <PrimType Name, class T = typename PrimConv<Name>::T>
223 bool NE(InterpState &S, CodePtr OpPC) {
224  return CmpHelperEQ<T>(S, OpPC, [](ComparisonCategoryResult R) {
226  });
227 }
228 
229 template <PrimType Name, class T = typename PrimConv<Name>::T>
230 bool LT(InterpState &S, CodePtr OpPC) {
231  return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
232  return R == ComparisonCategoryResult::Less;
233  });
234 }
235 
236 template <PrimType Name, class T = typename PrimConv<Name>::T>
237 bool LE(InterpState &S, CodePtr OpPC) {
238  return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
239  return R == ComparisonCategoryResult::Less ||
241  });
242 }
243 
244 template <PrimType Name, class T = typename PrimConv<Name>::T>
245 bool GT(InterpState &S, CodePtr OpPC) {
246  return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
248  });
249 }
250 
251 template <PrimType Name, class T = typename PrimConv<Name>::T>
252 bool GE(InterpState &S, CodePtr OpPC) {
253  return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
254  return R == ComparisonCategoryResult::Greater ||
256  });
257 }
258 
259 //===----------------------------------------------------------------------===//
260 // InRange
261 //===----------------------------------------------------------------------===//
262 
263 template <PrimType Name, class T = typename PrimConv<Name>::T>
264 bool InRange(InterpState &S, CodePtr OpPC) {
265  const T RHS = S.Stk.pop<T>();
266  const T LHS = S.Stk.pop<T>();
267  const T Value = S.Stk.pop<T>();
268 
269  S.Stk.push<bool>(LHS <= Value && Value <= RHS);
270  return true;
271 }
272 
273 //===----------------------------------------------------------------------===//
274 // Dup, Pop, Test
275 //===----------------------------------------------------------------------===//
276 
277 template <PrimType Name, class T = typename PrimConv<Name>::T>
278 bool Dup(InterpState &S, CodePtr OpPC) {
279  S.Stk.push<T>(S.Stk.peek<T>());
280  return true;
281 }
282 
283 template <PrimType Name, class T = typename PrimConv<Name>::T>
284 bool Pop(InterpState &S, CodePtr OpPC) {
285  S.Stk.pop<T>();
286  return true;
287 }
288 
289 //===----------------------------------------------------------------------===//
290 // Const
291 //===----------------------------------------------------------------------===//
292 
293 template <PrimType Name, class T = typename PrimConv<Name>::T>
294 bool Const(InterpState &S, CodePtr OpPC, const T &Arg) {
295  S.Stk.push<T>(Arg);
296  return true;
297 }
298 
299 //===----------------------------------------------------------------------===//
300 // Get/Set Local/Param/Global/This
301 //===----------------------------------------------------------------------===//
302 
303 template <PrimType Name, class T = typename PrimConv<Name>::T>
304 bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
305  S.Stk.push<T>(S.Current->getLocal<T>(I));
306  return true;
307 }
308 
309 template <PrimType Name, class T = typename PrimConv<Name>::T>
310 bool SetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
311  S.Current->setLocal<T>(I, S.Stk.pop<T>());
312  return true;
313 }
314 
315 template <PrimType Name, class T = typename PrimConv<Name>::T>
316 bool GetParam(InterpState &S, CodePtr OpPC, uint32_t I) {
318  return false;
319  }
320  S.Stk.push<T>(S.Current->getParam<T>(I));
321  return true;
322 }
323 
324 template <PrimType Name, class T = typename PrimConv<Name>::T>
325 bool SetParam(InterpState &S, CodePtr OpPC, uint32_t I) {
326  S.Current->setParam<T>(I, S.Stk.pop<T>());
327  return true;
328 }
329 
330 template <PrimType Name, class T = typename PrimConv<Name>::T>
331 bool GetField(InterpState &S, CodePtr OpPC, uint32_t I) {
332  const Pointer &Obj = S.Stk.peek<Pointer>();
333  if (!CheckNull(S, OpPC, Obj, CSK_Field))
334  return false;
335  if (!CheckRange(S, OpPC, Obj, CSK_Field))
336  return false;
337  const Pointer &Field = Obj.atField(I);
338  if (!CheckLoad(S, OpPC, Field))
339  return false;
340  S.Stk.push<T>(Field.deref<T>());
341  return true;
342 }
343 
344 template <PrimType Name, class T = typename PrimConv<Name>::T>
345 bool SetField(InterpState &S, CodePtr OpPC, uint32_t I) {
346  const T &Value = S.Stk.pop<T>();
347  const Pointer &Obj = S.Stk.peek<Pointer>();
348  if (!CheckNull(S, OpPC, Obj, CSK_Field))
349  return false;
350  if (!CheckRange(S, OpPC, Obj, CSK_Field))
351  return false;
352  const Pointer &Field = Obj.atField(I);
353  if (!CheckStore(S, OpPC, Field))
354  return false;
355  Field.deref<T>() = Value;
356  return true;
357 }
358 
359 template <PrimType Name, class T = typename PrimConv<Name>::T>
360 bool GetFieldPop(InterpState &S, CodePtr OpPC, uint32_t I) {
361  const Pointer &Obj = S.Stk.pop<Pointer>();
362  if (!CheckNull(S, OpPC, Obj, CSK_Field))
363  return false;
364  if (!CheckRange(S, OpPC, Obj, CSK_Field))
365  return false;
366  const Pointer &Field = Obj.atField(I);
367  if (!CheckLoad(S, OpPC, Field))
368  return false;
369  S.Stk.push<T>(Field.deref<T>());
370  return true;
371 }
372 
373 template <PrimType Name, class T = typename PrimConv<Name>::T>
374 bool GetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
376  return false;
377  const Pointer &This = S.Current->getThis();
378  if (!CheckThis(S, OpPC, This))
379  return false;
380  const Pointer &Field = This.atField(I);
381  if (!CheckLoad(S, OpPC, Field))
382  return false;
383  S.Stk.push<T>(Field.deref<T>());
384  return true;
385 }
386 
387 template <PrimType Name, class T = typename PrimConv<Name>::T>
388 bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
390  return false;
391  const T &Value = S.Stk.pop<T>();
392  const Pointer &This = S.Current->getThis();
393  if (!CheckThis(S, OpPC, This))
394  return false;
395  const Pointer &Field = This.atField(I);
396  if (!CheckStore(S, OpPC, Field))
397  return false;
398  Field.deref<T>() = Value;
399  return true;
400 }
401 
402 template <PrimType Name, class T = typename PrimConv<Name>::T>
403 bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
404  auto *B = S.P.getGlobal(I);
405  if (B->isExtern())
406  return false;
407  S.Stk.push<T>(B->deref<T>());
408  return true;
409 }
410 
411 template <PrimType Name, class T = typename PrimConv<Name>::T>
412 bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
413  // TODO: emit warning.
414  return false;
415 }
416 
417 template <PrimType Name, class T = typename PrimConv<Name>::T>
418 bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
419  S.P.getGlobal(I)->deref<T>() = S.Stk.pop<T>();
420  return true;
421 }
422 
423 template <PrimType Name, class T = typename PrimConv<Name>::T>
424 bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
426  return false;
427  const Pointer &This = S.Current->getThis();
428  if (!CheckThis(S, OpPC, This))
429  return false;
430  const Pointer &Field = This.atField(I);
431  Field.deref<T>() = S.Stk.pop<T>();
432  Field.initialize();
433  return true;
434 }
435 
436 template <PrimType Name, class T = typename PrimConv<Name>::T>
439  return false;
440  const Pointer &This = S.Current->getThis();
441  if (!CheckThis(S, OpPC, This))
442  return false;
443  const Pointer &Field = This.atField(F->Offset);
444  const auto &Value = S.Stk.pop<T>();
445  Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
446  Field.initialize();
447  return true;
448 }
449 
450 template <PrimType Name, class T = typename PrimConv<Name>::T>
451 bool InitThisFieldActive(InterpState &S, CodePtr OpPC, uint32_t I) {
453  return false;
454  const Pointer &This = S.Current->getThis();
455  if (!CheckThis(S, OpPC, This))
456  return false;
457  const Pointer &Field = This.atField(I);
458  Field.deref<T>() = S.Stk.pop<T>();
459  Field.activate();
460  Field.initialize();
461  return true;
462 }
463 
464 template <PrimType Name, class T = typename PrimConv<Name>::T>
465 bool InitField(InterpState &S, CodePtr OpPC, uint32_t I) {
466  const T &Value = S.Stk.pop<T>();
467  const Pointer &Field = S.Stk.pop<Pointer>().atField(I);
468  Field.deref<T>() = Value;
469  Field.activate();
470  Field.initialize();
471  return true;
472 }
473 
474 template <PrimType Name, class T = typename PrimConv<Name>::T>
475 bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
476  const T &Value = S.Stk.pop<T>();
477  const Pointer &Field = S.Stk.pop<Pointer>().atField(F->Offset);
478  Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
479  Field.activate();
480  Field.initialize();
481  return true;
482 }
483 
484 template <PrimType Name, class T = typename PrimConv<Name>::T>
485 bool InitFieldActive(InterpState &S, CodePtr OpPC, uint32_t I) {
486  const T &Value = S.Stk.pop<T>();
487  const Pointer &Ptr = S.Stk.pop<Pointer>();
488  const Pointer &Field = Ptr.atField(I);
489  Field.deref<T>() = Value;
490  Field.activate();
491  Field.initialize();
492  return true;
493 }
494 
495 //===----------------------------------------------------------------------===//
496 // GetPtr Local/Param/Global/Field/This
497 //===----------------------------------------------------------------------===//
498 
499 inline bool GetPtrLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
501  return true;
502 }
503 
504 inline bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t I) {
506  return false;
507  }
509  return true;
510 }
511 
512 inline bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
513  S.Stk.push<Pointer>(S.P.getPtrGlobal(I));
514  return true;
515 }
516 
517 inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
518  const Pointer &Ptr = S.Stk.pop<Pointer>();
519  if (!CheckNull(S, OpPC, Ptr, CSK_Field))
520  return false;
521  if (!CheckExtern(S, OpPC, Ptr))
522  return false;
523  if (!CheckRange(S, OpPC, Ptr, CSK_Field))
524  return false;
525  S.Stk.push<Pointer>(Ptr.atField(Off));
526  return true;
527 }
528 
529 inline bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off) {
531  return false;
532  const Pointer &This = S.Current->getThis();
533  if (!CheckThis(S, OpPC, This))
534  return false;
535  S.Stk.push<Pointer>(This.atField(Off));
536  return true;
537 }
538 
539 inline bool GetPtrActiveField(InterpState &S, CodePtr OpPC, uint32_t Off) {
540  const Pointer &Ptr = S.Stk.pop<Pointer>();
541  if (!CheckNull(S, OpPC, Ptr, CSK_Field))
542  return false;
543  if (!CheckRange(S, OpPC, Ptr, CSK_Field))
544  return false;
545  Pointer Field = Ptr.atField(Off);
546  Ptr.deactivate();
547  Field.activate();
548  S.Stk.push<Pointer>(std::move(Field));
549  return true;
550 }
551 
552 inline bool GetPtrActiveThisField(InterpState &S, CodePtr OpPC, uint32_t Off) {
554  return false;
555  const Pointer &This = S.Current->getThis();
556  if (!CheckThis(S, OpPC, This))
557  return false;
558  Pointer Field = This.atField(Off);
559  This.deactivate();
560  Field.activate();
561  S.Stk.push<Pointer>(std::move(Field));
562  return true;
563 }
564 
565 inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
566  const Pointer &Ptr = S.Stk.pop<Pointer>();
567  if (!CheckNull(S, OpPC, Ptr, CSK_Base))
568  return false;
569  S.Stk.push<Pointer>(Ptr.atField(Off));
570  return true;
571 }
572 
573 inline bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
575  return false;
576  const Pointer &This = S.Current->getThis();
577  if (!CheckThis(S, OpPC, This))
578  return false;
579  S.Stk.push<Pointer>(This.atField(Off));
580  return true;
581 }
582 
583 inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl,
584  const Pointer &Ptr) {
585  Pointer Base = Ptr;
586  while (Base.isBaseClass())
587  Base = Base.getBase();
588 
589  auto *Field = Base.getRecord()->getVirtualBase(Decl);
590  S.Stk.push<Pointer>(Base.atField(Field->Offset));
591  return true;
592 }
593 
594 inline bool GetPtrVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D) {
595  const Pointer &Ptr = S.Stk.pop<Pointer>();
596  if (!CheckNull(S, OpPC, Ptr, CSK_Base))
597  return false;
598  return VirtBaseHelper(S, OpPC, D, Ptr);
599 }
600 
602  const RecordDecl *D) {
604  return false;
605  const Pointer &This = S.Current->getThis();
606  if (!CheckThis(S, OpPC, This))
607  return false;
608  return VirtBaseHelper(S, OpPC, D, S.Current->getThis());
609 }
610 
611 //===----------------------------------------------------------------------===//
612 // Load, Store, Init
613 //===----------------------------------------------------------------------===//
614 
615 template <PrimType Name, class T = typename PrimConv<Name>::T>
616 bool Load(InterpState &S, CodePtr OpPC) {
617  const Pointer &Ptr = S.Stk.peek<Pointer>();
618  if (!CheckLoad(S, OpPC, Ptr))
619  return false;
620  S.Stk.push<T>(Ptr.deref<T>());
621  return true;
622 }
623 
624 template <PrimType Name, class T = typename PrimConv<Name>::T>
625 bool LoadPop(InterpState &S, CodePtr OpPC) {
626  const Pointer &Ptr = S.Stk.pop<Pointer>();
627  if (!CheckLoad(S, OpPC, Ptr))
628  return false;
629  S.Stk.push<T>(Ptr.deref<T>());
630  return true;
631 }
632 
633 template <PrimType Name, class T = typename PrimConv<Name>::T>
634 bool Store(InterpState &S, CodePtr OpPC) {
635  const T &Value = S.Stk.pop<T>();
636  const Pointer &Ptr = S.Stk.peek<Pointer>();
637  if (!CheckStore(S, OpPC, Ptr))
638  return false;
639  Ptr.deref<T>() = Value;
640  return true;
641 }
642 
643 template <PrimType Name, class T = typename PrimConv<Name>::T>
644 bool StorePop(InterpState &S, CodePtr OpPC) {
645  const T &Value = S.Stk.pop<T>();
646  const Pointer &Ptr = S.Stk.pop<Pointer>();
647  if (!CheckStore(S, OpPC, Ptr))
648  return false;
649  Ptr.deref<T>() = Value;
650  return true;
651 }
652 
653 template <PrimType Name, class T = typename PrimConv<Name>::T>
655  const T &Value = S.Stk.pop<T>();
656  const Pointer &Ptr = S.Stk.peek<Pointer>();
657  if (!CheckStore(S, OpPC, Ptr))
658  return false;
659  if (auto *FD = Ptr.getField()) {
660  Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getCtx()));
661  } else {
662  Ptr.deref<T>() = Value;
663  }
664  return true;
665 }
666 
667 template <PrimType Name, class T = typename PrimConv<Name>::T>
669  const T &Value = S.Stk.pop<T>();
670  const Pointer &Ptr = S.Stk.pop<Pointer>();
671  if (!CheckStore(S, OpPC, Ptr))
672  return false;
673  if (auto *FD = Ptr.getField()) {
674  Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getCtx()));
675  } else {
676  Ptr.deref<T>() = Value;
677  }
678  return true;
679 }
680 
681 template <PrimType Name, class T = typename PrimConv<Name>::T>
682 bool InitPop(InterpState &S, CodePtr OpPC) {
683  const T &Value = S.Stk.pop<T>();
684  const Pointer &Ptr = S.Stk.pop<Pointer>();
685  if (!CheckInit(S, OpPC, Ptr))
686  return false;
687  Ptr.initialize();
688  new (&Ptr.deref<T>()) T(Value);
689  return true;
690 }
691 
692 template <PrimType Name, class T = typename PrimConv<Name>::T>
693 bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx) {
694  const T &Value = S.Stk.pop<T>();
695  const Pointer &Ptr = S.Stk.peek<Pointer>().atIndex(Idx);
696  if (!CheckInit(S, OpPC, Ptr))
697  return false;
698  Ptr.initialize();
699  new (&Ptr.deref<T>()) T(Value);
700  return true;
701 }
702 
703 template <PrimType Name, class T = typename PrimConv<Name>::T>
704 bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) {
705  const T &Value = S.Stk.pop<T>();
706  const Pointer &Ptr = S.Stk.pop<Pointer>().atIndex(Idx);
707  if (!CheckInit(S, OpPC, Ptr))
708  return false;
709  Ptr.initialize();
710  new (&Ptr.deref<T>()) T(Value);
711  return true;
712 }
713 
714 //===----------------------------------------------------------------------===//
715 // AddOffset, SubOffset
716 //===----------------------------------------------------------------------===//
717 
718 template <class T, bool Add> bool OffsetHelper(InterpState &S, CodePtr OpPC) {
719  // Fetch the pointer and the offset.
720  const T &Offset = S.Stk.pop<T>();
721  const Pointer &Ptr = S.Stk.pop<Pointer>();
722  if (!CheckNull(S, OpPC, Ptr, CSK_ArrayIndex))
723  return false;
724  if (!CheckRange(S, OpPC, Ptr, CSK_ArrayToPointer))
725  return false;
726 
727  // Get a version of the index comparable to the type.
728  T Index = T::from(Ptr.getIndex(), Offset.bitWidth());
729  // A zero offset does not change the pointer, but in the case of an array
730  // it has to be adjusted to point to the first element instead of the array.
731  if (Offset.isZero()) {
732  S.Stk.push<Pointer>(Index.isZero() ? Ptr.atIndex(0) : Ptr);
733  return true;
734  }
735  // Arrays of unknown bounds cannot have pointers into them.
736  if (!CheckArray(S, OpPC, Ptr))
737  return false;
738 
739  // Compute the largest index into the array.
740  unsigned MaxIndex = Ptr.getNumElems();
741 
742  // Helper to report an invalid offset, computed as APSInt.
743  auto InvalidOffset = [&]() {
744  const unsigned Bits = Offset.bitWidth();
745  APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), false);
746  APSInt APIndex(Index.toAPSInt().extend(Bits + 2), false);
747  APSInt NewIndex = Add ? (APIndex + APOffset) : (APIndex - APOffset);
748  S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
749  << NewIndex
750  << /*array*/ static_cast<int>(!Ptr.inArray())
751  << static_cast<unsigned>(MaxIndex);
752  return false;
753  };
754 
755  // If the new offset would be negative, bail out.
756  if (Add && Offset.isNegative() && (Offset.isMin() || -Offset > Index))
757  return InvalidOffset();
758  if (!Add && Offset.isPositive() && Index < Offset)
759  return InvalidOffset();
760 
761  // If the new offset would be out of bounds, bail out.
762  unsigned MaxOffset = MaxIndex - Ptr.getIndex();
763  if (Add && Offset.isPositive() && Offset > MaxOffset)
764  return InvalidOffset();
765  if (!Add && Offset.isNegative() && (Offset.isMin() || -Offset > MaxOffset))
766  return InvalidOffset();
767 
768  // Offset is valid - compute it on unsigned.
769  int64_t WideIndex = static_cast<int64_t>(Index);
770  int64_t WideOffset = static_cast<int64_t>(Offset);
771  int64_t Result = Add ? (WideIndex + WideOffset) : (WideIndex - WideOffset);
772  S.Stk.push<Pointer>(Ptr.atIndex(static_cast<unsigned>(Result)));
773  return true;
774 }
775 
776 template <PrimType Name, class T = typename PrimConv<Name>::T>
777 bool AddOffset(InterpState &S, CodePtr OpPC) {
778  return OffsetHelper<T, true>(S, OpPC);
779 }
780 
781 template <PrimType Name, class T = typename PrimConv<Name>::T>
782 bool SubOffset(InterpState &S, CodePtr OpPC) {
783  return OffsetHelper<T, false>(S, OpPC);
784 }
785 
786 
787 //===----------------------------------------------------------------------===//
788 // Destroy
789 //===----------------------------------------------------------------------===//
790 
791 inline bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I) {
792  S.Current->destroy(I);
793  return true;
794 }
795 
796 //===----------------------------------------------------------------------===//
797 // Cast, CastFP
798 //===----------------------------------------------------------------------===//
799 
800 template <PrimType TIn, PrimType TOut> bool Cast(InterpState &S, CodePtr OpPC) {
801  using T = typename PrimConv<TIn>::T;
802  using U = typename PrimConv<TOut>::T;
803  S.Stk.push<U>(U::from(S.Stk.pop<T>()));
804  return true;
805 }
806 
807 //===----------------------------------------------------------------------===//
808 // Zero, Nullptr
809 //===----------------------------------------------------------------------===//
810 
811 template <PrimType Name, class T = typename PrimConv<Name>::T>
812 bool Zero(InterpState &S, CodePtr OpPC) {
813  S.Stk.push<T>(T::zero());
814  return true;
815 }
816 
817 template <PrimType Name, class T = typename PrimConv<Name>::T>
818 inline bool Null(InterpState &S, CodePtr OpPC) {
819  S.Stk.push<T>();
820  return true;
821 }
822 
823 //===----------------------------------------------------------------------===//
824 // This, ImplicitThis
825 //===----------------------------------------------------------------------===//
826 
827 inline bool This(InterpState &S, CodePtr OpPC) {
828  // Cannot read 'this' in this mode.
830  return false;
831  }
832 
833  const Pointer &This = S.Current->getThis();
834  if (!CheckThis(S, OpPC, This))
835  return false;
836 
837  S.Stk.push<Pointer>(This);
838  return true;
839 }
840 
841 //===----------------------------------------------------------------------===//
842 // Shr, Shl
843 //===----------------------------------------------------------------------===//
844 
845 template <PrimType TR, PrimType TL, class T = typename PrimConv<TR>::T>
846 unsigned Trunc(InterpState &S, CodePtr OpPC, unsigned Bits, const T &V) {
847  // C++11 [expr.shift]p1: Shift width must be less than the bit width of
848  // the shifted type.
849  if (Bits > 1 && V >= T::from(Bits, V.bitWidth())) {
850  const Expr *E = S.Current->getExpr(OpPC);
851  const APSInt Val = V.toAPSInt();
852  QualType Ty = E->getType();
853  S.CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty << Bits;
854  return Bits;
855  } else {
856  return static_cast<unsigned>(V);
857  }
858 }
859 
860 template <PrimType TL, PrimType TR, typename T = typename PrimConv<TL>::T>
861 inline bool ShiftRight(InterpState &S, CodePtr OpPC, const T &V, unsigned RHS) {
862  if (RHS >= V.bitWidth()) {
863  S.Stk.push<T>(T::from(0, V.bitWidth()));
864  } else {
865  S.Stk.push<T>(T::from(V >> RHS, V.bitWidth()));
866  }
867  return true;
868 }
869 
870 template <PrimType TL, PrimType TR, typename T = typename PrimConv<TL>::T>
871 inline bool ShiftLeft(InterpState &S, CodePtr OpPC, const T &V, unsigned RHS) {
872  if (V.isSigned() && !S.getLangOpts().CPlusPlus2a) {
873  // C++11 [expr.shift]p2: A signed left shift must have a non-negative
874  // operand, and must not overflow the corresponding unsigned type.
875  // C++2a [expr.shift]p2: E1 << E2 is the unique value congruent to
876  // E1 x 2^E2 module 2^N.
877  if (V.isNegative()) {
878  const Expr *E = S.Current->getExpr(OpPC);
879  S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << V.toAPSInt();
880  } else if (V.countLeadingZeros() < RHS) {
881  S.CCEDiag(S.Current->getExpr(OpPC), diag::note_constexpr_lshift_discards);
882  }
883  }
884 
885  if (V.bitWidth() == 1) {
886  S.Stk.push<T>(V);
887  } else if (RHS >= V.bitWidth()) {
888  S.Stk.push<T>(T::from(0, V.bitWidth()));
889  } else {
890  S.Stk.push<T>(T::from(V.toUnsigned() << RHS, V.bitWidth()));
891  }
892  return true;
893 }
894 
895 template <PrimType TL, PrimType TR>
896 inline bool Shr(InterpState &S, CodePtr OpPC) {
897  const auto &RHS = S.Stk.pop<typename PrimConv<TR>::T>();
898  const auto &LHS = S.Stk.pop<typename PrimConv<TL>::T>();
899  const unsigned Bits = LHS.bitWidth();
900 
901  if (RHS.isSigned() && RHS.isNegative()) {
902  const SourceInfo &Loc = S.Current->getSource(OpPC);
903  S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
904  return ShiftLeft<TL, TR>(S, OpPC, LHS, Trunc<TR, TL>(S, OpPC, Bits, -RHS));
905  } else {
906  return ShiftRight<TL, TR>(S, OpPC, LHS, Trunc<TR, TL>(S, OpPC, Bits, RHS));
907  }
908 }
909 
910 template <PrimType TL, PrimType TR>
911 inline bool Shl(InterpState &S, CodePtr OpPC) {
912  const auto &RHS = S.Stk.pop<typename PrimConv<TR>::T>();
913  const auto &LHS = S.Stk.pop<typename PrimConv<TL>::T>();
914  const unsigned Bits = LHS.bitWidth();
915 
916  if (RHS.isSigned() && RHS.isNegative()) {
917  const SourceInfo &Loc = S.Current->getSource(OpPC);
918  S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
919  return ShiftRight<TL, TR>(S, OpPC, LHS, Trunc<TR, TL>(S, OpPC, Bits, -RHS));
920  } else {
921  return ShiftLeft<TL, TR>(S, OpPC, LHS, Trunc<TR, TL>(S, OpPC, Bits, RHS));
922  }
923 }
924 
925 //===----------------------------------------------------------------------===//
926 // NoRet
927 //===----------------------------------------------------------------------===//
928 
929 inline bool NoRet(InterpState &S, CodePtr OpPC) {
930  SourceLocation EndLoc = S.Current->getCallee()->getEndLoc();
931  S.FFDiag(EndLoc, diag::note_constexpr_no_return);
932  return false;
933 }
934 
935 //===----------------------------------------------------------------------===//
936 // NarrowPtr, ExpandPtr
937 //===----------------------------------------------------------------------===//
938 
939 inline bool NarrowPtr(InterpState &S, CodePtr OpPC) {
940  const Pointer &Ptr = S.Stk.pop<Pointer>();
941  S.Stk.push<Pointer>(Ptr.narrow());
942  return true;
943 }
944 
945 inline bool ExpandPtr(InterpState &S, CodePtr OpPC) {
946  const Pointer &Ptr = S.Stk.pop<Pointer>();
947  S.Stk.push<Pointer>(Ptr.expand());
948  return true;
949 }
950 
951 /// Interpreter entry point.
952 bool Interpret(InterpState &S, APValue &Result);
953 
954 } // namespace interp
955 } // namespace clang
956 
957 #endif
bool Mul(InterpState &S, CodePtr OpPC)
Definition: Interp.h:148
Defines the clang::ASTContext interface.
bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a method can be invoked on an object.
Definition: Interp.cpp:315
bool Cast(InterpState &S, CodePtr OpPC)
Definition: Interp.h:800
A (possibly-)qualified type.
Definition: Type.h:654
Pointer getParamPointer(unsigned Offset)
Returns a pointer to an argument - lazily creates a block.
bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:424
InterpFrame * Current
The current frame.
Definition: InterpState.h:104
Mapping from primitive types to their representation.
Definition: PrimType.h:41
void initialize() const
Initializes a field.
Definition: Pointer.cpp:154
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
Definition: Interp.cpp:231
DiagnosticBuilder report(SourceLocation Loc, diag::kind DiagId)
Directly reports a diagnostic message.
Definition: State.cpp:75
Pointer into the code segment.
Definition: Source.h:25
bool SetParam(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:325
bool StoreBitFieldPop(InterpState &S, CodePtr OpPC)
Definition: Interp.h:668
bool Pop(InterpState &S, CodePtr OpPC)
Definition: Interp.h:284
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
Definition: Interp.cpp:393
void push(Tys &&... Args)
Constructs a value in place on the top of the stack.
Definition: InterpStack.h:30
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:88
Pointer getLocalPointer(unsigned Offset)
Returns a pointer to a local variables.
The base class of the type hierarchy.
Definition: Type.h:1450
bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:418
SourceLocation getEndLoc() const LLVM_READONLY
Definition: DeclBase.h:425
void activate() const
Activats a field.
Definition: Pointer.cpp:177
bool ReturnValue(const T &V, APValue &R)
Convers a value to an APValue.
Definition: Interp.h:41
unsigned Trunc(InterpState &S, CodePtr OpPC, unsigned Bits, const T &V)
Definition: Interp.h:846
bool This(InterpState &S, CodePtr OpPC)
Definition: Interp.h:827
bool StoreBitField(InterpState &S, CodePtr OpPC)
Definition: Interp.h:654
Describes the statement/declaration an opcode was generated from.
Definition: Source.h:81
bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl, const Pointer &Ptr)
Definition: Interp.h:583
bool InitFieldActive(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:485
bool InitPop(InterpState &S, CodePtr OpPC)
Definition: Interp.h:682
Represents a struct/union/class.
Definition: Decl.h:3748
A pointer to a memory block, live or dead.
Definition: Pointer.h:39
const T & getLocal(unsigned Offset)
Returns the value of a local variable.
Definition: InterpFrame.h:66
bool CmpHelperEQ< Pointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
Definition: Interp.h:194
bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F)
Definition: Interp.h:475
bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F)
Definition: Interp.h:437
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
bool Interpret(InterpState &S, APValue &Result)
Interpreter entry point.
Definition: Interp.cpp:401
bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn)
Definition: Interp.h:171
bool AddOffset(InterpState &S, CodePtr OpPC)
Definition: Interp.h:777
T pop()
Returns the value from the top of the stack and removes it.
Definition: InterpStack.h:35
InterpStack & Stk
Temporary stack.
Definition: InterpState.h:100
bool Zero(InterpState &S, CodePtr OpPC)
Definition: Interp.h:812
bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D)
Definition: Interp.h:601
Pointer getPtrGlobal(unsigned Idx)
Returns a pointer to a global.
Definition: Program.cpp:82
void setLocal(unsigned Offset, const T &Value)
Mutates a local variable.
Definition: InterpFrame.h:71
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
Definition: State.h:26
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
void destroy(unsigned Idx)
Invokes the destructors for a scope.
Definition: InterpFrame.cpp:45
ASTContext & getCtx() const override
Definition: InterpState.h:53
bool IsTrue(const T &V)
Definition: Interp.h:94
bool GE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:252
bool GetPtrVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D)
Definition: Interp.h:594
bool GetPtrActiveThisField(InterpState &S, CodePtr OpPC, uint32_t Off)
Definition: Interp.h:552
bool noteUndefinedBehavior() override
Definition: InterpState.h:65
unsigned getBitWidthValue(const ASTContext &Ctx) const
Definition: Decl.cpp:4031
static bool hasSameBase(const Pointer &A, const Pointer &B)
Checks if two pointers are comparable.
Definition: Pointer.cpp:187
bool Const(InterpState &S, CodePtr OpPC, const T &Arg)
Definition: Interp.h:294
bool GetThisField(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:374
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
Definition: Interp.cpp:181
bool InitThisFieldActive(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:451
unsigned getByteOffset() const
Returns the byte offset from the start.
Definition: Pointer.h:255
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accesible.
Definition: Interp.cpp:202
bool OffsetHelper(InterpState &S, CodePtr OpPC)
Definition: Interp.h:718
bool NoRet(InterpState &S, CodePtr OpPC)
Definition: Interp.h:929
unsigned Offset
Definition: Format.cpp:1827
bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:388
bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:791
This represents one expression.
Definition: Expr.h:108
bool GetPtrLocal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:499
bool GetPtrActiveField(InterpState &S, CodePtr OpPC, uint32_t Off)
Definition: Interp.h:539
#define V(N, I)
Definition: ASTContext.h:2941
llvm::function_ref< bool(ComparisonCategoryResult)> CompareFn
Definition: Interp.h:159
llvm::APSInt APSInt
Definition: Integral.h:28
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
Definition: Interp.cpp:194
bool CmpHelper(InterpState &S, CodePtr OpPC, CompareFn Fn)
Definition: Interp.h:162
#define bool
Definition: stdbool.h:15
void deactivate() const
Deactivates an entire strurcutre.
Definition: Pointer.cpp:183
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
Definition: Pointer.h:112
Block * getGlobal(unsigned Idx)
Returns the value of a global.
Definition: Program.h:54
QualType getType() const
Definition: Expr.h:137
virtual SourceInfo getSource(CodePtr PC) const
Map a location to a source.
bool Shl(InterpState &S, CodePtr OpPC)
Definition: Interp.h:911
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Definition: State.cpp:20
bool GetParam(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:316
bool checkingForUndefinedBehavior() const override
Definition: InterpState.h:56
unsigned getNumElems() const
Returns the number of elements.
Definition: Pointer.h:260
bool SetLocal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:310
bool SubOffset(InterpState &S, CodePtr OpPC)
Definition: Interp.h:782
bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx)
Definition: Interp.h:704
bool ExpandPtr(InterpState &S, CodePtr OpPC)
Definition: Interp.h:945
Pointer narrow() const
Restricts the scope of an array element pointer.
Definition: Pointer.h:76
Encodes a location in the source.
bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off)
Definition: Interp.h:573
llvm::APSInt APSInt
bool CmpHelper< Pointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
Definition: Interp.h:176
bool InRange(InterpState &S, CodePtr OpPC)
Definition: Interp.h:264
bool LoadPop(InterpState &S, CodePtr OpPC)
Definition: Interp.h:625
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1931
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be stored in a block.
Definition: Interp.cpp:301
Bytecode function.
Definition: Function.h:59
bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:304
llvm::APInt APInt
Definition: Integral.h:27
bool isBaseClass() const
Checks if a structure is a base class.
Definition: Pointer.h:244
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
Definition: Interp.cpp:258
const Expr * getExpr(CodePtr PC) const
bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx)
Definition: Interp.h:693
bool ShiftLeft(InterpState &S, CodePtr OpPC, const T &V, unsigned RHS)
Definition: Interp.h:871
bool Shr(InterpState &S, CodePtr OpPC)
Definition: Interp.h:896
bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off)
Definition: Interp.h:565
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
Definition: Interp.cpp:270
ComparisonCategoryResult Compare(const T &X, const T &Y)
Helper to compare two comparable types.
Definition: Integral.h:32
Dataflow Directional Tag Classes.
bool GT(InterpState &S, CodePtr OpPC)
Definition: Interp.h:245
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
Definition: Interp.cpp:240
const T & getParam(unsigned Offset)
Returns the value of an argument.
Definition: InterpFrame.h:79
bool NE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:223
bool CheckCallable(InterpState &S, CodePtr OpPC, Function *F)
Checks if a method can be called.
Definition: Interp.cpp:333
bool Dup(InterpState &S, CodePtr OpPC)
Definition: Interp.h:278
const FunctionDecl * getCallee() const
Returns the caller.
bool InitField(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:465
Describes a record field.
Definition: Record.h:26
T & deref() const
Dereferences the pointer, if it&#39;s live.
Definition: Pointer.h:280
Interpreter context.
Definition: InterpState.h:34
Record * getRecord() const
Returns the record descriptor of a class.
Definition: Pointer.h:221
void setParam(unsigned Offset, const T &Value)
Mutates a local copy of a parameter.
Definition: InterpFrame.h:89
Pointer atField(unsigned Off) const
Creates a pointer to a field.
Definition: Pointer.h:70
bool NarrowPtr(InterpState &S, CodePtr OpPC)
Definition: Interp.h:939
Program & P
Reference to the module containing all bytecode.
Definition: InterpState.h:98
bool Store(InterpState &S, CodePtr OpPC)
Definition: Interp.h:634
const LangOptions & getLangOpts() const
Definition: State.cpp:115
bool SetField(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:345
const Pointer & getThis() const
Returns the &#39;this&#39; pointer.
Definition: InterpFrame.h:97
bool isZero() const
Checks if the pointer is null.
Definition: Pointer.h:140
bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off)
Definition: Interp.h:517
T & deref()
Returns a view over the data.
Definition: Block.h:68
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat]...
Definition: APValue.h:115
bool ShiftRight(InterpState &S, CodePtr OpPC, const T &V, unsigned RHS)
Definition: Interp.h:861
const FieldDecl * Decl
Definition: Record.h:27
OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation does not produce a C++11 core constant expression.
Definition: State.cpp:41
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks the &#39;this&#39; pointer.
Definition: Interp.cpp:375
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be loaded from a block.
Definition: Interp.cpp:283
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
Definition: Interp.cpp:325
bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:504
bool LE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:237
bool Add(InterpState &S, CodePtr OpPC)
Definition: Interp.h:132
bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS, const T &RHS)
Definition: Interp.h:102
bool GetField(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:331
bool checkingPotentialConstantExpression() const override
Definition: InterpState.h:62
bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off)
Definition: Interp.h:529
bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:512
bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:403
CheckSubobjectKind
Definition: State.h:40
bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:412
bool Null(InterpState &S, CodePtr OpPC)
Definition: Interp.h:818
bool Load(InterpState &S, CodePtr OpPC)
Definition: Interp.h:616
bool StorePop(InterpState &S, CodePtr OpPC)
Definition: Interp.h:644
const Base * getVirtualBase(const RecordDecl *RD) const
Returns a virtual base descriptor.
Definition: Record.cpp:42
bool LT(InterpState &S, CodePtr OpPC)
Definition: Interp.h:230
T & peek()
Returns a reference to the value on the top of the stack.
Definition: InterpStack.h:51
bool Sub(InterpState &S, CodePtr OpPC)
Definition: Interp.h:140
bool EQ(InterpState &S, CodePtr OpPC)
Definition: Interp.h:216
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition: Pointer.h:151
bool GetFieldPop(InterpState &S, CodePtr OpPC, uint32_t I)
Definition: Interp.h:360