clang  16.0.0git
Interp.cpp
Go to the documentation of this file.
1 //===------- Interpcpp - 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 #include "Interp.h"
10 #include <limits>
11 #include <vector>
12 #include "Function.h"
13 #include "InterpFrame.h"
14 #include "InterpStack.h"
15 #include "Opcode.h"
16 #include "PrimType.h"
17 #include "Program.h"
18 #include "State.h"
19 #include "clang/AST/ASTContext.h"
22 #include "clang/AST/Expr.h"
23 #include "clang/AST/ExprCXX.h"
24 #include "llvm/ADT/APSInt.h"
25 
26 using namespace clang;
27 using namespace clang::interp;
28 
29 //===----------------------------------------------------------------------===//
30 // Ret
31 //===----------------------------------------------------------------------===//
32 
33 template <PrimType Name, class T = typename PrimConv<Name>::T>
34 static bool Ret(InterpState &S, CodePtr &PC, APValue &Result) {
35  S.CallStackDepth--;
36  const T &Ret = S.Stk.pop<T>();
37 
38  assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
39  if (!S.checkingPotentialConstantExpression())
40  S.Current->popArgs();
41 
42  if (InterpFrame *Caller = S.Current->Caller) {
43  PC = S.Current->getRetPC();
44  delete S.Current;
45  S.Current = Caller;
46  S.Stk.push<T>(Ret);
47  } else {
48  delete S.Current;
49  S.Current = nullptr;
50  if (!ReturnValue<T>(Ret, Result))
51  return false;
52  }
53  return true;
54 }
55 
56 static bool RetVoid(InterpState &S, CodePtr &PC, APValue &Result) {
57  S.CallStackDepth--;
58 
59  assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
60  if (!S.checkingPotentialConstantExpression())
61  S.Current->popArgs();
62 
63  if (InterpFrame *Caller = S.Current->Caller) {
64  PC = S.Current->getRetPC();
65  delete S.Current;
66  S.Current = Caller;
67  } else {
68  delete S.Current;
69  S.Current = nullptr;
70  }
71  return true;
72 }
73 
74 static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) {
75  llvm::report_fatal_error("Interpreter cannot return values");
76 }
77 
78 //===----------------------------------------------------------------------===//
79 // Jmp, Jt, Jf
80 //===----------------------------------------------------------------------===//
81 
82 static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
83  PC += Offset;
84  return true;
85 }
86 
87 static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
88  if (S.Stk.pop<bool>()) {
89  PC += Offset;
90  }
91  return true;
92 }
93 
94 static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
95  if (!S.Stk.pop<bool>()) {
96  PC += Offset;
97  }
98  return true;
99 }
100 
101 static bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
102  AccessKinds AK) {
103  if (Ptr.isInitialized())
104  return true;
105  if (!S.checkingPotentialConstantExpression()) {
106  const SourceInfo &Loc = S.Current->getSource(OpPC);
107  S.FFDiag(Loc, diag::note_constexpr_access_uninit) << AK << false;
108  }
109  return false;
110 }
111 
112 static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
113  AccessKinds AK) {
114  if (Ptr.isActive())
115  return true;
116 
117  // Get the inactive field descriptor.
118  const FieldDecl *InactiveField = Ptr.getField();
119 
120  // Walk up the pointer chain to find the union which is not active.
121  Pointer U = Ptr.getBase();
122  while (!U.isActive()) {
123  U = U.getBase();
124  }
125 
126  // Find the active field of the union.
127  Record *R = U.getRecord();
128  assert(R && R->isUnion() && "Not a union");
129  const FieldDecl *ActiveField = nullptr;
130  for (unsigned I = 0, N = R->getNumFields(); I < N; ++I) {
131  const Pointer &Field = U.atField(R->getField(I)->Offset);
132  if (Field.isActive()) {
133  ActiveField = Field.getField();
134  break;
135  }
136  }
137 
138  const SourceInfo &Loc = S.Current->getSource(OpPC);
139  S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
140  << AK << InactiveField << !ActiveField << ActiveField;
141  return false;
142 }
143 
144 static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
145  AccessKinds AK) {
146  if (auto ID = Ptr.getDeclID()) {
147  if (!Ptr.isStaticTemporary())
148  return true;
149 
150  if (Ptr.getDeclDesc()->getType().isConstQualified())
151  return true;
152 
153  if (S.P.getCurrentDecl() == ID)
154  return true;
155 
156  const SourceInfo &E = S.Current->getSource(OpPC);
157  S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
158  S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
159  return false;
160  }
161  return true;
162 }
163 
164 static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
165  if (auto ID = Ptr.getDeclID()) {
166  if (!Ptr.isStatic())
167  return true;
168 
169  if (S.P.getCurrentDecl() == ID)
170  return true;
171 
172  S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
173  return false;
174  }
175  return true;
176 }
177 
178 namespace clang {
179 namespace interp {
180 
181 bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
182  if (!Ptr.isExtern())
183  return true;
184 
185  if (!S.checkingPotentialConstantExpression()) {
186  auto *VD = Ptr.getDeclDesc()->asValueDecl();
187  const SourceInfo &Loc = S.Current->getSource(OpPC);
188  S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
189  S.Note(VD->getLocation(), diag::note_declared_at);
190  }
191  return false;
192 }
193 
194 bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
195  if (!Ptr.isUnknownSizeArray())
196  return true;
197  const SourceInfo &E = S.Current->getSource(OpPC);
198  S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
199  return false;
200 }
201 
202 bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
203  AccessKinds AK) {
204  if (Ptr.isZero()) {
205  const auto &Src = S.Current->getSource(OpPC);
206 
207  if (Ptr.isField())
208  S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
209  else
210  S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
211 
212  return false;
213  }
214 
215  if (!Ptr.isLive()) {
216  const auto &Src = S.Current->getSource(OpPC);
217  bool IsTemp = Ptr.isTemporary();
218 
219  S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
220 
221  if (IsTemp)
222  S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
223  else
224  S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
225 
226  return false;
227  }
228 
229  return true;
230 }
231 
232 bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
233  CheckSubobjectKind CSK) {
234  if (!Ptr.isZero())
235  return true;
236  const SourceInfo &Loc = S.Current->getSource(OpPC);
237  S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
238  return false;
239 }
240 
241 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
242  AccessKinds AK) {
243  if (!Ptr.isOnePastEnd())
244  return true;
245  const SourceInfo &Loc = S.Current->getSource(OpPC);
246  S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
247  return false;
248 }
249 
250 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
251  CheckSubobjectKind CSK) {
252  if (!Ptr.isElementPastEnd())
253  return true;
254  const SourceInfo &Loc = S.Current->getSource(OpPC);
255  S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
256  return false;
257 }
258 
259 bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
260  assert(Ptr.isLive() && "Pointer is not live");
261  if (!Ptr.isConst()) {
262  return true;
263  }
264 
265  const QualType Ty = Ptr.getType();
266  const SourceInfo &Loc = S.Current->getSource(OpPC);
267  S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
268  return false;
269 }
270 
271 bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
272  assert(Ptr.isLive() && "Pointer is not live");
273  if (!Ptr.isMutable()) {
274  return true;
275  }
276 
277  const SourceInfo &Loc = S.Current->getSource(OpPC);
278  const FieldDecl *Field = Ptr.getField();
279  S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
280  S.Note(Field->getLocation(), diag::note_declared_at);
281  return false;
282 }
283 
284 bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
285  if (!CheckLive(S, OpPC, Ptr, AK_Read))
286  return false;
287  if (!CheckExtern(S, OpPC, Ptr))
288  return false;
289  if (!CheckRange(S, OpPC, Ptr, AK_Read))
290  return false;
291  if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
292  return false;
293  if (!CheckActive(S, OpPC, Ptr, AK_Read))
294  return false;
295  if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
296  return false;
297  if (!CheckMutable(S, OpPC, Ptr))
298  return false;
299  return true;
300 }
301 
302 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
303  if (!CheckLive(S, OpPC, Ptr, AK_Assign))
304  return false;
305  if (!CheckExtern(S, OpPC, Ptr))
306  return false;
307  if (!CheckRange(S, OpPC, Ptr, AK_Assign))
308  return false;
309  if (!CheckGlobal(S, OpPC, Ptr))
310  return false;
311  if (!CheckConst(S, OpPC, Ptr))
312  return false;
313  return true;
314 }
315 
316 bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
317  if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
318  return false;
319  if (!CheckExtern(S, OpPC, Ptr))
320  return false;
321  if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
322  return false;
323  return true;
324 }
325 
326 bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
327  if (!CheckLive(S, OpPC, Ptr, AK_Assign))
328  return false;
329  if (!CheckRange(S, OpPC, Ptr, AK_Assign))
330  return false;
331  return true;
332 }
333 
335  const SourceLocation &Loc = S.Current->getLocation(OpPC);
336 
337  if (F->isVirtual()) {
338  if (!S.getLangOpts().CPlusPlus20) {
339  S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
340  return false;
341  }
342  }
343 
344  if (!F->isConstexpr()) {
345  if (S.getLangOpts().CPlusPlus11) {
346  const FunctionDecl *DiagDecl = F->getDecl();
347 
348  // If this function is not constexpr because it is an inherited
349  // non-constexpr constructor, diagnose that directly.
350  auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
351  if (CD && CD->isInheritingConstructor()) {
352  auto *Inherited = CD->getInheritedConstructor().getConstructor();
353  if (!Inherited->isConstexpr())
354  DiagDecl = CD = Inherited;
355  }
356 
357  // FIXME: If DiagDecl is an implicitly-declared special member function
358  // or an inheriting constructor, we should be much more explicit about why
359  // it's not constexpr.
360  if (CD && CD->isInheritingConstructor())
361  S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
362  << CD->getInheritedConstructor().getConstructor()->getParent();
363  else
364  S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
365  << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
366  S.Note(DiagDecl->getLocation(), diag::note_declared_at);
367  } else {
368  S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
369  }
370  return false;
371  }
372 
373  return true;
374 }
375 
376 bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
377  if (!This.isZero())
378  return true;
379 
380  const SourceInfo &Loc = S.Current->getSource(OpPC);
381 
382  bool IsImplicit = false;
383  if (auto *E = dyn_cast_or_null<CXXThisExpr>(Loc.asExpr()))
384  IsImplicit = E->isImplicit();
385 
386  if (S.getLangOpts().CPlusPlus11)
387  S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
388  else
389  S.FFDiag(Loc);
390 
391  return false;
392 }
393 
394 bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
395  if (!MD->isPure())
396  return true;
397  const SourceInfo &E = S.Current->getSource(OpPC);
398  S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
399  S.Note(MD->getLocation(), diag::note_declared_at);
400  return false;
401 }
402 
403 bool Interpret(InterpState &S, APValue &Result) {
404  // The current stack frame when we started Interpret().
405  // This is being used by the ops to determine wheter
406  // to return from this function and thus terminate
407  // interpretation.
408  const InterpFrame *StartFrame = S.Current;
409  assert(!S.Current->isRoot());
410  CodePtr PC = S.Current->getPC();
411 
412  // Empty program.
413  if (!PC)
414  return true;
415 
416  for (;;) {
417  auto Op = PC.read<Opcode>();
418  CodePtr OpPC = PC;
419 
420  switch (Op) {
421 #define GET_INTERP
422 #include "Opcodes.inc"
423 #undef GET_INTERP
424  }
425  }
426 }
427 
428 } // namespace interp
429 } // namespace clang
clang::interp::Record::isUnion
bool isUnion() const
Checks if the record is a union.
Definition: Record.h:54
clang::interp::SourceInfo::asExpr
const Expr * asExpr() const
Definition: Source.cpp:25
clang::AK_Read
@ AK_Read
Definition: State.h:27
clang::interp::Function::getDecl
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
Definition: Function.h:89
clang::interp::CheckCallable
bool CheckCallable(InterpState &S, CodePtr OpPC, Function *F)
Checks if a method can be called.
Definition: Interp.cpp:334
clang::CheckSubobjectKind
CheckSubobjectKind
Definition: State.h:40
Ret
static bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
Definition: Interp.cpp:34
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:376
clang::QualType::isConstQualified
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:6694
clang::FunctionDecl::isConstexpr
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2354
Opcode.h
CheckGlobal
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition: Interp.cpp:164
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:86
CXXInheritance.h
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:737
clang::interp::Pointer::isMutable
bool isMutable() const
Checks if the field is mutable.
Definition: Pointer.h:235
clang::AK_MemberCall
@ AK_MemberCall
Definition: State.h:32
clang::FieldDecl
Represents a member of a struct/union/class.
Definition: Decl.h:2930
Jt
static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:87
clang::interp::Record::getField
const Field * getField(const FieldDecl *FD) const
Returns a field.
Definition: Record.cpp:30
clang::interp::Pointer::getDeclLoc
SourceLocation getDeclLoc() const
Definition: Pointer.h:145
clang::interp::Pointer::getDeclDesc
Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition: Pointer.h:144
RetValue
static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result)
Definition: Interp.cpp:74
clang::interp::Pointer::isField
bool isField() const
Checks if the item is a field in an object.
Definition: Pointer.h:141
clang::interp::Record::Field::Offset
unsigned Offset
Definition: Record.h:29
clang::interp::Function::isConstexpr
bool isConstexpr() const
Checks if the function is valid to call in constexpr.
Definition: Function.h:125
Jmp
static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:82
clang::interp::Pointer::isTemporary
bool isTemporary() const
Checks if the storage is temporary.
Definition: Pointer.h:230
clang::interp::Pointer
A pointer to a memory block, live or dead.
Definition: Pointer.h:36
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:316
Offset
unsigned Offset
Definition: Format.cpp:2717
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::CSK_Field
@ CSK_Field
Definition: State.h:43
clang::Sema::getLangOpts
const LangOptions & getLangOpts() const
Definition: Sema.h:1630
U
clang::interp::InterpFrame
Frame storing local variables.
Definition: InterpFrame.h:29
clang::interp::CheckArray
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
Definition: Interp.cpp:194
clang::interp
Definition: ASTContext.h:155
clang::interp::Pointer::isStaticTemporary
bool isStaticTemporary() const
Checks if the storage is a static temporary.
Definition: Pointer.h:232
clang::interp::Opcode
Opcode
Definition: Opcode.h:21
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::Pointer::isElementPastEnd
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
Definition: Pointer.h:274
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:284
clang::interp::Pointer::isLive
bool isLive() const
Checks if the pointer is live.
Definition: Pointer.h:139
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:302
clang::interp::Descriptor::getType
QualType getType() const
Definition: Descriptor.cpp:251
clang::interp::Pointer::isConst
bool isConst() const
Checks if an object or a subfield is mutable.
Definition: Pointer.h:244
Expr.h
bool
#define bool
Definition: stdbool.h:20
ASTContext.h
CheckActive
static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:112
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:241
clang::interp::SourceInfo
Describes the statement/declaration an opcode was generated from.
Definition: Source.h:68
InterpStack.h
clang::interp::Pointer::getType
QualType getType() const
Returns the type of the innermost field.
Definition: Pointer.h:175
ExprCXX.h
ASTDiagnostic.h
clang::interp::Interpret
bool Interpret(InterpState &S, APValue &Result)
Interpreter entry point.
Definition: Interp.cpp:403
clang::interp::CheckPure
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
Definition: Interp.cpp:394
RetVoid
static bool RetVoid(InterpState &S, CodePtr &PC, APValue &Result)
Definition: Interp.cpp:56
clang::interp::Descriptor::asValueDecl
const ValueDecl * asValueDecl() const
Definition: Descriptor.h:115
clang::interp::CheckMutable
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
Definition: Interp.cpp:271
Interp.h
clang::interp::CodePtr::read
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
Definition: Source.h:49
clang::interp::Record::getNumFields
unsigned getNumFields() const
Definition: Record.h:71
clang::FunctionDecl::isPure
bool isPure() const
Whether this virtual function is pure, i.e.
Definition: Decl.h:2244
clang::interp::Pointer::isZero
bool isZero() const
Checks if the pointer is null.
Definition: Pointer.h:137
clang::interp::CodePtr
Pointer into the code segment.
Definition: Source.h:25
clang::AccessKinds
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
Definition: State.h:26
clang::interp::Pointer::isInitialized
bool isInitialized() const
Checks if an object was initialized.
Definition: Pointer.cpp:141
clang::interp::This
bool This(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1137
clang::interp::Pointer::isActive
bool isActive() const
Checks if the object is active.
Definition: Pointer.h:239
clang::Builtin::ID
ID
Definition: Builtins.h:52
clang::interp::Pointer::getBase
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition: Pointer.h:148
clang
Definition: CalledOnceCheck.h:17
Function.h
clang::interp::Pointer::isExtern
bool isExtern() const
Checks if the storage is extern.
Definition: Pointer.h:226
clang::interp::Function
Bytecode function.
Definition: Function.h:74
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:259
clang::interp::Pointer::getField
const FieldDecl * getField() const
Returns the field information.
Definition: Pointer.h:220
clang::interp::Pointer::isStatic
bool isStatic() const
Checks if the storage is static.
Definition: Pointer.h:228
State.h
Program.h
clang::AK_Assign
@ AK_Assign
Definition: State.h:29
clang::APValue
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition: APValue.h:122
clang::interp::Function::isVirtual
bool isVirtual() const
Checks if the function is virtual.
Definition: Function.cpp:42
clang::interp::Pointer::getDeclID
llvm::Optional< unsigned > getDeclID() const
Returns the declaration ID.
Definition: Pointer.h:249
Jf
static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:94
clang::interp::CheckInit
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
Definition: Interp.cpp:326
clang::interp::CheckNull
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
Definition: Interp.cpp:232
clang::interp::Record
Structure/Class descriptor.
Definition: Record.h:24
clang::Decl::getLocation
SourceLocation getLocation() const
Definition: DeclBase.h:432
CheckTemporary
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:144
clang::FunctionDecl
Represents a function declaration or definition.
Definition: Decl.h:1904
clang::interp::Pointer::isUnknownSizeArray
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition: Pointer.h:207
CheckInitialized
static bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:101
clang::CXXMethodDecl
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1983
clang::interp::Pointer::isOnePastEnd
bool isOnePastEnd() const
Checks if the index is one past end.
Definition: Pointer.h:269