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