clang 20.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 "Function.h"
11#include "InterpFrame.h"
12#include "InterpShared.h"
13#include "InterpStack.h"
14#include "Opcode.h"
15#include "PrimType.h"
16#include "Program.h"
17#include "State.h"
21#include "clang/AST/DeclObjC.h"
22#include "clang/AST/Expr.h"
23#include "clang/AST/ExprCXX.h"
24#include "llvm/ADT/APSInt.h"
25#include "llvm/ADT/StringExtras.h"
26#include <limits>
27#include <vector>
28
29using namespace clang;
30
31using namespace clang;
32using namespace clang::interp;
33
34static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) {
35 llvm::report_fatal_error("Interpreter cannot return values");
36}
37
38//===----------------------------------------------------------------------===//
39// Jmp, Jt, Jf
40//===----------------------------------------------------------------------===//
41
42static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
43 PC += Offset;
44 return true;
45}
46
47static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
48 if (S.Stk.pop<bool>()) {
49 PC += Offset;
50 }
51 return true;
52}
53
54static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
55 if (!S.Stk.pop<bool>()) {
56 PC += Offset;
57 }
58 return true;
59}
60
62 const ValueDecl *VD) {
63 const SourceInfo &E = S.Current->getSource(OpPC);
64 S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
65 S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
66}
67
69 const ValueDecl *VD);
71 const ValueDecl *D) {
72 const SourceInfo &E = S.Current->getSource(OpPC);
73
74 if (isa<ParmVarDecl>(D)) {
75 if (S.getLangOpts().CPlusPlus11) {
76 S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
77 S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
78 } else {
79 S.FFDiag(E);
80 }
81 return false;
82 }
83
84 if (!D->getType().isConstQualified())
86 else if (const auto *VD = dyn_cast<VarDecl>(D);
87 VD && !VD->getAnyInitializer())
88 diagnoseMissingInitializer(S, OpPC, VD);
89
90 return false;
91}
92
94 const ValueDecl *VD) {
95 if (!S.getLangOpts().CPlusPlus)
96 return;
97
98 const SourceInfo &Loc = S.Current->getSource(OpPC);
99 if (const auto *VarD = dyn_cast<VarDecl>(VD);
100 VarD && VarD->getType().isConstQualified() &&
101 !VarD->getAnyInitializer()) {
102 diagnoseMissingInitializer(S, OpPC, VD);
103 return;
104 }
105
106 // Rather random, but this is to match the diagnostic output of the current
107 // interpreter.
108 if (isa<ObjCIvarDecl>(VD))
109 return;
110
112 S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
113 S.Note(VD->getLocation(), diag::note_declared_at);
114 return;
115 }
116
117 S.FFDiag(Loc,
118 S.getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
119 : diag::note_constexpr_ltor_non_integral,
120 1)
121 << VD << VD->getType();
122 S.Note(VD->getLocation(), diag::note_declared_at);
123}
124
125static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
126 AccessKinds AK) {
127 if (Ptr.isActive())
128 return true;
129
130 // Get the inactive field descriptor.
131 const FieldDecl *InactiveField = Ptr.getField();
132
133 // Walk up the pointer chain to find the union which is not active.
134 Pointer U = Ptr.getBase();
135 while (!U.isActive()) {
136 U = U.getBase();
137 }
138
139 // Find the active field of the union.
140 const Record *R = U.getRecord();
141 assert(R && R->isUnion() && "Not a union");
142 const FieldDecl *ActiveField = nullptr;
143 for (unsigned I = 0, N = R->getNumFields(); I < N; ++I) {
144 const Pointer &Field = U.atField(R->getField(I)->Offset);
145 if (Field.isActive()) {
146 ActiveField = Field.getField();
147 break;
148 }
149 }
150
151 const SourceInfo &Loc = S.Current->getSource(OpPC);
152 S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
153 << AK << InactiveField << !ActiveField << ActiveField;
154 return false;
155}
156
157static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
158 AccessKinds AK) {
159 if (auto ID = Ptr.getDeclID()) {
160 if (!Ptr.isStaticTemporary())
161 return true;
162
163 if (Ptr.getDeclDesc()->getType().isConstQualified())
164 return true;
165
166 if (S.P.getCurrentDecl() == ID)
167 return true;
168
169 const SourceInfo &E = S.Current->getSource(OpPC);
170 S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
171 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
172 return false;
173 }
174 return true;
175}
176
177static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
178 if (auto ID = Ptr.getDeclID()) {
179 if (!Ptr.isStatic())
180 return true;
181
182 if (S.P.getCurrentDecl() == ID)
183 return true;
184
185 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
186 return false;
187 }
188 return true;
189}
190
191namespace clang {
192namespace interp {
193static void popArg(InterpState &S, const Expr *Arg) {
194 PrimType Ty = S.getContext().classify(Arg).value_or(PT_Ptr);
195 TYPE_SWITCH(Ty, S.Stk.discard<T>());
196}
197
199 assert(S.Current);
200 const Function *CurFunc = S.Current->getFunction();
201 assert(CurFunc);
202
203 if (CurFunc->isUnevaluatedBuiltin())
204 return;
205
206 // Some builtin functions require us to only look at the call site, since
207 // the classified parameter types do not match.
208 if (CurFunc->isBuiltin()) {
209 const auto *CE =
210 cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
211 for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
212 const Expr *A = CE->getArg(I);
213 popArg(S, A);
214 }
215 return;
216 }
217
218 if (S.Current->Caller && CurFunc->isVariadic()) {
219 // CallExpr we're look for is at the return PC of the current function, i.e.
220 // in the caller.
221 // This code path should be executed very rarely.
222 unsigned NumVarArgs;
223 const Expr *const *Args = nullptr;
224 unsigned NumArgs = 0;
225 const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
226 if (const auto *CE = dyn_cast<CallExpr>(CallSite)) {
227 Args = CE->getArgs();
228 NumArgs = CE->getNumArgs();
229 } else if (const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
230 Args = CE->getArgs();
231 NumArgs = CE->getNumArgs();
232 } else
233 assert(false && "Can't get arguments from that expression type");
234
235 assert(NumArgs >= CurFunc->getNumWrittenParams());
236 NumVarArgs = NumArgs - (CurFunc->getNumWrittenParams() +
237 isa<CXXOperatorCallExpr>(CallSite));
238 for (unsigned I = 0; I != NumVarArgs; ++I) {
239 const Expr *A = Args[NumArgs - 1 - I];
240 popArg(S, A);
241 }
242 }
243
244 // And in any case, remove the fixed parameters (the non-variadic ones)
245 // at the end.
246 S.Current->popArgs();
247}
248
249bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
250 if (!Ptr.isExtern())
251 return true;
252
253 if (Ptr.isInitialized() ||
254 (Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl))
255 return true;
256
257 if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
258 const auto *VD = Ptr.getDeclDesc()->asValueDecl();
259 diagnoseNonConstVariable(S, OpPC, VD);
260 }
261 return false;
262}
263
264bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
265 if (!Ptr.isUnknownSizeArray())
266 return true;
267 const SourceInfo &E = S.Current->getSource(OpPC);
268 S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
269 return false;
270}
271
272bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
273 AccessKinds AK) {
274 if (Ptr.isZero()) {
275 const auto &Src = S.Current->getSource(OpPC);
276
277 if (Ptr.isField())
278 S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
279 else
280 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
281
282 return false;
283 }
284
285 if (!Ptr.isLive()) {
286 const auto &Src = S.Current->getSource(OpPC);
287 bool IsTemp = Ptr.isTemporary();
288
289 S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
290
291 if (IsTemp)
292 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
293 else
294 S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
295
296 return false;
297 }
298
299 return true;
300}
301
302bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
303 assert(Desc);
304
305 auto IsConstType = [&S](const VarDecl *VD) -> bool {
306 if (VD->isConstexpr())
307 return true;
308
309 QualType T = VD->getType();
310 if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11)
313 T.isConstQualified();
314
315 if (T.isConstQualified())
316 return true;
317
318 if (const auto *RT = T->getAs<ReferenceType>())
319 return RT->getPointeeType().isConstQualified();
320
321 if (const auto *PT = T->getAs<PointerType>())
322 return PT->getPointeeType().isConstQualified();
323
324 return false;
325 };
326
327 if (const auto *D = Desc->asVarDecl();
328 D && D->hasGlobalStorage() && D != S.EvaluatingDecl && !IsConstType(D)) {
329 diagnoseNonConstVariable(S, OpPC, D);
330 return S.inConstantContext();
331 }
332
333 return true;
334}
335
336static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
337 if (!Ptr.isBlockPointer())
338 return true;
339 return CheckConstant(S, OpPC, Ptr.getDeclDesc());
340}
341
342bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
343 CheckSubobjectKind CSK) {
344 if (!Ptr.isZero())
345 return true;
346 const SourceInfo &Loc = S.Current->getSource(OpPC);
347 S.FFDiag(Loc, diag::note_constexpr_null_subobject)
348 << CSK << S.Current->getRange(OpPC);
349
350 return false;
351}
352
353bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
354 AccessKinds AK) {
355 if (!Ptr.isOnePastEnd())
356 return true;
357 const SourceInfo &Loc = S.Current->getSource(OpPC);
358 S.FFDiag(Loc, diag::note_constexpr_access_past_end)
359 << AK << S.Current->getRange(OpPC);
360 return false;
361}
362
363bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
364 CheckSubobjectKind CSK) {
365 if (!Ptr.isElementPastEnd())
366 return true;
367 const SourceInfo &Loc = S.Current->getSource(OpPC);
368 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
369 << CSK << S.Current->getRange(OpPC);
370 return false;
371}
372
373bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
374 CheckSubobjectKind CSK) {
375 if (!Ptr.isOnePastEnd())
376 return true;
377
378 const SourceInfo &Loc = S.Current->getSource(OpPC);
379 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
380 << CSK << S.Current->getRange(OpPC);
381 return false;
382}
383
384bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
385 uint32_t Offset) {
386 uint32_t MinOffset = Ptr.getDeclDesc()->getMetadataSize();
387 uint32_t PtrOffset = Ptr.getByteOffset();
388
389 // We subtract Offset from PtrOffset. The result must be at least
390 // MinOffset.
391 if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
392 return true;
393
394 const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
395 QualType TargetQT = E->getType()->getPointeeType();
396 QualType MostDerivedQT = Ptr.getDeclPtr().getType();
397
398 S.CCEDiag(E, diag::note_constexpr_invalid_downcast)
399 << MostDerivedQT << TargetQT;
400
401 return false;
402}
403
404bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
405 assert(Ptr.isLive() && "Pointer is not live");
406 if (!Ptr.isConst() || Ptr.isMutable())
407 return true;
408
409 // The This pointer is writable in constructors and destructors,
410 // even if isConst() returns true.
411 // TODO(perf): We could be hitting this code path quite a lot in complex
412 // constructors. Is there a better way to do this?
413 if (S.Current->getFunction()) {
414 for (const InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) {
415 if (const Function *Func = Frame->getFunction();
416 Func && (Func->isConstructor() || Func->isDestructor()) &&
417 Ptr.block() == Frame->getThis().block()) {
418 return true;
419 }
420 }
421 }
422
423 if (!Ptr.isBlockPointer())
424 return false;
425
426 const QualType Ty = Ptr.getType();
427 const SourceInfo &Loc = S.Current->getSource(OpPC);
428 S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
429 return false;
430}
431
432bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
433 assert(Ptr.isLive() && "Pointer is not live");
434 if (!Ptr.isMutable())
435 return true;
436
437 // In C++14 onwards, it is permitted to read a mutable member whose
438 // lifetime began within the evaluation.
439 if (S.getLangOpts().CPlusPlus14 &&
440 Ptr.block()->getEvalID() == S.Ctx.getEvalID())
441 return true;
442
443 const SourceInfo &Loc = S.Current->getSource(OpPC);
444 const FieldDecl *Field = Ptr.getField();
445 S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
446 S.Note(Field->getLocation(), diag::note_declared_at);
447 return false;
448}
449
450bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
451 AccessKinds AK) {
452 assert(Ptr.isLive());
453
454 // FIXME: This check here might be kinda expensive. Maybe it would be better
455 // to have another field in InlineDescriptor for this?
456 if (!Ptr.isBlockPointer())
457 return true;
458
459 QualType PtrType = Ptr.getType();
460 if (!PtrType.isVolatileQualified())
461 return true;
462
463 const SourceInfo &Loc = S.Current->getSource(OpPC);
464 if (S.getLangOpts().CPlusPlus)
465 S.FFDiag(Loc, diag::note_constexpr_access_volatile_type) << AK << PtrType;
466 else
467 S.FFDiag(Loc);
468 return false;
469}
470
471bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
472 AccessKinds AK) {
473 assert(Ptr.isLive());
474
475 if (Ptr.isInitialized())
476 return true;
477
478 if (const auto *VD = Ptr.getDeclDesc()->asVarDecl();
479 VD && VD->hasGlobalStorage()) {
480 const SourceInfo &Loc = S.Current->getSource(OpPC);
481 if (VD->getAnyInitializer()) {
482 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
483 S.Note(VD->getLocation(), diag::note_declared_at);
484 } else {
485 diagnoseMissingInitializer(S, OpPC, VD);
486 }
487 return false;
488 }
489
490 if (!S.checkingPotentialConstantExpression()) {
491 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
492 << AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
493 }
494 return false;
495}
496
498 if (Ptr.isInitialized())
499 return true;
500
501 assert(S.getLangOpts().CPlusPlus);
502 const auto *VD = cast<VarDecl>(Ptr.getDeclDesc()->asValueDecl());
503 if ((!VD->hasConstantInitialization() &&
504 VD->mightBeUsableInConstantExpressions(S.getCtx())) ||
505 (S.getLangOpts().OpenCL && !S.getLangOpts().CPlusPlus11 &&
506 !VD->hasICEInitializer(S.getCtx()))) {
507 const SourceInfo &Loc = S.Current->getSource(OpPC);
508 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
509 S.Note(VD->getLocation(), diag::note_declared_at);
510 }
511 return false;
512}
513
514bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
515 AccessKinds AK) {
516 if (!CheckLive(S, OpPC, Ptr, AK))
517 return false;
518 if (!CheckConstant(S, OpPC, Ptr))
519 return false;
520
521 if (!CheckDummy(S, OpPC, Ptr, AK))
522 return false;
523 if (!CheckExtern(S, OpPC, Ptr))
524 return false;
525 if (!CheckRange(S, OpPC, Ptr, AK))
526 return false;
527 if (!CheckActive(S, OpPC, Ptr, AK))
528 return false;
529 if (!CheckInitialized(S, OpPC, Ptr, AK))
530 return false;
531 if (!CheckTemporary(S, OpPC, Ptr, AK))
532 return false;
533 if (!CheckMutable(S, OpPC, Ptr))
534 return false;
535 if (!CheckVolatile(S, OpPC, Ptr, AK))
536 return false;
537 return true;
538}
539
540bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
541 if (!CheckLive(S, OpPC, Ptr, AK_Assign))
542 return false;
543 if (!CheckDummy(S, OpPC, Ptr, AK_Assign))
544 return false;
545 if (!CheckExtern(S, OpPC, Ptr))
546 return false;
547 if (!CheckRange(S, OpPC, Ptr, AK_Assign))
548 return false;
549 if (!CheckGlobal(S, OpPC, Ptr))
550 return false;
551 if (!CheckConst(S, OpPC, Ptr))
552 return false;
553 return true;
554}
555
556bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
557 if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
558 return false;
559 if (!Ptr.isDummy()) {
560 if (!CheckExtern(S, OpPC, Ptr))
561 return false;
562 if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
563 return false;
564 }
565 return true;
566}
567
568bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
569 if (!CheckLive(S, OpPC, Ptr, AK_Assign))
570 return false;
571 if (!CheckRange(S, OpPC, Ptr, AK_Assign))
572 return false;
573 return true;
574}
575
576bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
577
578 if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
579 const SourceLocation &Loc = S.Current->getLocation(OpPC);
580 S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
581 return false;
582 }
583
584 if (F->isConstexpr() && F->hasBody() &&
585 (F->getDecl()->isConstexpr() || F->getDecl()->hasAttr<MSConstexprAttr>()))
586 return true;
587
588 // Implicitly constexpr.
589 if (F->isLambdaStaticInvoker())
590 return true;
591
592 const SourceLocation &Loc = S.Current->getLocation(OpPC);
593 if (S.getLangOpts().CPlusPlus11) {
594 const FunctionDecl *DiagDecl = F->getDecl();
595
596 // Invalid decls have been diagnosed before.
597 if (DiagDecl->isInvalidDecl())
598 return false;
599
600 // If this function is not constexpr because it is an inherited
601 // non-constexpr constructor, diagnose that directly.
602 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
603 if (CD && CD->isInheritingConstructor()) {
604 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
605 if (!Inherited->isConstexpr())
606 DiagDecl = CD = Inherited;
607 }
608
609 // FIXME: If DiagDecl is an implicitly-declared special member function
610 // or an inheriting constructor, we should be much more explicit about why
611 // it's not constexpr.
612 if (CD && CD->isInheritingConstructor()) {
613 S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
614 << CD->getInheritedConstructor().getConstructor()->getParent();
615 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
616 } else {
617 // Don't emit anything if the function isn't defined and we're checking
618 // for a constant expression. It might be defined at the point we're
619 // actually calling it.
620 bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
621 if (!DiagDecl->isDefined() && !IsExtern && DiagDecl->isConstexpr() &&
622 S.checkingPotentialConstantExpression())
623 return false;
624
625 // If the declaration is defined, declared 'constexpr' _and_ has a body,
626 // the below diagnostic doesn't add anything useful.
627 if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
628 DiagDecl->hasBody())
629 return false;
630
631 S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
632 << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
633 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
634 }
635 } else {
636 S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
637 }
638
639 return false;
640}
641
643 if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
644 S.FFDiag(S.Current->getSource(OpPC),
645 diag::note_constexpr_depth_limit_exceeded)
646 << S.getLangOpts().ConstexprCallDepth;
647 return false;
648 }
649
650 return true;
651}
652
653bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
654 if (!This.isZero())
655 return true;
656
657 const SourceInfo &Loc = S.Current->getSource(OpPC);
658
659 bool IsImplicit = false;
660 if (const auto *E = dyn_cast_if_present<CXXThisExpr>(Loc.asExpr()))
661 IsImplicit = E->isImplicit();
662
663 if (S.getLangOpts().CPlusPlus11)
664 S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
665 else
666 S.FFDiag(Loc);
667
668 return false;
669}
670
671bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
672 if (!MD->isPureVirtual())
673 return true;
674 const SourceInfo &E = S.Current->getSource(OpPC);
675 S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
676 S.Note(MD->getLocation(), diag::note_declared_at);
677 return false;
678}
679
681 APFloat::opStatus Status) {
682 const SourceInfo &E = S.Current->getSource(OpPC);
683
684 // [expr.pre]p4:
685 // If during the evaluation of an expression, the result is not
686 // mathematically defined [...], the behavior is undefined.
687 // FIXME: C++ rules require us to not conform to IEEE 754 here.
688 if (Result.isNan()) {
689 S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
690 << /*NaN=*/true << S.Current->getRange(OpPC);
691 return S.noteUndefinedBehavior();
692 }
693
694 // In a constant context, assume that any dynamic rounding mode or FP
695 // exception state matches the default floating-point environment.
696 if (S.inConstantContext())
697 return true;
698
699 FPOptions FPO = E.asExpr()->getFPFeaturesInEffect(S.Ctx.getLangOpts());
700
701 if ((Status & APFloat::opInexact) &&
702 FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) {
703 // Inexact result means that it depends on rounding mode. If the requested
704 // mode is dynamic, the evaluation cannot be made in compile time.
705 S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
706 return false;
707 }
708
709 if ((Status != APFloat::opOK) &&
710 (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic ||
712 FPO.getAllowFEnvAccess())) {
713 S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
714 return false;
715 }
716
717 if ((Status & APFloat::opStatus::opInvalidOp) &&
719 // There is no usefully definable result.
720 S.FFDiag(E);
721 return false;
722 }
723
724 return true;
725}
726
728 if (S.getLangOpts().CPlusPlus20)
729 return true;
730
731 const SourceInfo &E = S.Current->getSource(OpPC);
732 S.CCEDiag(E, diag::note_constexpr_new);
733 return true;
734}
735
736bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC, bool NewWasArray,
737 bool DeleteIsArray, const Descriptor *D,
738 const Expr *NewExpr) {
739 if (NewWasArray == DeleteIsArray)
740 return true;
741
742 QualType TypeToDiagnose;
743 // We need to shuffle things around a bit here to get a better diagnostic,
744 // because the expression we allocated the block for was of type int*,
745 // but we want to get the array size right.
746 if (D->isArray()) {
747 QualType ElemQT = D->getType()->getPointeeType();
748 TypeToDiagnose = S.getCtx().getConstantArrayType(
749 ElemQT, APInt(64, static_cast<uint64_t>(D->getNumElems()), false),
750 nullptr, ArraySizeModifier::Normal, 0);
751 } else
752 TypeToDiagnose = D->getType()->getPointeeType();
753
754 const SourceInfo &E = S.Current->getSource(OpPC);
755 S.FFDiag(E, diag::note_constexpr_new_delete_mismatch)
756 << DeleteIsArray << 0 << TypeToDiagnose;
757 S.Note(NewExpr->getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
758 << NewExpr->getSourceRange();
759 return false;
760}
761
762bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source,
763 const Pointer &Ptr) {
764 if (Source && isa<CXXNewExpr>(Source))
765 return true;
766
767 // Whatever this is, we didn't heap allocate it.
768 const SourceInfo &Loc = S.Current->getSource(OpPC);
769 S.FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
770 << Ptr.toDiagnosticString(S.getCtx());
771
772 if (Ptr.isTemporary())
773 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
774 else
775 S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
776 return false;
777}
778
779/// We aleady know the given DeclRefExpr is invalid for some reason,
780/// now figure out why and print appropriate diagnostics.
781bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
782 const ValueDecl *D = DR->getDecl();
783 return diagnoseUnknownDecl(S, OpPC, D);
784}
785
786bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
787 AccessKinds AK) {
788 if (!Ptr.isDummy())
789 return true;
790
791 const Descriptor *Desc = Ptr.getDeclDesc();
792 const ValueDecl *D = Desc->asValueDecl();
793 if (!D)
794 return false;
795
796 if (AK == AK_Read || AK == AK_Increment || AK == AK_Decrement)
797 return diagnoseUnknownDecl(S, OpPC, D);
798
799 assert(AK == AK_Assign);
800 if (S.getLangOpts().CPlusPlus11) {
801 const SourceInfo &E = S.Current->getSource(OpPC);
802 S.FFDiag(E, diag::note_constexpr_modify_global);
803 }
804 return false;
805}
806
808 const CallExpr *CE, unsigned ArgSize) {
809 auto Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
810 auto NonNullArgs = collectNonNullArgs(F->getDecl(), Args);
811 unsigned Offset = 0;
812 unsigned Index = 0;
813 for (const Expr *Arg : Args) {
814 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
815 const Pointer &ArgPtr = S.Stk.peek<Pointer>(ArgSize - Offset);
816 if (ArgPtr.isZero()) {
817 const SourceLocation &Loc = S.Current->getLocation(OpPC);
818 S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
819 return false;
820 }
821 }
822
823 Offset += align(primSize(S.Ctx.classify(Arg).value_or(PT_Ptr)));
824 ++Index;
825 }
826 return true;
827}
828
829// FIXME: This is similar to code we already have in Compiler.cpp.
830// I think it makes sense to instead add the field and base destruction stuff
831// to the destructor Function itself. Then destroying a record would really
832// _just_ be calling its destructor. That would also help with the diagnostic
833// difference when the destructor or a field/base fails.
835 const Pointer &BasePtr,
836 const Descriptor *Desc) {
837 assert(Desc->isRecord());
838 const Record *R = Desc->ElemRecord;
839 assert(R);
840
841 // Fields.
842 for (const Record::Field &Field : llvm::reverse(R->fields())) {
843 const Descriptor *D = Field.Desc;
844 if (D->isRecord()) {
845 if (!runRecordDestructor(S, OpPC, BasePtr.atField(Field.Offset), D))
846 return false;
847 } else if (D->isCompositeArray()) {
848 const Descriptor *ElemDesc = Desc->ElemDesc;
849 assert(ElemDesc->isRecord());
850 for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
851 if (!runRecordDestructor(S, OpPC, BasePtr.atIndex(I).narrow(),
852 ElemDesc))
853 return false;
854 }
855 }
856 }
857
858 // Destructor of this record.
859 if (const CXXDestructorDecl *Dtor = R->getDestructor();
860 Dtor && !Dtor->isTrivial()) {
861 const Function *DtorFunc = S.getContext().getOrCreateFunction(Dtor);
862 if (!DtorFunc)
863 return false;
864
865 S.Stk.push<Pointer>(BasePtr);
866 if (!Call(S, OpPC, DtorFunc, 0))
867 return false;
868 }
869
870 // Bases.
871 for (const Record::Base &Base : llvm::reverse(R->bases())) {
872 if (!runRecordDestructor(S, OpPC, BasePtr.atField(Base.Offset), Base.Desc))
873 return false;
874 }
875
876 return true;
877}
878
879bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B) {
880 assert(B);
881 const Descriptor *Desc = B->getDescriptor();
882
883 if (Desc->isPrimitive() || Desc->isPrimitiveArray())
884 return true;
885
886 assert(Desc->isRecord() || Desc->isCompositeArray());
887
888 if (Desc->isCompositeArray()) {
889 const Descriptor *ElemDesc = Desc->ElemDesc;
890 assert(ElemDesc->isRecord());
891
892 Pointer RP(const_cast<Block *>(B));
893 for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
894 if (!runRecordDestructor(S, OpPC, RP.atIndex(I).narrow(), ElemDesc))
895 return false;
896 }
897 return true;
898 }
899
900 assert(Desc->isRecord());
901 return runRecordDestructor(S, OpPC, Pointer(const_cast<Block *>(B)), Desc);
902}
903
905 const APSInt &Value) {
906 llvm::APInt Min;
907 llvm::APInt Max;
908
909 if (S.EvaluatingDecl && !S.EvaluatingDecl->isConstexpr())
910 return;
911
912 ED->getValueRange(Max, Min);
913 --Max;
914
915 if (ED->getNumNegativeBits() &&
916 (Max.slt(Value.getSExtValue()) || Min.sgt(Value.getSExtValue()))) {
917 const SourceLocation &Loc = S.Current->getLocation(OpPC);
918 S.report(Loc, diag::warn_constexpr_unscoped_enum_out_of_range)
919 << llvm::toString(Value, 10) << Min.getSExtValue() << Max.getSExtValue()
920 << ED;
921 } else if (!ED->getNumNegativeBits() && Max.ult(Value.getZExtValue())) {
922 const SourceLocation &Loc = S.Current->getLocation(OpPC);
923 S.report(Loc, diag::warn_constexpr_unscoped_enum_out_of_range)
924 << llvm::toString(Value, 10) << Min.getZExtValue() << Max.getZExtValue()
925 << ED;
926 }
927}
928
930 // The current stack frame when we started Interpret().
931 // This is being used by the ops to determine wheter
932 // to return from this function and thus terminate
933 // interpretation.
934 const InterpFrame *StartFrame = S.Current;
935 assert(!S.Current->isRoot());
936 CodePtr PC = S.Current->getPC();
937
938 // Empty program.
939 if (!PC)
940 return true;
941
942 for (;;) {
943 auto Op = PC.read<Opcode>();
944 CodePtr OpPC = PC;
945
946 switch (Op) {
947#define GET_INTERP
948#include "Opcodes.inc"
949#undef GET_INTERP
950 }
951 }
952}
953
954} // namespace interp
955} // namespace clang
Defines the clang::ASTContext interface.
const Decl * D
Expr * E
Defines the clang::Expr interface and subclasses for C++ expressions.
static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:42
static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:125
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition: Interp.cpp:177
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:157
static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:47
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
Definition: Interp.cpp:93
static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result)
Definition: Interp.cpp:34
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, const ValueDecl *D)
Definition: Interp.cpp:70
static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:54
static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
Definition: Interp.cpp:61
#define TYPE_SWITCH(Expr, B)
Definition: PrimType.h:122
SourceLocation Loc
Definition: SemaObjC.cpp:758
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition: APValue.h:122
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2799
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2060
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2830
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:3008
Expr ** getArgs()
Retrieve the call arguments.
Definition: Expr.h:3011
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1265
ValueDecl * getDecl()
Definition: Expr.h:1333
bool isInvalidDecl() const
Definition: DeclBase.h:594
SourceLocation getLocation() const
Definition: DeclBase.h:445
bool hasAttr() const
Definition: DeclBase.h:583
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:433
Represents an enum.
Definition: Decl.h:3840
unsigned getNumNegativeBits() const
Returns the width in bits required to store all the negative enumerators of this enum.
Definition: Decl.h:4037
void getValueRange(llvm::APInt &Max, llvm::APInt &Min) const
Calculates the [Min,Max) values the enum can store based on the NumPositiveBits and NumNegativeBits.
Definition: Decl.cpp:4961
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:3864
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:277
QualType getType() const
Definition: Expr.h:142
LangOptions::FPExceptionModeKind getExceptionMode() const
Definition: LangOptions.h:865
RoundingMode getRoundingMode() const
Definition: LangOptions.h:853
Represents a member of a struct/union/class.
Definition: Decl.h:3030
Represents a function declaration or definition.
Definition: Decl.h:1932
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition: Decl.h:2302
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition: Decl.h:2760
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2395
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
Definition: Decl.h:2285
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition: Decl.cpp:3144
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Definition: Decl.cpp:3191
@ FPE_Ignore
Assume that floating-point exceptions are masked.
Definition: LangOptions.h:278
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3161
A (possibly-)qualified type.
Definition: Type.h:941
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition: Type.h:7827
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:7816
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3402
const LangOptions & getLangOpts() const
Definition: Sema.h:593
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition: Type.cpp:2167
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
Definition: Type.cpp:2217
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:705
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:8410
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8516
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:667
QualType getType() const
Definition: Decl.h:678
Represents a variable declaration or definition.
Definition: Decl.h:879
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1174
A memory block, either on the stack or in the heap.
Definition: InterpBlock.h:49
const Descriptor * getDescriptor() const
Returns the block's descriptor.
Definition: InterpBlock.h:67
unsigned getEvalID() const
The Evaluation ID this block was created in.
Definition: InterpBlock.h:85
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
Base class for stack frames, shared between VM and walker.
Definition: Frame.h:25
Bytecode function.
Definition: Function.h:77
bool isBuiltin() const
Definition: Function.h:183
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
Definition: Function.h:92
bool hasBody() const
Checks if the function already has a body attached.
Definition: Function.h:174
bool isVirtual() const
Checks if the function is virtual.
Definition: Function.cpp:48
bool isUnevaluatedBuiltin() const
Definition: Function.h:185
bool isConstexpr() const
Checks if the function is valid to call in constexpr.
Definition: Function.h:135
unsigned getNumWrittenParams() const
Returns the number of parameter this function takes when it's called, i.e excluding the instance poin...
Definition: Function.h:191
bool isLambdaStaticInvoker() const
Returns whether this function is a lambda static invoker, which we generate custom byte code for.
Definition: Function.h:154
bool isVariadic() const
Definition: Function.h:179
Frame storing local variables.
Definition: InterpFrame.h:26
Interpreter context.
Definition: InterpState.h:36
A pointer to a memory block, live or dead.
Definition: Pointer.h:80
Pointer narrow() const
Restricts the scope of an array element pointer.
Definition: Pointer.h:179
bool isInitialized() const
Checks if an object was initialized.
Definition: Pointer.cpp:271
bool isStatic() const
Checks if the storage is static.
Definition: Pointer.h:470
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
Definition: Pointer.h:144
bool isDummy() const
Checks if the pointer points to a dummy value.
Definition: Pointer.h:517
bool isExtern() const
Checks if the storage is extern.
Definition: Pointer.h:464
bool isActive() const
Checks if the object is active.
Definition: Pointer.h:506
bool isConst() const
Checks if an object or a subfield is mutable.
Definition: Pointer.h:528
Pointer atField(unsigned Off) const
Creates a pointer to a field.
Definition: Pointer.h:163
bool isMutable() const
Checks if the field is mutable.
Definition: Pointer.h:488
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition: Pointer.h:406
QualType getType() const
Returns the type of the innermost field.
Definition: Pointer.h:334
bool isLive() const
Checks if the pointer is live.
Definition: Pointer.h:265
bool isStaticTemporary() const
Checks if the storage is a static temporary.
Definition: Pointer.h:485
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition: Pointer.h:304
std::string toDiagnosticString(const ASTContext &Ctx) const
Converts the pointer to a string usable in diagnostics.
Definition: Pointer.cpp:261
bool isZero() const
Checks if the pointer is null.
Definition: Pointer.h:256
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition: Pointer.h:279
bool isOnePastEnd() const
Checks if the index is one past end.
Definition: Pointer.h:580
const FieldDecl * getField() const
Returns the field information.
Definition: Pointer.h:458
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
Definition: Pointer.h:603
bool isBlockPointer() const
Definition: Pointer.h:446
bool isTemporary() const
Checks if the storage is temporary.
Definition: Pointer.h:477
SourceLocation getDeclLoc() const
Definition: Pointer.h:289
const Block * block() const
Definition: Pointer.h:559
Pointer getDeclPtr() const
Definition: Pointer.h:348
std::optional< unsigned > getDeclID() const
Returns the declaration ID.
Definition: Pointer.h:535
bool isField() const
Checks if the item is a field in an object.
Definition: Pointer.h:271
unsigned getByteOffset() const
Returns the byte offset from the start.
Definition: Pointer.h:544
Structure/Class descriptor.
Definition: Record.h:25
bool isUnion() const
Checks if the record is a union.
Definition: Record.h:56
const CXXDestructorDecl * getDestructor() const
Returns the destructor of the record, if any.
Definition: Record.h:70
const Field * getField(const FieldDecl *FD) const
Returns a field.
Definition: Record.cpp:39
llvm::iterator_range< const_base_iter > bases() const
Definition: Record.h:85
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
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
Definition: Interp.cpp:568
bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B)
Definition: Interp.cpp:879
llvm::APInt APInt
Definition: Integral.h:29
bool Interpret(InterpState &S, APValue &Result)
Interpreter entry point.
Definition: Interp.cpp:929
static bool runRecordDestructor(InterpState &S, CodePtr OpPC, const Pointer &BasePtr, const Descriptor *Desc)
Definition: Interp.cpp:834
bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t Offset)
Checks if the dowcast using the given offset is possible with the given pointer.
Definition: Interp.cpp:384
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:781
bool CheckCallDepth(InterpState &S, CodePtr OpPC)
Checks if calling the currently active function would exceed the allowed call depth.
Definition: Interp.cpp:642
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks the 'this' pointer.
Definition: Interp.cpp:653
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Checks if the Descriptor is of a constexpr or const global variable.
Definition: Interp.cpp:302
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
Definition: Interp.cpp:432
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if Ptr is a one-past-the-end pointer.
Definition: Interp.cpp:373
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a value can be loaded from a block.
Definition: Interp.cpp:514
bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:471
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition: PrimType.h:104
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
Definition: Interp.cpp:353
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
Definition: Interp.cpp:671
bool This(InterpState &S, CodePtr OpPC)
Definition: Interp.h:2230
bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC)
Checks if dynamic memory allocation is available in the current language mode.
Definition: Interp.cpp:727
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
Definition: Interp.cpp:272
static void popArg(InterpState &S, const Expr *Arg)
Definition: Interp.cpp:193
void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED, const APSInt &Value)
Definition: Interp.cpp:904
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:33
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be stored in a block.
Definition: Interp.cpp:540
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
Definition: Interp.cpp:342
bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source, const Pointer &Ptr)
Check the source of the pointer passed to delete/delete[] has actually been heap allocated by us.
Definition: Interp.cpp:762
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
Definition: Interp.cpp:264
bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Check if a global variable is initialized.
Definition: Interp.cpp:497
bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *CE, unsigned ArgSize)
Checks if all the arguments annotated as 'nonnull' are in fact not null.
Definition: Interp.cpp:807
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is a dummy pointer.
Definition: Interp.cpp:786
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC)
Definition: Interp.cpp:198
bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:450
llvm::BitVector collectNonNullArgs(const FunctionDecl *F, const llvm::ArrayRef< const Expr * > &Args)
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
Definition: PrimType.cpp:23
llvm::APSInt APSInt
Definition: Floating.h:24
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
Definition: Interp.cpp:249
bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC, bool NewWasArray, bool DeleteIsArray, const Descriptor *D, const Expr *NewExpr)
Diagnose mismatched new[]/delete or new/delete[] pairs.
Definition: Interp.cpp:736
bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
Checks if a method can be called.
Definition: Interp.cpp:576
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
Definition: Interp.cpp:404
bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a method can be invoked on an object.
Definition: Interp.cpp:556
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:680
The JSON file list parser is used to communicate input to InstallAPI.
@ SC_Extern
Definition: Specifiers.h:248
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_Increment
Definition: State.h:30
@ AK_Read
Definition: State.h:27
@ AK_Assign
Definition: State.h:29
@ AK_MemberCall
Definition: State.h:32
@ AK_Decrement
Definition: State.h:31
const FunctionProtoType * T
#define bool
Definition: stdbool.h:24
Describes a memory block created by an allocation site.
Definition: Descriptor.h:107
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition: Descriptor.h:233
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition: Descriptor.h:247
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
Definition: Descriptor.h:240
const ValueDecl * asValueDecl() const
Definition: Descriptor.h:198
QualType getType() const
Definition: Descriptor.cpp:366
const Descriptor *const ElemDesc
Descriptor of the array element.
Definition: Descriptor.h:139
unsigned getMetadataSize() const
Returns the size of the metadata.
Definition: Descriptor.h:230
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition: Descriptor.h:238
const VarDecl * asVarDecl() const
Definition: Descriptor.h:202
bool isRecord() const
Checks if the descriptor is of a record.
Definition: Descriptor.h:252
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition: Descriptor.h:137