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