clang 18.0.0git
Interp.cpp
Go to the documentation of this file.
1//===------- Interp.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"
22#include "clang/AST/Expr.h"
23#include "clang/AST/ExprCXX.h"
24#include "llvm/ADT/APSInt.h"
25
26using namespace clang;
27using namespace clang::interp;
28
29static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) {
30 llvm::report_fatal_error("Interpreter cannot return values");
31}
32
33//===----------------------------------------------------------------------===//
34// Jmp, Jt, Jf
35//===----------------------------------------------------------------------===//
36
37static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
38 PC += Offset;
39 return true;
40}
41
42static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
43 if (S.Stk.pop<bool>()) {
44 PC += Offset;
45 }
46 return true;
47}
48
49static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
50 if (!S.Stk.pop<bool>()) {
51 PC += Offset;
52 }
53 return true;
54}
55
56static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
57 AccessKinds AK) {
58 if (Ptr.isActive())
59 return true;
60
61 // Get the inactive field descriptor.
62 const FieldDecl *InactiveField = Ptr.getField();
63
64 // Walk up the pointer chain to find the union which is not active.
65 Pointer U = Ptr.getBase();
66 while (!U.isActive()) {
67 U = U.getBase();
68 }
69
70 // Find the active field of the union.
71 const Record *R = U.getRecord();
72 assert(R && R->isUnion() && "Not a union");
73 const FieldDecl *ActiveField = nullptr;
74 for (unsigned I = 0, N = R->getNumFields(); I < N; ++I) {
75 const Pointer &Field = U.atField(R->getField(I)->Offset);
76 if (Field.isActive()) {
77 ActiveField = Field.getField();
78 break;
79 }
80 }
81
82 const SourceInfo &Loc = S.Current->getSource(OpPC);
83 S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
84 << AK << InactiveField << !ActiveField << ActiveField;
85 return false;
86}
87
88static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
89 AccessKinds AK) {
90 if (auto ID = Ptr.getDeclID()) {
91 if (!Ptr.isStaticTemporary())
92 return true;
93
95 return true;
96
97 if (S.P.getCurrentDecl() == ID)
98 return true;
99
100 const SourceInfo &E = S.Current->getSource(OpPC);
101 S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
102 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
103 return false;
104 }
105 return true;
106}
107
108static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
109 if (auto ID = Ptr.getDeclID()) {
110 if (!Ptr.isStatic())
111 return true;
112
113 if (S.P.getCurrentDecl() == ID)
114 return true;
115
116 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
117 return false;
118 }
119 return true;
120}
121
122namespace clang {
123namespace interp {
124static void popArg(InterpState &S, const Expr *Arg) {
125 PrimType Ty = S.getContext().classify(Arg->getType()).value_or(PT_Ptr);
126 TYPE_SWITCH(Ty, S.Stk.discard<T>());
127}
128
130 assert(S.Current);
131 const Function *CurFunc = S.Current->getFunction();
132 assert(CurFunc);
133
134 if (CurFunc->isUnevaluatedBuiltin())
135 return;
136
137 if (S.Current->Caller && CurFunc->isVariadic()) {
138 // CallExpr we're look for is at the return PC of the current function, i.e.
139 // in the caller.
140 // This code path should be executed very rarely.
141 const auto *CE =
142 cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
143 unsigned FixedParams = CurFunc->getNumParams();
144 int32_t ArgsToPop = CE->getNumArgs() - FixedParams;
145 assert(ArgsToPop >= 0);
146 for (int32_t I = ArgsToPop - 1; I >= 0; --I) {
147 const Expr *A = CE->getArg(FixedParams + I);
148 popArg(S, A);
149 }
150 }
151 // And in any case, remove the fixed parameters (the non-variadic ones)
152 // at the end.
153 S.Current->popArgs();
154}
155
156bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
157 if (!Ptr.isExtern())
158 return true;
159
160 if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
161 const auto *VD = Ptr.getDeclDesc()->asValueDecl();
162 const SourceInfo &Loc = S.Current->getSource(OpPC);
163 S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
164 S.Note(VD->getLocation(), diag::note_declared_at);
165 }
166 return false;
167}
168
169bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
170 if (!Ptr.isUnknownSizeArray())
171 return true;
172 const SourceInfo &E = S.Current->getSource(OpPC);
173 S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
174 return false;
175}
176
177bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
178 AccessKinds AK) {
179 if (Ptr.isZero()) {
180 const auto &Src = S.Current->getSource(OpPC);
181
182 if (Ptr.isField())
183 S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
184 else
185 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
186
187 return false;
188 }
189
190 if (!Ptr.isLive()) {
191 const auto &Src = S.Current->getSource(OpPC);
192 bool IsTemp = Ptr.isTemporary();
193
194 S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
195
196 if (IsTemp)
197 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
198 else
199 S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
200
201 return false;
202 }
203
204 return true;
205}
206
207bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
208 return !Ptr.isZero() && !Ptr.isDummy();
209}
210
211bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
212 CheckSubobjectKind CSK) {
213 if (!Ptr.isZero())
214 return true;
215 const SourceInfo &Loc = S.Current->getSource(OpPC);
216 S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
217 return false;
218}
219
220bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
221 AccessKinds AK) {
222 if (!Ptr.isOnePastEnd())
223 return true;
224 const SourceInfo &Loc = S.Current->getSource(OpPC);
225 S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
226 return false;
227}
228
229bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
230 CheckSubobjectKind CSK) {
231 if (!Ptr.isElementPastEnd())
232 return true;
233 const SourceInfo &Loc = S.Current->getSource(OpPC);
234 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
235 return false;
236}
237
238bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
239 CheckSubobjectKind CSK) {
240 if (!Ptr.isOnePastEnd())
241 return true;
242
243 const SourceInfo &Loc = S.Current->getSource(OpPC);
244 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
245 return false;
246}
247
248bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
249 assert(Ptr.isLive() && "Pointer is not live");
250 if (!Ptr.isConst())
251 return true;
252
253 // The This pointer is writable in constructors and destructors,
254 // even if isConst() returns true.
255 if (const Function *Func = S.Current->getFunction();
256 Func && (Func->isConstructor() || Func->isDestructor()) &&
257 Ptr.block() == S.Current->getThis().block()) {
258 return true;
259 }
260
261 const QualType Ty = Ptr.getType();
262 const SourceInfo &Loc = S.Current->getSource(OpPC);
263 S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
264 return false;
265}
266
267bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
268 assert(Ptr.isLive() && "Pointer is not live");
269 if (!Ptr.isMutable()) {
270 return true;
271 }
272
273 const SourceInfo &Loc = S.Current->getSource(OpPC);
274 const FieldDecl *Field = Ptr.getField();
275 S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
276 S.Note(Field->getLocation(), diag::note_declared_at);
277 return false;
278}
279
280bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
281 AccessKinds AK) {
282 if (Ptr.isInitialized())
283 return true;
284
285 if (!S.checkingPotentialConstantExpression()) {
286 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
287 << AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
288 }
289 return false;
290}
291
292bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
293 if (!CheckDummy(S, OpPC, Ptr))
294 return false;
295 if (!CheckLive(S, OpPC, Ptr, AK_Read))
296 return false;
297 if (!CheckExtern(S, OpPC, Ptr))
298 return false;
299 if (!CheckRange(S, OpPC, Ptr, AK_Read))
300 return false;
301 if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
302 return false;
303 if (!CheckActive(S, OpPC, Ptr, AK_Read))
304 return false;
305 if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
306 return false;
307 if (!CheckMutable(S, OpPC, Ptr))
308 return false;
309 return true;
310}
311
312bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
313 if (!CheckLive(S, OpPC, Ptr, AK_Assign))
314 return false;
315 if (!CheckExtern(S, OpPC, Ptr))
316 return false;
317 if (!CheckRange(S, OpPC, Ptr, AK_Assign))
318 return false;
319 if (!CheckGlobal(S, OpPC, Ptr))
320 return false;
321 if (!CheckConst(S, OpPC, Ptr))
322 return false;
323 return true;
324}
325
326bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
327 if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
328 return false;
329 if (!CheckExtern(S, OpPC, Ptr))
330 return false;
331 if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
332 return false;
333 return true;
334}
335
336bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
337 if (!CheckLive(S, OpPC, Ptr, AK_Assign))
338 return false;
339 if (!CheckRange(S, OpPC, Ptr, AK_Assign))
340 return false;
341 return true;
342}
343
344bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
345
346 if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
347 const SourceLocation &Loc = S.Current->getLocation(OpPC);
348 S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
349 return false;
350 }
351
352 if (!F->isConstexpr()) {
353 // Don't emit anything if we're checking for a potential constant
354 // expression. That will happen later when actually executing.
355 if (S.checkingPotentialConstantExpression())
356 return false;
357
358 const SourceLocation &Loc = S.Current->getLocation(OpPC);
359 if (S.getLangOpts().CPlusPlus11) {
360 const FunctionDecl *DiagDecl = F->getDecl();
361
362 // If this function is not constexpr because it is an inherited
363 // non-constexpr constructor, diagnose that directly.
364 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
365 if (CD && CD->isInheritingConstructor()) {
366 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
367 if (!Inherited->isConstexpr())
368 DiagDecl = CD = Inherited;
369 }
370
371 // FIXME: If DiagDecl is an implicitly-declared special member function
372 // or an inheriting constructor, we should be much more explicit about why
373 // it's not constexpr.
374 if (CD && CD->isInheritingConstructor())
375 S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
376 << CD->getInheritedConstructor().getConstructor()->getParent();
377 else
378 S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
379 << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
380 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
381 } else {
382 S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
383 }
384 return false;
385 }
386
387 return true;
388}
389
391 if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
392 S.FFDiag(S.Current->getSource(OpPC),
393 diag::note_constexpr_depth_limit_exceeded)
394 << S.getLangOpts().ConstexprCallDepth;
395 return false;
396 }
397
398 return true;
399}
400
401bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
402 if (!This.isZero())
403 return true;
404
405 const SourceInfo &Loc = S.Current->getSource(OpPC);
406
407 bool IsImplicit = false;
408 if (const auto *E = dyn_cast_if_present<CXXThisExpr>(Loc.asExpr()))
409 IsImplicit = E->isImplicit();
410
411 if (S.getLangOpts().CPlusPlus11)
412 S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
413 else
414 S.FFDiag(Loc);
415
416 return false;
417}
418
419bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
420 if (!MD->isPure())
421 return true;
422 const SourceInfo &E = S.Current->getSource(OpPC);
423 S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
424 S.Note(MD->getLocation(), diag::note_declared_at);
425 return false;
426}
427
429 const FieldDecl *SubObjDecl) {
430 assert(SubObjDecl && "Subobject declaration does not exist");
431 S.FFDiag(SI, diag::note_constexpr_uninitialized)
432 << /*(name)*/ 1 << SubObjDecl;
433 S.Note(SubObjDecl->getLocation(),
434 diag::note_constexpr_subobject_declared_here);
435}
436
437static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC,
438 const Pointer &BasePtr, const Record *R);
439
441 const Pointer &BasePtr,
442 const ConstantArrayType *CAT) {
443 bool Result = true;
444 size_t NumElems = CAT->getSize().getZExtValue();
445 QualType ElemType = CAT->getElementType();
446
447 if (ElemType->isRecordType()) {
448 const Record *R = BasePtr.getElemRecord();
449 for (size_t I = 0; I != NumElems; ++I) {
450 Pointer ElemPtr = BasePtr.atIndex(I).narrow();
451 Result &= CheckFieldsInitialized(S, OpPC, ElemPtr, R);
452 }
453 } else if (const auto *ElemCAT = dyn_cast<ConstantArrayType>(ElemType)) {
454 for (size_t I = 0; I != NumElems; ++I) {
455 Pointer ElemPtr = BasePtr.atIndex(I).narrow();
456 Result &= CheckArrayInitialized(S, OpPC, ElemPtr, ElemCAT);
457 }
458 } else {
459 for (size_t I = 0; I != NumElems; ++I) {
460 if (!BasePtr.atIndex(I).isInitialized()) {
461 DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC),
462 BasePtr.getField());
463 Result = false;
464 }
465 }
466 }
467
468 return Result;
469}
470
472 const Pointer &BasePtr, const Record *R) {
473 assert(R);
474 bool Result = true;
475 // Check all fields of this record are initialized.
476 for (const Record::Field &F : R->fields()) {
477 Pointer FieldPtr = BasePtr.atField(F.Offset);
478 QualType FieldType = F.Decl->getType();
479
480 if (FieldType->isRecordType()) {
481 Result &= CheckFieldsInitialized(S, OpPC, FieldPtr, FieldPtr.getRecord());
482 } else if (FieldType->isIncompleteArrayType()) {
483 // Nothing to do here.
484 } else if (FieldType->isArrayType()) {
485 const auto *CAT =
486 cast<ConstantArrayType>(FieldType->getAsArrayTypeUnsafe());
487 Result &= CheckArrayInitialized(S, OpPC, FieldPtr, CAT);
488 } else if (!FieldPtr.isInitialized()) {
489 DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC), F.Decl);
490 Result = false;
491 }
492 }
493
494 // Check Fields in all bases
495 for (const Record::Base &B : R->bases()) {
496 Pointer P = BasePtr.atField(B.Offset);
497 if (!P.isInitialized()) {
498 S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(),
499 diag::note_constexpr_uninitialized_base)
500 << B.Desc->getType();
501 return false;
502 }
503 Result &= CheckFieldsInitialized(S, OpPC, P, B.R);
504 }
505
506 // TODO: Virtual bases
507
508 return Result;
509}
510
512 assert(!This.isZero());
513 if (const Record *R = This.getRecord())
514 return CheckFieldsInitialized(S, OpPC, This, R);
515 const auto *CAT =
516 cast<ConstantArrayType>(This.getType()->getAsArrayTypeUnsafe());
517 return CheckArrayInitialized(S, OpPC, This, CAT);
518}
519
521 const Pointer &Ptr) {
522 if (!S.inConstantContext())
523 return true;
524
525 const SourceInfo &E = S.Current->getSource(OpPC);
526 S.CCEDiag(E, diag::note_constexpr_invalid_cast)
527 << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
528 return false;
529}
530
532 APFloat::opStatus Status) {
533 const SourceInfo &E = S.Current->getSource(OpPC);
534
535 // [expr.pre]p4:
536 // If during the evaluation of an expression, the result is not
537 // mathematically defined [...], the behavior is undefined.
538 // FIXME: C++ rules require us to not conform to IEEE 754 here.
539 if (Result.isNan()) {
540 S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
541 << /*NaN=*/true << S.Current->getRange(OpPC);
542 return S.noteUndefinedBehavior();
543 }
544
545 // In a constant context, assume that any dynamic rounding mode or FP
546 // exception state matches the default floating-point environment.
547 if (S.inConstantContext())
548 return true;
549
551
552 if ((Status & APFloat::opInexact) &&
553 FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) {
554 // Inexact result means that it depends on rounding mode. If the requested
555 // mode is dynamic, the evaluation cannot be made in compile time.
556 S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
557 return false;
558 }
559
560 if ((Status != APFloat::opOK) &&
561 (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic ||
563 FPO.getAllowFEnvAccess())) {
564 S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
565 return false;
566 }
567
568 if ((Status & APFloat::opStatus::opInvalidOp) &&
570 // There is no usefully definable result.
571 S.FFDiag(E);
572 return false;
573 }
574
575 return true;
576}
577
578/// We aleady know the given DeclRefExpr is invalid for some reason,
579/// now figure out why and print appropriate diagnostics.
580bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
581 const ValueDecl *D = DR->getDecl();
582 const SourceInfo &E = S.Current->getSource(OpPC);
583
584 if (isa<ParmVarDecl>(D)) {
585 if (S.getLangOpts().CPlusPlus11) {
586 S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
587 S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
588 } else {
589 S.FFDiag(E);
590 }
591 } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
592 if (!VD->getType().isConstQualified()) {
593 S.FFDiag(E,
594 VD->getType()->isIntegralOrEnumerationType()
595 ? diag::note_constexpr_ltor_non_const_int
596 : diag::note_constexpr_ltor_non_constexpr,
597 1)
598 << VD;
599 S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
600 return false;
601 }
602
603 // const, but no initializer.
604 if (!VD->getAnyInitializer()) {
605 S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
606 S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
607 return false;
608 }
609 }
610
611 return false;
612}
613
615 // The current stack frame when we started Interpret().
616 // This is being used by the ops to determine wheter
617 // to return from this function and thus terminate
618 // interpretation.
619 const InterpFrame *StartFrame = S.Current;
620 assert(!S.Current->isRoot());
621 CodePtr PC = S.Current->getPC();
622
623 // Empty program.
624 if (!PC)
625 return true;
626
627 for (;;) {
628 auto Op = PC.read<Opcode>();
629 CodePtr OpPC = PC;
630
631 switch (Op) {
632#define GET_INTERP
633#include "Opcodes.inc"
634#undef GET_INTERP
635 }
636 }
637}
638
639} // namespace interp
640} // namespace clang
Defines the clang::ASTContext interface.
StringRef P
Defines the clang::Expr interface and subclasses for C++ expressions.
static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:37
static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:56
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition: Interp.cpp:108
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:88
static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:42
static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result)
Definition: Interp.cpp:29
static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:49
#define TYPE_SWITCH(Expr, B)
Definition: PrimType.h:109
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition: APValue.h:122
QualType getElementType() const
Definition: Type.h:3157
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2053
Represents the canonical version of C arrays with a specified constant size.
Definition: Type.h:3184
const llvm::APInt & getSize() const
Definition: Type.h:3205
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1248
ValueDecl * getDecl()
Definition: Expr.h:1316
SourceLocation getLocation() const
Definition: DeclBase.h:444
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:432
This represents one expression.
Definition: Expr.h:110
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Returns the set of floating point options that apply to this expression.
Definition: Expr.cpp:3791
QualType getType() const
Definition: Expr.h:142
LangOptions::FPExceptionModeKind getExceptionMode() const
Definition: LangOptions.h:777
RoundingMode getRoundingMode() const
Definition: LangOptions.h:765
Represents a member of a struct/union/class.
Definition: Decl.h:3015
Represents a function declaration or definition.
Definition: Decl.h:1957
bool isPure() const
Whether this virtual function is pure, i.e.
Definition: Decl.h:2295
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2405
@ FPE_Ignore
Assume that floating-point exceptions are masked.
Definition: LangOptions.h:283
A (possibly-)qualified type.
Definition: Type.h:736
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:6853
const LangOptions & getLangOpts() const
Definition: Sema.h:1681
Encodes a location in the source.
bool isIncompleteArrayType() const
Definition: Type.h:7107
bool isArrayType() const
Definition: Type.h:7099
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:7611
bool isRecordType() const
Definition: Type.h:7123
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:704
Pointer into the code segment.
Definition: Source.h:30
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
Definition: Source.h:55
Bytecode function.
Definition: Function.h:76
unsigned getNumParams() const
Definition: Function.h:184
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
Definition: Function.h:91
bool isVirtual() const
Checks if the function is virtual.
Definition: Function.cpp:47
bool isUnevaluatedBuiltin() const
Definition: Function.h:182
bool isConstexpr() const
Checks if the function is valid to call in constexpr.
Definition: Function.h:132
bool isVariadic() const
Definition: Function.h:176
Frame storing local variables.
Definition: InterpFrame.h:28
Interpreter context.
Definition: InterpState.h:35
A pointer to a memory block, live or dead.
Definition: Pointer.h:65
Pointer narrow() const
Restricts the scope of an array element pointer.
Definition: Pointer.h:130
bool isInitialized() const
Checks if an object was initialized.
Definition: Pointer.cpp:160
bool isStatic() const
Checks if the storage is static.
Definition: Pointer.h:304
bool isDummy() const
Checks if the pointer pointers to a dummy value.
Definition: Pointer.h:327
bool isExtern() const
Checks if the storage is extern.
Definition: Pointer.h:302
Pointer atIndex(unsigned Idx) const
Offsets a pointer inside an array.
Definition: Pointer.h:104
bool isActive() const
Checks if the object is active.
Definition: Pointer.h:323
bool isConst() const
Checks if an object or a subfield is mutable.
Definition: Pointer.h:330
Pointer atField(unsigned Off) const
Creates a pointer to a field.
Definition: Pointer.h:116
bool isMutable() const
Checks if the field is mutable.
Definition: Pointer.h:317
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition: Pointer.h:278
QualType getType() const
Returns the type of the innermost field.
Definition: Pointer.h:236
bool isLive() const
Checks if the pointer is live.
Definition: Pointer.h:197
bool isStaticTemporary() const
Checks if the storage is a static temporary.
Definition: Pointer.h:314
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition: Pointer.h:209
bool isZero() const
Checks if the pointer is null.
Definition: Pointer.h:195
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition: Pointer.h:202
const Record * getElemRecord() const
Returns the element record type, if this is a non-primive array.
Definition: Pointer.h:291
bool isOnePastEnd() const
Checks if the index is one past end.
Definition: Pointer.h:365
const FieldDecl * getField() const
Returns the field information.
Definition: Pointer.h:296
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
Definition: Pointer.h:372
bool isTemporary() const
Checks if the storage is temporary.
Definition: Pointer.h:309
SourceLocation getDeclLoc() const
Definition: Pointer.h:206
const Block * block() const
Definition: Pointer.h:348
std::optional< unsigned > getDeclID() const
Returns the declaration ID.
Definition: Pointer.h:335
bool isField() const
Checks if the item is a field in an object.
Definition: Pointer.h:199
const Record * getRecord() const
Returns the record descriptor of a class.
Definition: Pointer.h:289
Structure/Class descriptor.
Definition: Record.h:25
bool isUnion() const
Checks if the record is a union.
Definition: Record.h:56
const Field * getField(const FieldDecl *FD) const
Returns a field.
Definition: Record.cpp:30
llvm::iterator_range< const_base_iter > bases() const
Definition: Record.h:86
unsigned getNumFields() const
Definition: Record.h:81
llvm::iterator_range< const_field_iter > fields() const
Definition: Record.h:77
Describes the statement/declaration an opcode was generated from.
Definition: Source.h:72
const Expr * asExpr() const
Definition: Source.cpp:35
bool CheckPotentialReinterpretCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if reinterpret casts are legal in the current context.
Definition: Interp.cpp:520
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
Definition: Interp.cpp:336
bool Interpret(InterpState &S, APValue &Result)
Interpreter entry point.
Definition: Interp.cpp:614
bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR)
We aleady know the given DeclRefExpr is invalid for some reason, now figure out why and print appropr...
Definition: Interp.cpp:580
bool CheckCallDepth(InterpState &S, CodePtr OpPC)
Checks if calling the currently active function would exceed the allowed call depth.
Definition: Interp.cpp:390
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks the 'this' pointer.
Definition: Interp.cpp:401
bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks that all fields are initialized after a constructor call.
Definition: Interp.cpp:511
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
Definition: Interp.cpp:267
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if Ptr is a one-past-the-end pointer.
Definition: Interp.cpp:238
bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:280
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
Definition: Interp.cpp:220
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
Definition: Interp.cpp:419
bool This(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1711
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
Definition: Interp.cpp:177
static void popArg(InterpState &S, const Expr *Arg)
Definition: Interp.cpp:124
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:32
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be stored in a block.
Definition: Interp.cpp:312
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
Definition: Interp.cpp:211
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be loaded from a block.
Definition: Interp.cpp:292
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
Definition: Interp.cpp:169
static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC, const Pointer &BasePtr, const Record *R)
Definition: Interp.cpp:471
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC)
Definition: Interp.cpp:129
static void DiagnoseUninitializedSubobject(InterpState &S, const SourceInfo &SI, const FieldDecl *SubObjDecl)
Definition: Interp.cpp:428
static bool CheckArrayInitialized(InterpState &S, CodePtr OpPC, const Pointer &BasePtr, const ConstantArrayType *CAT)
Definition: Interp.cpp:440
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
Definition: Interp.cpp:156
bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
Checks if a method can be called.
Definition: Interp.cpp:344
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer is a dummy pointer.
Definition: Interp.cpp:207
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
Definition: Interp.cpp:248
bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a method can be invoked on an object.
Definition: Interp.cpp:326
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result, APFloat::opStatus Status)
Checks if the result of a floating-point operation is valid in the current context.
Definition: Interp.cpp:531
CheckSubobjectKind
The order of this enum is important for diagnostics.
Definition: State.h:40
@ CSK_Field
Definition: State.h:43
@ Result
The result type of a method or function.
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
Definition: State.h:26
@ AK_Read
Definition: State.h:27
@ AK_Assign
Definition: State.h:29
@ AK_MemberCall
Definition: State.h:32
#define bool
Definition: stdbool.h:20
const ValueDecl * asValueDecl() const
Definition: Descriptor.h:153
QualType getType() const
Definition: Descriptor.cpp:306
const Decl * asDecl() const
Definition: Descriptor.h:150
Describes a base class.
Definition: Record.h:36
Describes a record field.
Definition: Record.h:28