clang 19.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/Expr.h"
22#include "clang/AST/ExprCXX.h"
23#include "llvm/ADT/APSInt.h"
24#include <limits>
25#include <vector>
26
27using namespace clang;
28
29using namespace clang;
30using namespace clang::interp;
31
32static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) {
33 llvm::report_fatal_error("Interpreter cannot return values");
34}
35
36//===----------------------------------------------------------------------===//
37// Jmp, Jt, Jf
38//===----------------------------------------------------------------------===//
39
40static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
41 PC += Offset;
42 return true;
43}
44
45static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
46 if (S.Stk.pop<bool>()) {
47 PC += Offset;
48 }
49 return true;
50}
51
52static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
53 if (!S.Stk.pop<bool>()) {
54 PC += Offset;
55 }
56 return true;
57}
58
60 const ValueDecl *VD) {
61 const SourceInfo &E = S.Current->getSource(OpPC);
62 S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
63 S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
64}
65
67 const ValueDecl *VD);
69 const ValueDecl *D) {
70 const SourceInfo &E = S.Current->getSource(OpPC);
71
72 if (isa<ParmVarDecl>(D)) {
73 if (S.getLangOpts().CPlusPlus11) {
74 S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
75 S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
76 } else {
77 S.FFDiag(E);
78 }
79 } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
80 if (!VD->getType().isConstQualified()) {
81 diagnoseNonConstVariable(S, OpPC, VD);
82 return false;
83 }
84
85 // const, but no initializer.
86 if (!VD->getAnyInitializer()) {
87 diagnoseMissingInitializer(S, OpPC, VD);
88 return false;
89 }
90 }
91 return false;
92}
93
95 const ValueDecl *VD) {
96 if (!S.getLangOpts().CPlusPlus)
97 return;
98
99 const SourceInfo &Loc = S.Current->getSource(OpPC);
100 if (const auto *VarD = dyn_cast<VarDecl>(VD);
101 VarD && VarD->getType().isConstQualified() &&
102 !VarD->getAnyInitializer()) {
103 diagnoseMissingInitializer(S, OpPC, VD);
104 return;
105 }
106
108 S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
109 S.Note(VD->getLocation(), diag::note_declared_at);
110 return;
111 }
112
113 S.FFDiag(Loc,
114 S.getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
115 : diag::note_constexpr_ltor_non_integral,
116 1)
117 << VD << VD->getType();
118 S.Note(VD->getLocation(), diag::note_declared_at);
119}
120
121static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
122 AccessKinds AK) {
123 if (Ptr.isActive())
124 return true;
125
126 // Get the inactive field descriptor.
127 const FieldDecl *InactiveField = Ptr.getField();
128
129 // Walk up the pointer chain to find the union which is not active.
130 Pointer U = Ptr.getBase();
131 while (!U.isActive()) {
132 U = U.getBase();
133 }
134
135 // Find the active field of the union.
136 const Record *R = U.getRecord();
137 assert(R && R->isUnion() && "Not a union");
138 const FieldDecl *ActiveField = nullptr;
139 for (unsigned I = 0, N = R->getNumFields(); I < N; ++I) {
140 const Pointer &Field = U.atField(R->getField(I)->Offset);
141 if (Field.isActive()) {
142 ActiveField = Field.getField();
143 break;
144 }
145 }
146
147 const SourceInfo &Loc = S.Current->getSource(OpPC);
148 S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
149 << AK << InactiveField << !ActiveField << ActiveField;
150 return false;
151}
152
153static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
154 AccessKinds AK) {
155 if (auto ID = Ptr.getDeclID()) {
156 if (!Ptr.isStaticTemporary())
157 return true;
158
159 if (Ptr.getDeclDesc()->getType().isConstQualified())
160 return true;
161
162 if (S.P.getCurrentDecl() == ID)
163 return true;
164
165 const SourceInfo &E = S.Current->getSource(OpPC);
166 S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
167 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
168 return false;
169 }
170 return true;
171}
172
173static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
174 if (auto ID = Ptr.getDeclID()) {
175 if (!Ptr.isStatic())
176 return true;
177
178 if (S.P.getCurrentDecl() == ID)
179 return true;
180
181 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
182 return false;
183 }
184 return true;
185}
186
187namespace clang {
188namespace interp {
189static void popArg(InterpState &S, const Expr *Arg) {
190 PrimType Ty = S.getContext().classify(Arg).value_or(PT_Ptr);
191 TYPE_SWITCH(Ty, S.Stk.discard<T>());
192}
193
195 assert(S.Current);
196 const Function *CurFunc = S.Current->getFunction();
197 assert(CurFunc);
198
199 if (CurFunc->isUnevaluatedBuiltin())
200 return;
201
202 // Some builtin functions require us to only look at the call site, since
203 // the classified parameter types do not match.
204 if (CurFunc->isBuiltin()) {
205 const auto *CE =
206 cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
207 for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
208 const Expr *A = CE->getArg(I);
209 popArg(S, A);
210 }
211 return;
212 }
213
214 if (S.Current->Caller && CurFunc->isVariadic()) {
215 // CallExpr we're look for is at the return PC of the current function, i.e.
216 // in the caller.
217 // This code path should be executed very rarely.
218 unsigned NumVarArgs;
219 const Expr *const *Args = nullptr;
220 unsigned NumArgs = 0;
221 const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
222 if (const auto *CE = dyn_cast<CallExpr>(CallSite)) {
223 Args = CE->getArgs();
224 NumArgs = CE->getNumArgs();
225 } else if (const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
226 Args = CE->getArgs();
227 NumArgs = CE->getNumArgs();
228 } else
229 assert(false && "Can't get arguments from that expression type");
230
231 assert(NumArgs >= CurFunc->getNumWrittenParams());
232 NumVarArgs = NumArgs - CurFunc->getNumWrittenParams();
233 for (unsigned I = 0; I != NumVarArgs; ++I) {
234 const Expr *A = Args[NumArgs - 1 - I];
235 popArg(S, A);
236 }
237 }
238
239 // And in any case, remove the fixed parameters (the non-variadic ones)
240 // at the end.
241 S.Current->popArgs();
242}
243
244bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
245 if (!Ptr.isExtern())
246 return true;
247
248 if (Ptr.isInitialized())
249 return true;
250
251 if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
252 const auto *VD = Ptr.getDeclDesc()->asValueDecl();
253 diagnoseNonConstVariable(S, OpPC, VD);
254 }
255 return false;
256}
257
258bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
259 if (!Ptr.isUnknownSizeArray())
260 return true;
261 const SourceInfo &E = S.Current->getSource(OpPC);
262 S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
263 return false;
264}
265
266bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
267 AccessKinds AK) {
268 if (Ptr.isZero()) {
269 const auto &Src = S.Current->getSource(OpPC);
270
271 if (Ptr.isField())
272 S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
273 else
274 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
275
276 return false;
277 }
278
279 if (!Ptr.isLive()) {
280 const auto &Src = S.Current->getSource(OpPC);
281 bool IsTemp = Ptr.isTemporary();
282
283 S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
284
285 if (IsTemp)
286 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
287 else
288 S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
289
290 return false;
291 }
292
293 return true;
294}
295
296bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
297 assert(Desc);
298
299 auto IsConstType = [&S](const VarDecl *VD) -> bool {
300 if (VD->isConstexpr())
301 return true;
302
303 QualType T = VD->getType();
304 if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11)
306
307 if (T.isConstQualified())
308 return true;
309
310 if (const auto *RT = T->getAs<ReferenceType>())
311 return RT->getPointeeType().isConstQualified();
312
313 if (const auto *PT = T->getAs<PointerType>())
314 return PT->getPointeeType().isConstQualified();
315
316 return false;
317 };
318
319 if (const auto *D = Desc->asValueDecl()) {
320 if (const auto *VD = dyn_cast<VarDecl>(D);
321 VD && VD->hasGlobalStorage() && !IsConstType(VD)) {
322 diagnoseNonConstVariable(S, OpPC, VD);
323 return S.inConstantContext();
324 }
325 }
326
327 return true;
328}
329
330static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
331 if (Ptr.isIntegralPointer())
332 return true;
333 return CheckConstant(S, OpPC, Ptr.getDeclDesc());
334}
335
336bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
337 CheckSubobjectKind CSK) {
338 if (!Ptr.isZero())
339 return true;
340 const SourceInfo &Loc = S.Current->getSource(OpPC);
341 S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
342 return false;
343}
344
345bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
346 AccessKinds AK) {
347 if (!Ptr.isOnePastEnd())
348 return true;
349 const SourceInfo &Loc = S.Current->getSource(OpPC);
350 S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
351 return false;
352}
353
354bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
355 CheckSubobjectKind CSK) {
356 if (!Ptr.isElementPastEnd())
357 return true;
358 const SourceInfo &Loc = S.Current->getSource(OpPC);
359 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
360 return false;
361}
362
363bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
364 CheckSubobjectKind CSK) {
365 if (!Ptr.isOnePastEnd())
366 return true;
367
368 const SourceInfo &Loc = S.Current->getSource(OpPC);
369 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
370 return false;
371}
372
373bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
374 assert(Ptr.isLive() && "Pointer is not live");
375 if (!Ptr.isConst())
376 return true;
377
378 // The This pointer is writable in constructors and destructors,
379 // even if isConst() returns true.
380 if (const Function *Func = S.Current->getFunction();
381 Func && (Func->isConstructor() || Func->isDestructor()) &&
382 Ptr.block() == S.Current->getThis().block()) {
383 return true;
384 }
385
386 if (!Ptr.isBlockPointer())
387 return false;
388
389 const QualType Ty = Ptr.getType();
390 const SourceInfo &Loc = S.Current->getSource(OpPC);
391 S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
392 return false;
393}
394
395bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
396 assert(Ptr.isLive() && "Pointer is not live");
397 if (!Ptr.isMutable()) {
398 return true;
399 }
400
401 const SourceInfo &Loc = S.Current->getSource(OpPC);
402 const FieldDecl *Field = Ptr.getField();
403 S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
404 S.Note(Field->getLocation(), diag::note_declared_at);
405 return false;
406}
407
408bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
409 AccessKinds AK) {
410 assert(Ptr.isLive());
411
412 if (Ptr.isInitialized())
413 return true;
414
415 if (const auto *VD = Ptr.getDeclDesc()->asVarDecl();
416 VD && VD->hasGlobalStorage()) {
417 const SourceInfo &Loc = S.Current->getSource(OpPC);
418 if (VD->getAnyInitializer()) {
419 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
420 S.Note(VD->getLocation(), diag::note_declared_at);
421 } else {
422 diagnoseMissingInitializer(S, OpPC, VD);
423 }
424 return false;
425 }
426
427 if (!S.checkingPotentialConstantExpression()) {
428 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
429 << AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
430 }
431 return false;
432}
433
435 if (Ptr.isInitialized())
436 return true;
437
438 assert(S.getLangOpts().CPlusPlus);
439 const auto *VD = cast<VarDecl>(Ptr.getDeclDesc()->asValueDecl());
440 if ((!VD->hasConstantInitialization() &&
441 VD->mightBeUsableInConstantExpressions(S.getCtx())) ||
442 (S.getLangOpts().OpenCL && !S.getLangOpts().CPlusPlus11 &&
443 !VD->hasICEInitializer(S.getCtx()))) {
444 const SourceInfo &Loc = S.Current->getSource(OpPC);
445 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
446 S.Note(VD->getLocation(), diag::note_declared_at);
447 }
448 return false;
449}
450
451bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
452 if (!CheckLive(S, OpPC, Ptr, AK_Read))
453 return false;
454 if (!CheckConstant(S, OpPC, Ptr))
455 return false;
456
457 if (!CheckDummy(S, OpPC, Ptr))
458 return false;
459 if (!CheckExtern(S, OpPC, Ptr))
460 return false;
461 if (!CheckRange(S, OpPC, Ptr, AK_Read))
462 return false;
463 if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
464 return false;
465 if (!CheckActive(S, OpPC, Ptr, AK_Read))
466 return false;
467 if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
468 return false;
469 if (!CheckMutable(S, OpPC, Ptr))
470 return false;
471 return true;
472}
473
474bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
475 if (!CheckLive(S, OpPC, Ptr, AK_Assign))
476 return false;
477 if (!CheckDummy(S, OpPC, Ptr))
478 return false;
479 if (!CheckExtern(S, OpPC, Ptr))
480 return false;
481 if (!CheckRange(S, OpPC, Ptr, AK_Assign))
482 return false;
483 if (!CheckGlobal(S, OpPC, Ptr))
484 return false;
485 if (!CheckConst(S, OpPC, Ptr))
486 return false;
487 return true;
488}
489
490bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
491 if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
492 return false;
493 if (!CheckExtern(S, OpPC, Ptr))
494 return false;
495 if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
496 return false;
497 return true;
498}
499
500bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
501 if (!CheckLive(S, OpPC, Ptr, AK_Assign))
502 return false;
503 if (!CheckRange(S, OpPC, Ptr, AK_Assign))
504 return false;
505 return true;
506}
507
508bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
509
510 if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
511 const SourceLocation &Loc = S.Current->getLocation(OpPC);
512 S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
513 return false;
514 }
515
516 if (!F->isConstexpr()) {
517 const SourceLocation &Loc = S.Current->getLocation(OpPC);
518 if (S.getLangOpts().CPlusPlus11) {
519 const FunctionDecl *DiagDecl = F->getDecl();
520
521 // Invalid decls have been diagnosed before.
522 if (DiagDecl->isInvalidDecl())
523 return false;
524
525 // If this function is not constexpr because it is an inherited
526 // non-constexpr constructor, diagnose that directly.
527 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
528 if (CD && CD->isInheritingConstructor()) {
529 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
530 if (!Inherited->isConstexpr())
531 DiagDecl = CD = Inherited;
532 }
533
534 // FIXME: If DiagDecl is an implicitly-declared special member function
535 // or an inheriting constructor, we should be much more explicit about why
536 // it's not constexpr.
537 if (CD && CD->isInheritingConstructor()) {
538 S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
539 << CD->getInheritedConstructor().getConstructor()->getParent();
540 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
541 } else {
542 // Don't emit anything if the function isn't defined and we're checking
543 // for a constant expression. It might be defined at the point we're
544 // actually calling it.
545 bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
546 if (!DiagDecl->isDefined() && !IsExtern &&
547 S.checkingPotentialConstantExpression())
548 return false;
549
550 // If the declaration is defined _and_ declared 'constexpr', the below
551 // diagnostic doesn't add anything useful.
552 if (DiagDecl->isDefined() && DiagDecl->isConstexpr())
553 return false;
554
555 S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
556 << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
557 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
558 }
559 } else {
560 S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
561 }
562 return false;
563 }
564
565 return true;
566}
567
569 if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
570 S.FFDiag(S.Current->getSource(OpPC),
571 diag::note_constexpr_depth_limit_exceeded)
572 << S.getLangOpts().ConstexprCallDepth;
573 return false;
574 }
575
576 return true;
577}
578
579bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
580 if (!This.isZero())
581 return true;
582
583 const SourceInfo &Loc = S.Current->getSource(OpPC);
584
585 bool IsImplicit = false;
586 if (const auto *E = dyn_cast_if_present<CXXThisExpr>(Loc.asExpr()))
587 IsImplicit = E->isImplicit();
588
589 if (S.getLangOpts().CPlusPlus11)
590 S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
591 else
592 S.FFDiag(Loc);
593
594 return false;
595}
596
597bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
598 if (!MD->isPureVirtual())
599 return true;
600 const SourceInfo &E = S.Current->getSource(OpPC);
601 S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
602 S.Note(MD->getLocation(), diag::note_declared_at);
603 return false;
604}
605
607 APFloat::opStatus Status) {
608 const SourceInfo &E = S.Current->getSource(OpPC);
609
610 // [expr.pre]p4:
611 // If during the evaluation of an expression, the result is not
612 // mathematically defined [...], the behavior is undefined.
613 // FIXME: C++ rules require us to not conform to IEEE 754 here.
614 if (Result.isNan()) {
615 S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
616 << /*NaN=*/true << S.Current->getRange(OpPC);
617 return S.noteUndefinedBehavior();
618 }
619
620 // In a constant context, assume that any dynamic rounding mode or FP
621 // exception state matches the default floating-point environment.
622 if (S.inConstantContext())
623 return true;
624
626
627 if ((Status & APFloat::opInexact) &&
628 FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) {
629 // Inexact result means that it depends on rounding mode. If the requested
630 // mode is dynamic, the evaluation cannot be made in compile time.
631 S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
632 return false;
633 }
634
635 if ((Status != APFloat::opOK) &&
636 (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic ||
638 FPO.getAllowFEnvAccess())) {
639 S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
640 return false;
641 }
642
643 if ((Status & APFloat::opStatus::opInvalidOp) &&
645 // There is no usefully definable result.
646 S.FFDiag(E);
647 return false;
648 }
649
650 return true;
651}
652
653/// We aleady know the given DeclRefExpr is invalid for some reason,
654/// now figure out why and print appropriate diagnostics.
655bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
656 const ValueDecl *D = DR->getDecl();
657 return diagnoseUnknownDecl(S, OpPC, D);
658}
659
660bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
661 if (!Ptr.isDummy())
662 return true;
663
664 const Descriptor *Desc = Ptr.getDeclDesc();
665 const ValueDecl *D = Desc->asValueDecl();
666 if (!D)
667 return false;
668
669 return diagnoseUnknownDecl(S, OpPC, D);
670}
671
673 const CallExpr *CE, unsigned ArgSize) {
674 auto Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
675 auto NonNullArgs = collectNonNullArgs(F->getDecl(), Args);
676 unsigned Offset = 0;
677 unsigned Index = 0;
678 for (const Expr *Arg : Args) {
679 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
680 const Pointer &ArgPtr = S.Stk.peek<Pointer>(ArgSize - Offset);
681 if (ArgPtr.isZero()) {
682 const SourceLocation &Loc = S.Current->getLocation(OpPC);
683 S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
684 return false;
685 }
686 }
687
688 Offset += align(primSize(S.Ctx.classify(Arg).value_or(PT_Ptr)));
689 ++Index;
690 }
691 return true;
692}
693
695 // The current stack frame when we started Interpret().
696 // This is being used by the ops to determine wheter
697 // to return from this function and thus terminate
698 // interpretation.
699 const InterpFrame *StartFrame = S.Current;
700 assert(!S.Current->isRoot());
701 CodePtr PC = S.Current->getPC();
702
703 // Empty program.
704 if (!PC)
705 return true;
706
707 for (;;) {
708 auto Op = PC.read<Opcode>();
709 CodePtr OpPC = PC;
710
711 switch (Op) {
712#define GET_INTERP
713#include "Opcodes.inc"
714#undef GET_INTERP
715 }
716 }
717}
718
719} // namespace interp
720} // namespace clang
Defines the clang::ASTContext interface.
Defines the clang::Expr interface and subclasses for C++ expressions.
static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:40
static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:121
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition: Interp.cpp:173
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:153
static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:45
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
Definition: Interp.cpp:94
static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result)
Definition: Interp.cpp:32
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, const ValueDecl *D)
Definition: Interp.cpp:68
static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset)
Definition: Interp.cpp:52
static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
Definition: Interp.cpp:59
#define TYPE_SWITCH(Expr, B)
Definition: PrimType.h:117
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition: APValue.h:122
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2057
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2820
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:2998
Expr ** getArgs()
Retrieve the call arguments.
Definition: Expr.h:3001
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1260
ValueDecl * getDecl()
Definition: Expr.h:1328
bool isInvalidDecl() const
Definition: DeclBase.h:596
SourceLocation getLocation() const
Definition: DeclBase.h:447
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:435
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:3846
LangOptions::FPExceptionModeKind getExceptionMode() const
Definition: LangOptions.h:854
RoundingMode getRoundingMode() const
Definition: LangOptions.h:842
Represents a member of a struct/union/class.
Definition: Decl.h:3058
Represents a function declaration or definition.
Definition: Decl.h:1971
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition: Decl.h:2798
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2433
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
Definition: Decl.h:2323
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:3203
@ FPE_Ignore
Assume that floating-point exceptions are masked.
Definition: LangOptions.h:271
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:2929
A (possibly-)qualified type.
Definition: Type.h:738
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:7222
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3170
const LangOptions & getLangOpts() const
Definition: Sema.h:520
Encodes a location in the source.
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition: Type.cpp:2155
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
Definition: Type.cpp:2205
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:7810
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:7913
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:706
QualType getType() const
Definition: Decl.h:717
Represents a variable declaration or definition.
Definition: Decl.h:918
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1213
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:77
bool isBuiltin() const
Definition: Function.h:183
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
Definition: Function.h:92
bool isVirtual() const
Checks if the function is virtual.
Definition: Function.cpp:47
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 isVariadic() const
Definition: Function.h:179
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:80
bool isInitialized() const
Checks if an object was initialized.
Definition: Pointer.cpp:216
bool isStatic() const
Checks if the storage is static.
Definition: Pointer.h:449
bool isDummy() const
Checks if the pointer points to a dummy value.
Definition: Pointer.h:497
bool isExtern() const
Checks if the storage is extern.
Definition: Pointer.h:443
bool isActive() const
Checks if the object is active.
Definition: Pointer.h:487
bool isConst() const
Checks if an object or a subfield is mutable.
Definition: Pointer.h:508
bool isMutable() const
Checks if the field is mutable.
Definition: Pointer.h:467
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition: Pointer.h:387
bool isIntegralPointer() const
Definition: Pointer.h:427
QualType getType() const
Returns the type of the innermost field.
Definition: Pointer.h:318
bool isLive() const
Checks if the pointer is live.
Definition: Pointer.h:250
bool isStaticTemporary() const
Checks if the storage is a static temporary.
Definition: Pointer.h:464
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition: Pointer.h:286
bool isZero() const
Checks if the pointer is null.
Definition: Pointer.h:243
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition: Pointer.h:266
bool isOnePastEnd() const
Checks if the index is one past end.
Definition: Pointer.h:564
const FieldDecl * getField() const
Returns the field information.
Definition: Pointer.h:437
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
Definition: Pointer.h:574
bool isBlockPointer() const
Definition: Pointer.h:426
bool isTemporary() const
Checks if the storage is temporary.
Definition: Pointer.h:456
SourceLocation getDeclLoc() const
Definition: Pointer.h:274
const Block * block() const
Definition: Pointer.h:540
std::optional< unsigned > getDeclID() const
Returns the declaration ID.
Definition: Pointer.h:518
bool isField() const
Checks if the item is a field in an object.
Definition: Pointer.h:256
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:39
unsigned getNumFields() const
Definition: Record.h:81
Describes the statement/declaration an opcode was generated from.
Definition: Source.h:72
const Expr * asExpr() const
Definition: Source.cpp:35
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
Definition: Interp.cpp:500
bool Interpret(InterpState &S, APValue &Result)
Interpreter entry point.
Definition: Interp.cpp:694
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:655
bool CheckCallDepth(InterpState &S, CodePtr OpPC)
Checks if calling the currently active function would exceed the allowed call depth.
Definition: Interp.cpp:568
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks the 'this' pointer.
Definition: Interp.cpp:579
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Checks if the Descriptor is of a constexpr or const global variable.
Definition: Interp.cpp:296
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
Definition: Interp.cpp:395
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if Ptr is a one-past-the-end pointer.
Definition: Interp.cpp:363
bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition: Interp.cpp:408
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition: PrimType.h:99
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
Definition: Interp.cpp:345
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
Definition: Interp.cpp:597
bool This(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1893
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
Definition: Interp.cpp:266
static void popArg(InterpState &S, const Expr *Arg)
Definition: Interp.cpp:189
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:474
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
Definition: Interp.cpp:336
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be loaded from a block.
Definition: Interp.cpp:451
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
Definition: Interp.cpp:258
bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Check if a global variable is initialized.
Definition: Interp.cpp:434
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:672
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC)
Definition: Interp.cpp:194
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:22
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
Definition: Interp.cpp:244
bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
Checks if a method can be called.
Definition: Interp.cpp:508
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer is a dummy pointer.
Definition: Interp.cpp:660
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
Definition: Interp.cpp:373
bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a method can be invoked on an object.
Definition: Interp.cpp:490
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:606
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_Read
Definition: State.h:27
@ AK_Assign
Definition: State.h:29
@ AK_MemberCall
Definition: State.h:32
const FunctionProtoType * T
#define bool
Definition: stdbool.h:20
Describes a memory block created by an allocation site.
Definition: Descriptor.h:88
const ValueDecl * asValueDecl() const
Definition: Descriptor.h:173
QualType getType() const
Definition: Descriptor.cpp:320
const VarDecl * asVarDecl() const
Definition: Descriptor.h:177