clang  14.0.0git
Interp.cpp
Go to the documentation of this file.
1 //===--- InterpState.cpp - 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  const auto &Src = S.Current->getSource(OpPC);
205  if (Ptr.isZero()) {
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  bool IsTemp = Ptr.isTemporary();
217 
218  S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
219 
220  if (IsTemp)
221  S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
222  else
223  S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
224 
225  return false;
226  }
227 
228  return true;
229 }
230 
231 bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
232  CheckSubobjectKind CSK) {
233  if (!Ptr.isZero())
234  return true;
235  const SourceInfo &Loc = S.Current->getSource(OpPC);
236  S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
237  return false;
238 }
239 
240 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
241  AccessKinds AK) {
242  if (!Ptr.isOnePastEnd())
243  return true;
244  const SourceInfo &Loc = S.Current->getSource(OpPC);
245  S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
246  return false;
247 }
248 
249 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
250  CheckSubobjectKind CSK) {
251  if (!Ptr.isElementPastEnd())
252  return true;
253  const SourceInfo &Loc = S.Current->getSource(OpPC);
254  S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
255  return false;
256 }
257 
258 bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
259  assert(Ptr.isLive() && "Pointer is not live");
260  if (!Ptr.isConst()) {
261  return true;
262  }
263 
264  const QualType Ty = Ptr.getType();
265  const SourceInfo &Loc = S.Current->getSource(OpPC);
266  S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
267  return false;
268 }
269 
270 bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
271  assert(Ptr.isLive() && "Pointer is not live");
272  if (!Ptr.isMutable()) {
273  return true;
274  }
275 
276  const SourceInfo &Loc = S.Current->getSource(OpPC);
277  const FieldDecl *Field = Ptr.getField();
278  S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
279  S.Note(Field->getLocation(), diag::note_declared_at);
280  return false;
281 }
282 
283 bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
284  if (!CheckLive(S, OpPC, Ptr, AK_Read))
285  return false;
286  if (!CheckExtern(S, OpPC, Ptr))
287  return false;
288  if (!CheckRange(S, OpPC, Ptr, AK_Read))
289  return false;
290  if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
291  return false;
292  if (!CheckActive(S, OpPC, Ptr, AK_Read))
293  return false;
294  if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
295  return false;
296  if (!CheckMutable(S, OpPC, Ptr))
297  return false;
298  return true;
299 }
300 
301 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
302  if (!CheckLive(S, OpPC, Ptr, AK_Assign))
303  return false;
304  if (!CheckExtern(S, OpPC, Ptr))
305  return false;
306  if (!CheckRange(S, OpPC, Ptr, AK_Assign))
307  return false;
308  if (!CheckGlobal(S, OpPC, Ptr))
309  return false;
310  if (!CheckConst(S, OpPC, Ptr))
311  return false;
312  return true;
313 }
314 
315 bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
316  if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
317  return false;
318  if (!CheckExtern(S, OpPC, Ptr))
319  return false;
320  if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
321  return false;
322  return true;
323 }
324 
325 bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
326  if (!CheckLive(S, OpPC, Ptr, AK_Assign))
327  return false;
328  if (!CheckRange(S, OpPC, Ptr, AK_Assign))
329  return false;
330  return true;
331 }
332 
334  const SourceLocation &Loc = S.Current->getLocation(OpPC);
335 
336  if (F->isVirtual()) {
337  if (!S.getLangOpts().CPlusPlus20) {
338  S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
339  return false;
340  }
341  }
342 
343  if (!F->isConstexpr()) {
344  if (S.getLangOpts().CPlusPlus11) {
345  const FunctionDecl *DiagDecl = F->getDecl();
346 
347  // If this function is not constexpr because it is an inherited
348  // non-constexpr constructor, diagnose that directly.
349  auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
350  if (CD && CD->isInheritingConstructor()) {
351  auto *Inherited = CD->getInheritedConstructor().getConstructor();
352  if (!Inherited->isConstexpr())
353  DiagDecl = CD = Inherited;
354  }
355 
356  // FIXME: If DiagDecl is an implicitly-declared special member function
357  // or an inheriting constructor, we should be much more explicit about why
358  // it's not constexpr.
359  if (CD && CD->isInheritingConstructor())
360  S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
361  << CD->getInheritedConstructor().getConstructor()->getParent();
362  else
363  S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
364  << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
365  S.Note(DiagDecl->getLocation(), diag::note_declared_at);
366  } else {
367  S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
368  }
369  return false;
370  }
371 
372  return true;
373 }
374 
375 bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
376  if (!This.isZero())
377  return true;
378 
379  const SourceInfo &Loc = S.Current->getSource(OpPC);
380 
381  bool IsImplicit = false;
382  if (auto *E = dyn_cast_or_null<CXXThisExpr>(Loc.asExpr()))
383  IsImplicit = E->isImplicit();
384 
385  if (S.getLangOpts().CPlusPlus11)
386  S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
387  else
388  S.FFDiag(Loc);
389 
390  return false;
391 }
392 
393 bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
394  if (!MD->isPure())
395  return true;
396  const SourceInfo &E = S.Current->getSource(OpPC);
397  S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
398  S.Note(MD->getLocation(), diag::note_declared_at);
399  return false;
400 }
401 bool Interpret(InterpState &S, APValue &Result) {
402  CodePtr PC = S.Current->getPC();
403 
404  for (;;) {
405  auto Op = PC.read<Opcode>();
406  CodePtr OpPC = PC;
407 
408  switch (Op) {
409 #define GET_INTERP
410 #include "Opcodes.inc"
411 #undef GET_INTERP
412  }
413  }
414 }
415 
416 } // namespace interp
417 } // namespace clang
clang::interp::Record::isUnion
bool isUnion() const
Checks if the record is a union.
Definition: Record.h:51
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:74
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
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:375
clang::QualType::isConstQualified
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:6487
clang::FunctionDecl::isConstexpr
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2284
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:673
clang::interp::Pointer::isMutable
bool isMutable() const
Checks if the field is mutable.
Definition: Pointer.h:238
clang::AK_MemberCall
@ AK_MemberCall
Definition: State.h:32
clang::FieldDecl
Represents a member of a struct/union/class.
Definition: Decl.h:2840
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:148
clang::interp::Pointer::getDeclDesc
Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition: Pointer.h:147
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:144
clang::interp::Record::Field::Offset
unsigned Offset
Definition: Record.h:28
clang::interp::Function::isConstexpr
bool isConstexpr() const
Checks if the function is valid to call in constexpr.
Definition: Function.h:103
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:233
clang::interp::Pointer
A pointer to a memory block, live or dead.
Definition: Pointer.h:39
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
Offset
unsigned Offset
Definition: Format.cpp:2381
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:1584
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:158
clang::interp::Pointer::isStaticTemporary
bool isStaticTemporary() const
Checks if the storage is a static temporary.
Definition: Pointer.h:235
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:277
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::interp::Pointer::isLive
bool isLive() const
Checks if the pointer is live.
Definition: Pointer.h:142
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
clang::interp::Descriptor::getType
QualType getType() const
Definition: Descriptor.cpp:245
clang::interp::Pointer::isConst
bool isConst() const
Checks if an object or a subfield is mutable.
Definition: Pointer.h:247
Expr.h
bool
#define bool
Definition: stdbool.h:15
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:240
clang::interp::Record::getNumFields
unsigned getNumFields()
Definition: Record.h:68
clang::interp::SourceInfo
Describes the statement/declaration an opcode was generated from.
Definition: Source.h:66
InterpStack.h
clang::interp::Pointer::getType
QualType getType() const
Returns the type of the innermost field.
Definition: Pointer.h:178
ExprCXX.h
ASTDiagnostic.h
clang::interp::Interpret
bool Interpret(InterpState &S, APValue &Result)
Interpreter entry point.
Definition: Interp.cpp:401
clang::interp::CheckPure
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
Definition: Interp.cpp:393
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:270
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:47
clang::FunctionDecl::isPure
bool isPure() const
Whether this virtual function is pure, i.e.
Definition: Decl.h:2191
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::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:135
clang::interp::This
bool This(InterpState &S, CodePtr OpPC)
Definition: Interp.h:829
clang::interp::Pointer::isActive
bool isActive() const
Checks if the object is active.
Definition: Pointer.h:242
clang::Builtin::ID
ID
Definition: Builtins.h:48
clang::interp::Pointer::getBase
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition: Pointer.h:151
clang
Definition: CalledOnceCheck.h:17
Function.h
clang::interp::Pointer::isExtern
bool isExtern() const
Checks if the storage is extern.
Definition: Pointer.h:229
clang::interp::Function
Bytecode function.
Definition: Function.h:59
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::interp::Pointer::getField
const FieldDecl * getField() const
Returns the field information.
Definition: Pointer.h:223
clang::interp::Pointer::isStatic
bool isStatic() const
Checks if the storage is static.
Definition: Pointer.h:231
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:44
clang::interp::Pointer::getDeclID
llvm::Optional< unsigned > getDeclID() const
Returns the declaration ID.
Definition: Pointer.h:252
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: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::Record
Structure/Class descriptor.
Definition: Record.h:23
clang::Decl::getLocation
SourceLocation getLocation() const
Definition: DeclBase.h:430
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:1857
clang::interp::Pointer::isUnknownSizeArray
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition: Pointer.h:210
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:1948
clang::interp::Pointer::isOnePastEnd
bool isOnePastEnd() const
Checks if the index is one past end.
Definition: Pointer.h:272