clang 22.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 "Compiler.h"
11#include "Function.h"
12#include "InterpFrame.h"
13#include "InterpShared.h"
14#include "InterpStack.h"
15#include "Opcode.h"
16#include "PrimType.h"
17#include "Program.h"
18#include "State.h"
21#include "clang/AST/DeclObjC.h"
22#include "clang/AST/Expr.h"
23#include "clang/AST/ExprCXX.h"
26#include "llvm/ADT/StringExtras.h"
27
28using namespace clang;
29using namespace clang::interp;
30
31static bool RetValue(InterpState &S, CodePtr &Pt) {
32 llvm::report_fatal_error("Interpreter cannot return values");
33}
34
35//===----------------------------------------------------------------------===//
36// Jmp, Jt, Jf
37//===----------------------------------------------------------------------===//
38
39static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
40 PC += Offset;
41 return true;
42}
43
44static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
45 if (S.Stk.pop<bool>()) {
46 PC += Offset;
47 }
48 return true;
49}
50
51static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
52 if (!S.Stk.pop<bool>()) {
53 PC += Offset;
54 }
55 return true;
56}
57
58// https://github.com/llvm/llvm-project/issues/102513
59#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
60#pragma optimize("", off)
61#endif
62// FIXME: We have the large switch over all opcodes here again, and in
63// Interpret().
64static bool BCP(InterpState &S, CodePtr &RealPC, int32_t Offset, PrimType PT) {
65 [[maybe_unused]] CodePtr PCBefore = RealPC;
66 size_t StackSizeBefore = S.Stk.size();
67
68 auto SpeculativeInterp = [&S, RealPC]() -> bool {
69 const InterpFrame *StartFrame = S.Current;
70 CodePtr PC = RealPC;
71
72 for (;;) {
73 auto Op = PC.read<Opcode>();
74 if (Op == OP_EndSpeculation)
75 return true;
76 CodePtr OpPC = PC;
77
78 switch (Op) {
79#define GET_INTERP
80#include "Opcodes.inc"
81#undef GET_INTERP
82 }
83 }
84 llvm_unreachable("We didn't see an EndSpeculation op?");
85 };
86
87 if (SpeculativeInterp()) {
88 if (PT == PT_Ptr) {
89 const auto &Ptr = S.Stk.pop<Pointer>();
90 assert(S.Stk.size() == StackSizeBefore);
93 } else {
94 // Pop the result from the stack and return success.
95 TYPE_SWITCH(PT, S.Stk.pop<T>(););
96 assert(S.Stk.size() == StackSizeBefore);
98 }
99 } else {
100 if (!S.inConstantContext())
101 return Invalid(S, RealPC);
102
103 S.Stk.clearTo(StackSizeBefore);
105 }
106
107 // RealPC should not have been modified.
108 assert(*RealPC == *PCBefore);
109
110 // Jump to end label. This is a little tricker than just RealPC += Offset
111 // because our usual jump instructions don't have any arguments, to the offset
112 // we get is a little too much and we need to subtract the size of the
113 // bool and PrimType arguments again.
114 int32_t ParamSize = align(sizeof(PrimType));
115 assert(Offset >= ParamSize);
116 RealPC += Offset - ParamSize;
117
118 [[maybe_unused]] CodePtr PCCopy = RealPC;
119 assert(PCCopy.read<Opcode>() == OP_EndSpeculation);
120
121 return true;
122}
123// https://github.com/llvm/llvm-project/issues/102513
124#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
125#pragma optimize("", on)
126#endif
127
129 const ValueDecl *VD) {
130 const SourceInfo &E = S.Current->getSource(OpPC);
131 S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
132 S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
133}
134
135static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
136 const ValueDecl *VD);
138 const ValueDecl *D) {
139 // This function tries pretty hard to produce a good diagnostic. Just skip
140 // tha if nobody will see it anyway.
141 if (!S.diagnosing())
142 return false;
143
144 if (isa<ParmVarDecl>(D)) {
145 if (D->getType()->isReferenceType()) {
146 if (S.inConstantContext() && S.getLangOpts().CPlusPlus &&
147 !S.getLangOpts().CPlusPlus11)
148 diagnoseNonConstVariable(S, OpPC, D);
149 return false;
150 }
151
152 const SourceInfo &Loc = S.Current->getSource(OpPC);
153 if (S.getLangOpts().CPlusPlus11) {
154 S.FFDiag(Loc, diag::note_constexpr_function_param_value_unknown) << D;
155 S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
156 } else {
157 S.FFDiag(Loc);
158 }
159 return false;
160 }
161
162 if (!D->getType().isConstQualified()) {
163 diagnoseNonConstVariable(S, OpPC, D);
164 } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
165 if (!VD->getAnyInitializer()) {
166 diagnoseMissingInitializer(S, OpPC, VD);
167 } else {
168 const SourceInfo &Loc = S.Current->getSource(OpPC);
169 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
170 S.Note(VD->getLocation(), diag::note_declared_at);
171 }
172 }
173
174 return false;
175}
176
178 const ValueDecl *VD) {
179 if (!S.diagnosing())
180 return;
181
182 const SourceInfo &Loc = S.Current->getSource(OpPC);
183 if (!S.getLangOpts().CPlusPlus) {
184 S.FFDiag(Loc);
185 return;
186 }
187
188 if (const auto *VarD = dyn_cast<VarDecl>(VD);
189 VarD && VarD->getType().isConstQualified() &&
190 !VarD->getAnyInitializer()) {
191 diagnoseMissingInitializer(S, OpPC, VD);
192 return;
193 }
194
195 // Rather random, but this is to match the diagnostic output of the current
196 // interpreter.
197 if (isa<ObjCIvarDecl>(VD))
198 return;
199
201 S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
202 S.Note(VD->getLocation(), diag::note_declared_at);
203 return;
204 }
205
206 S.FFDiag(Loc,
207 S.getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
208 : diag::note_constexpr_ltor_non_integral,
209 1)
210 << VD << VD->getType();
211 S.Note(VD->getLocation(), diag::note_declared_at);
212}
213
214static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Block *B,
215 AccessKinds AK) {
216 if (B->getDeclID()) {
217 if (!(B->isStatic() && B->isTemporary()))
218 return true;
219
220 const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
221 B->getDescriptor()->asExpr());
222 if (!MTE)
223 return true;
224
225 // FIXME(perf): Since we do this check on every Load from a static
226 // temporary, it might make sense to cache the value of the
227 // isUsableInConstantExpressions call.
228 if (B->getEvalID() != S.Ctx.getEvalID() &&
229 !MTE->isUsableInConstantExpressions(S.getASTContext())) {
230 const SourceInfo &E = S.Current->getSource(OpPC);
231 S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
233 diag::note_constexpr_temporary_here);
234 return false;
235 }
236 }
237 return true;
238}
239
240static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
241 if (auto ID = Ptr.getDeclID()) {
242 if (!Ptr.isStatic())
243 return true;
244
245 if (S.P.getCurrentDecl() == ID)
246 return true;
247
248 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
249 return false;
250 }
251 return true;
252}
253
254namespace clang {
255namespace interp {
256static void popArg(InterpState &S, const Expr *Arg) {
258 TYPE_SWITCH(Ty, S.Stk.discard<T>());
259}
260
262 const Function *Func) {
263 assert(S.Current);
264 assert(Func);
265
266 if (S.Current->Caller && Func->isVariadic()) {
267 // CallExpr we're look for is at the return PC of the current function, i.e.
268 // in the caller.
269 // This code path should be executed very rarely.
270 unsigned NumVarArgs;
271 const Expr *const *Args = nullptr;
272 unsigned NumArgs = 0;
273 const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
274 if (const auto *CE = dyn_cast<CallExpr>(CallSite)) {
275 Args = CE->getArgs();
276 NumArgs = CE->getNumArgs();
277 } else if (const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
278 Args = CE->getArgs();
279 NumArgs = CE->getNumArgs();
280 } else
281 assert(false && "Can't get arguments from that expression type");
282
283 assert(NumArgs >= Func->getNumWrittenParams());
284 NumVarArgs = NumArgs - (Func->getNumWrittenParams() +
285 isa<CXXOperatorCallExpr>(CallSite));
286 for (unsigned I = 0; I != NumVarArgs; ++I) {
287 const Expr *A = Args[NumArgs - 1 - I];
288 popArg(S, A);
289 }
290 }
291
292 // And in any case, remove the fixed parameters (the non-variadic ones)
293 // at the end.
294 for (PrimType Ty : Func->args_reverse())
295 TYPE_SWITCH(Ty, S.Stk.discard<T>());
296}
297
299 if (!P.isBlockPointer())
300 return false;
301
302 if (P.isDummy())
303 return isa_and_nonnull<ParmVarDecl>(P.getDeclDesc()->asValueDecl());
304
306}
307
308bool CheckBCPResult(InterpState &S, const Pointer &Ptr) {
309 if (Ptr.isDummy())
310 return false;
311 if (Ptr.isZero())
312 return true;
313 if (Ptr.isFunctionPointer())
314 return false;
315 if (Ptr.isIntegralPointer())
316 return true;
317 if (Ptr.isTypeidPointer())
318 return true;
319
320 if (Ptr.getType()->isAnyComplexType())
321 return true;
322
323 if (const Expr *Base = Ptr.getDeclDesc()->asExpr())
324 return isa<StringLiteral>(Base) && Ptr.getIndex() == 0;
325 return false;
326}
327
328bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
329 AccessKinds AK, bool WillActivate) {
330 if (Ptr.isActive())
331 return true;
332
333 assert(Ptr.inUnion());
334
335 // Find the outermost union.
336 Pointer U = Ptr.getBase();
337 Pointer C = Ptr;
338 while (!U.isRoot() && !U.isActive()) {
339 // A little arbitrary, but this is what the current interpreter does.
340 // See the AnonymousUnion test in test/AST/ByteCode/unions.cpp.
341 // GCC's output is more similar to what we would get without
342 // this condition.
343 if (U.getRecord() && U.getRecord()->isAnonymousUnion())
344 break;
345
346 C = U;
347 U = U.getBase();
348 }
349 assert(C.isField());
350 assert(C.getBase() == U);
351
352 // Consider:
353 // union U {
354 // struct {
355 // int x;
356 // int y;
357 // } a;
358 // }
359 //
360 // When activating x, we will also activate a. If we now try to read
361 // from y, we will get to CheckActive, because y is not active. In that
362 // case, our U will be a (not a union). We return here and let later code
363 // handle this.
364 if (!U.getFieldDesc()->isUnion())
365 return true;
366
367 // When we will activate Ptr, check that none of the unions in its path have a
368 // non-trivial default constructor.
369 if (WillActivate) {
370 bool Fails = false;
371 Pointer It = Ptr;
372 while (!It.isRoot() && !It.isActive()) {
373 if (const Record *R = It.getRecord(); R && R->isUnion()) {
374 if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(R->getDecl());
375 CXXRD && !CXXRD->hasTrivialDefaultConstructor()) {
376 Fails = true;
377 break;
378 }
379 }
380 It = It.getBase();
381 }
382 if (!Fails)
383 return true;
384 }
385
386 // Get the inactive field descriptor.
387 assert(!C.isActive());
388 const FieldDecl *InactiveField = C.getField();
389 assert(InactiveField);
390
391 // Find the active field of the union.
392 const Record *R = U.getRecord();
393 assert(R && R->isUnion() && "Not a union");
394
395 const FieldDecl *ActiveField = nullptr;
396 for (const Record::Field &F : R->fields()) {
397 const Pointer &Field = U.atField(F.Offset);
398 if (Field.isActive()) {
399 ActiveField = Field.getField();
400 break;
401 }
402 }
403
404 const SourceInfo &Loc = S.Current->getSource(OpPC);
405 S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
406 << AK << InactiveField << !ActiveField << ActiveField;
407 return false;
408}
409
410bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
411 if (!Ptr.isExtern())
412 return true;
413
414 if (!Ptr.isPastEnd() &&
415 (Ptr.isInitialized() ||
416 (Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl)))
417 return true;
418
419 if (S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus &&
420 Ptr.isConst())
421 return false;
422
423 const auto *VD = Ptr.getDeclDesc()->asValueDecl();
424 diagnoseNonConstVariable(S, OpPC, VD);
425 return false;
426}
427
428bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
429 if (!Ptr.isUnknownSizeArray())
430 return true;
431 const SourceInfo &E = S.Current->getSource(OpPC);
432 S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
433 return false;
434}
435
436bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
437 AccessKinds AK) {
438 if (Ptr.isZero()) {
439 const auto &Src = S.Current->getSource(OpPC);
440
441 if (Ptr.isField())
442 S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
443 else
444 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
445
446 return false;
447 }
448
449 if (!Ptr.isLive()) {
450 const auto &Src = S.Current->getSource(OpPC);
451
452 if (Ptr.isDynamic()) {
453 S.FFDiag(Src, diag::note_constexpr_access_deleted_object) << AK;
454 } else if (!S.checkingPotentialConstantExpression()) {
455 bool IsTemp = Ptr.isTemporary();
456 S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
457
458 if (IsTemp)
459 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
460 else
461 S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
462 }
463
464 return false;
465 }
466
467 return true;
468}
469
470bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
471 assert(Desc);
472
473 const auto *D = Desc->asVarDecl();
474 if (!D || D == S.EvaluatingDecl || D->isConstexpr())
475 return true;
476
477 // If we're evaluating the initializer for a constexpr variable in C23, we may
478 // only read other contexpr variables. Abort here since this one isn't
479 // constexpr.
480 if (const auto *VD = dyn_cast_if_present<VarDecl>(S.EvaluatingDecl);
481 VD && VD->isConstexpr() && S.getLangOpts().C23)
482 return Invalid(S, OpPC);
483
484 QualType T = D->getType();
485 bool IsConstant = T.isConstant(S.getASTContext());
486 if (T->isIntegralOrEnumerationType()) {
487 if (!IsConstant) {
488 diagnoseNonConstVariable(S, OpPC, D);
489 return false;
490 }
491 return true;
492 }
493
494 if (IsConstant) {
495 if (S.getLangOpts().CPlusPlus) {
496 S.CCEDiag(S.Current->getLocation(OpPC),
497 S.getLangOpts().CPlusPlus11
498 ? diag::note_constexpr_ltor_non_constexpr
499 : diag::note_constexpr_ltor_non_integral,
500 1)
501 << D << T;
502 S.Note(D->getLocation(), diag::note_declared_at);
503 } else {
504 S.CCEDiag(S.Current->getLocation(OpPC));
505 }
506 return true;
507 }
508
509 if (T->isPointerOrReferenceType()) {
510 if (!T->getPointeeType().isConstant(S.getASTContext()) ||
511 !S.getLangOpts().CPlusPlus11) {
512 diagnoseNonConstVariable(S, OpPC, D);
513 return false;
514 }
515 return true;
516 }
517
518 diagnoseNonConstVariable(S, OpPC, D);
519 return false;
520}
521
522static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
523 if (!Ptr.isStatic() || !Ptr.isBlockPointer())
524 return true;
525 if (!Ptr.getDeclID())
526 return true;
527 return CheckConstant(S, OpPC, Ptr.getDeclDesc());
528}
529
530bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
531 CheckSubobjectKind CSK) {
532 if (!Ptr.isZero())
533 return true;
534 const SourceInfo &Loc = S.Current->getSource(OpPC);
535 S.FFDiag(Loc, diag::note_constexpr_null_subobject)
536 << CSK << S.Current->getRange(OpPC);
537
538 return false;
539}
540
541bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
542 AccessKinds AK) {
543 if (!Ptr.isOnePastEnd() && !Ptr.isZeroSizeArray())
544 return true;
545 if (S.getLangOpts().CPlusPlus) {
546 const SourceInfo &Loc = S.Current->getSource(OpPC);
547 S.FFDiag(Loc, diag::note_constexpr_access_past_end)
548 << AK << S.Current->getRange(OpPC);
549 }
550 return false;
551}
552
553bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
554 CheckSubobjectKind CSK) {
555 if (!Ptr.isElementPastEnd() && !Ptr.isZeroSizeArray())
556 return true;
557 const SourceInfo &Loc = S.Current->getSource(OpPC);
558 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
559 << CSK << S.Current->getRange(OpPC);
560 return false;
561}
562
563bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
564 CheckSubobjectKind CSK) {
565 if (!Ptr.isOnePastEnd())
566 return true;
567
568 const SourceInfo &Loc = S.Current->getSource(OpPC);
569 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
570 << CSK << S.Current->getRange(OpPC);
571 return false;
572}
573
574bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
575 uint32_t Offset) {
576 uint32_t MinOffset = Ptr.getDeclDesc()->getMetadataSize();
577 uint32_t PtrOffset = Ptr.getByteOffset();
578
579 // We subtract Offset from PtrOffset. The result must be at least
580 // MinOffset.
581 if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
582 return true;
583
584 const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
585 QualType TargetQT = E->getType()->getPointeeType();
586 QualType MostDerivedQT = Ptr.getDeclPtr().getType();
587
588 S.CCEDiag(E, diag::note_constexpr_invalid_downcast)
589 << MostDerivedQT << TargetQT;
590
591 return false;
592}
593
594bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
595 assert(Ptr.isLive() && "Pointer is not live");
596 if (!Ptr.isConst())
597 return true;
598
599 if (Ptr.isMutable() && !Ptr.isConstInMutable())
600 return true;
601
602 if (!Ptr.isBlockPointer())
603 return false;
604
605 // The This pointer is writable in constructors and destructors,
606 // even if isConst() returns true.
607 if (llvm::is_contained(S.InitializingBlocks, Ptr.block()))
608 return true;
609
610 const QualType Ty = Ptr.getType();
611 const SourceInfo &Loc = S.Current->getSource(OpPC);
612 S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
613 return false;
614}
615
616bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
617 assert(Ptr.isLive() && "Pointer is not live");
618 if (!Ptr.isMutable())
619 return true;
620
621 // In C++14 onwards, it is permitted to read a mutable member whose
622 // lifetime began within the evaluation.
623 if (S.getLangOpts().CPlusPlus14 &&
624 Ptr.block()->getEvalID() == S.Ctx.getEvalID()) {
625 // FIXME: This check is necessary because (of the way) we revisit
626 // variables in Compiler.cpp:visitDeclRef. Revisiting a so far
627 // unknown variable will get the same EvalID and we end up allowing
628 // reads from mutable members of it.
629 if (!S.inConstantContext() && isConstexprUnknown(Ptr))
630 return false;
631 return true;
632 }
633
634 const SourceInfo &Loc = S.Current->getSource(OpPC);
635 const FieldDecl *Field = Ptr.getField();
636 S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
637 S.Note(Field->getLocation(), diag::note_declared_at);
638 return false;
639}
640
641static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
642 AccessKinds AK) {
643 assert(Ptr.isLive());
644
645 if (!Ptr.isVolatile())
646 return true;
647
648 if (!S.getLangOpts().CPlusPlus)
649 return Invalid(S, OpPC);
650
651 // Volatile object can be written-to and read if they are being constructed.
652 if (llvm::is_contained(S.InitializingBlocks, Ptr.block()))
653 return true;
654
655 // The reason why Ptr is volatile might be further up the hierarchy.
656 // Find that pointer.
657 Pointer P = Ptr;
658 while (!P.isRoot()) {
660 break;
661 P = P.getBase();
662 }
663
664 const NamedDecl *ND = nullptr;
665 int DiagKind;
666 SourceLocation Loc;
667 if (const auto *F = P.getField()) {
668 DiagKind = 2;
669 Loc = F->getLocation();
670 ND = F;
671 } else if (auto *VD = P.getFieldDesc()->asValueDecl()) {
672 DiagKind = 1;
673 Loc = VD->getLocation();
674 ND = VD;
675 } else {
676 DiagKind = 0;
677 if (const auto *E = P.getFieldDesc()->asExpr())
678 Loc = E->getExprLoc();
679 }
680
681 S.FFDiag(S.Current->getLocation(OpPC),
682 diag::note_constexpr_access_volatile_obj, 1)
683 << AK << DiagKind << ND;
684 S.Note(Loc, diag::note_constexpr_volatile_here) << DiagKind;
685 return false;
686}
687
689 AccessKinds AK) {
690 assert(Ptr.isLive());
691 assert(!Ptr.isInitialized());
692 return DiagnoseUninitialized(S, OpPC, Ptr.isExtern(), Ptr.getDeclDesc(), AK);
693}
694
695bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern,
696 const Descriptor *Desc, AccessKinds AK) {
697 if (Extern && S.checkingPotentialConstantExpression())
698 return false;
699
700 if (const auto *VD = Desc->asVarDecl();
701 VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
702
703 if (VD == S.EvaluatingDecl &&
704 !(S.getLangOpts().CPlusPlus23 && VD->getType()->isReferenceType())) {
705 if (!S.getLangOpts().CPlusPlus14 &&
706 !VD->getType().isConstant(S.getASTContext())) {
707 // Diagnose as non-const read.
708 diagnoseNonConstVariable(S, OpPC, VD);
709 } else {
710 const SourceInfo &Loc = S.Current->getSource(OpPC);
711 // Diagnose as "read of object outside its lifetime".
712 S.FFDiag(Loc, diag::note_constexpr_access_uninit)
713 << AK << /*IsIndeterminate=*/false;
714 }
715 return false;
716 }
717
718 if (VD->getAnyInitializer()) {
719 const SourceInfo &Loc = S.Current->getSource(OpPC);
720 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
721 S.Note(VD->getLocation(), diag::note_declared_at);
722 } else {
723 diagnoseMissingInitializer(S, OpPC, VD);
724 }
725 return false;
726 }
727
729 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
730 << AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
731 }
732 return false;
733}
734
736 AccessKinds AK) {
737 if (LT == Lifetime::Started)
738 return true;
739
741 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
742 << AK << /*uninitialized=*/false << S.Current->getRange(OpPC);
743 }
744 return false;
745}
746
747static bool CheckWeak(InterpState &S, CodePtr OpPC, const Block *B) {
748 if (!B->isWeak())
749 return true;
750
751 const auto *VD = B->getDescriptor()->asVarDecl();
752 assert(VD);
753 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_var_init_weak)
754 << VD;
755 S.Note(VD->getLocation(), diag::note_declared_at);
756
757 return false;
758}
759
760// The list of checks here is just the one from CheckLoad, but with the
761// ones removed that are impossible on primitive global values.
762// For example, since those can't be members of structs, they also can't
763// be mutable.
764bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
765 const auto &Desc = B->getBlockDesc<GlobalInlineDescriptor>();
766 if (!B->isAccessible()) {
767 if (!CheckExtern(S, OpPC, Pointer(const_cast<Block *>(B))))
768 return false;
769 if (!CheckDummy(S, OpPC, B, AK_Read))
770 return false;
771 return CheckWeak(S, OpPC, B);
772 }
773
774 if (!CheckConstant(S, OpPC, B->getDescriptor()))
775 return false;
776 if (Desc.InitState != GlobalInitState::Initialized)
777 return DiagnoseUninitialized(S, OpPC, B->isExtern(), B->getDescriptor(),
778 AK_Read);
779 if (!CheckTemporary(S, OpPC, B, AK_Read))
780 return false;
781 if (B->getDescriptor()->IsVolatile) {
782 if (!S.getLangOpts().CPlusPlus)
783 return Invalid(S, OpPC);
784
785 const ValueDecl *D = B->getDescriptor()->asValueDecl();
786 S.FFDiag(S.Current->getLocation(OpPC),
787 diag::note_constexpr_access_volatile_obj, 1)
788 << AK_Read << 1 << D;
789 S.Note(D->getLocation(), diag::note_constexpr_volatile_here) << 1;
790 return false;
791 }
792 return true;
793}
794
795// Similarly, for local loads.
796bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
797 assert(!B->isExtern());
798 const auto &Desc = *reinterpret_cast<const InlineDescriptor *>(B->rawData());
799 if (!CheckLifetime(S, OpPC, Desc.LifeState, AK_Read))
800 return false;
801 if (!Desc.IsInitialized)
802 return DiagnoseUninitialized(S, OpPC, /*Extern=*/false, B->getDescriptor(),
803 AK_Read);
804 if (B->getDescriptor()->IsVolatile) {
805 if (!S.getLangOpts().CPlusPlus)
806 return Invalid(S, OpPC);
807
808 const ValueDecl *D = B->getDescriptor()->asValueDecl();
809 S.FFDiag(S.Current->getLocation(OpPC),
810 diag::note_constexpr_access_volatile_obj, 1)
811 << AK_Read << 1 << D;
812 S.Note(D->getLocation(), diag::note_constexpr_volatile_here) << 1;
813 return false;
814 }
815 return true;
816}
817
818bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
819 AccessKinds AK) {
820 if (Ptr.isZero()) {
821 const auto &Src = S.Current->getSource(OpPC);
822
823 if (Ptr.isField())
824 S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
825 else
826 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
827 return false;
828 }
829 // Block pointers are the only ones we can actually read from.
830 if (!Ptr.isBlockPointer())
831 return false;
832
833 if (!Ptr.block()->isAccessible()) {
834 if (!CheckLive(S, OpPC, Ptr, AK))
835 return false;
836 if (!CheckExtern(S, OpPC, Ptr))
837 return false;
838 if (!CheckDummy(S, OpPC, Ptr.block(), AK))
839 return false;
840 return CheckWeak(S, OpPC, Ptr.block());
841 }
842
843 if (!CheckConstant(S, OpPC, Ptr))
844 return false;
845 if (!CheckRange(S, OpPC, Ptr, AK))
846 return false;
847 if (!CheckActive(S, OpPC, Ptr, AK))
848 return false;
849 if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK))
850 return false;
851 if (!Ptr.isInitialized())
852 return DiagnoseUninitialized(S, OpPC, Ptr, AK);
853 if (!CheckTemporary(S, OpPC, Ptr.block(), AK))
854 return false;
855
856 if (!CheckMutable(S, OpPC, Ptr))
857 return false;
858 if (!CheckVolatile(S, OpPC, Ptr, AK))
859 return false;
860 if (!Ptr.isConst() && !S.inConstantContext() && isConstexprUnknown(Ptr))
861 return false;
862 return true;
863}
864
865/// This is not used by any of the opcodes directly. It's used by
866/// EvalEmitter to do the final lvalue-to-rvalue conversion.
867bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
868 assert(!Ptr.isZero());
869 if (!Ptr.isBlockPointer())
870 return false;
871
872 if (!Ptr.block()->isAccessible()) {
873 if (!CheckLive(S, OpPC, Ptr, AK_Read))
874 return false;
875 if (!CheckExtern(S, OpPC, Ptr))
876 return false;
877 if (!CheckDummy(S, OpPC, Ptr.block(), AK_Read))
878 return false;
879 return CheckWeak(S, OpPC, Ptr.block());
880 }
881
882 if (!CheckConstant(S, OpPC, Ptr))
883 return false;
884
885 if (!CheckActive(S, OpPC, Ptr, AK_Read))
886 return false;
887 if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK_Read))
888 return false;
889 if (!Ptr.isInitialized())
890 return DiagnoseUninitialized(S, OpPC, Ptr, AK_Read);
891 if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Read))
892 return false;
893 if (!CheckMutable(S, OpPC, Ptr))
894 return false;
895 return true;
896}
897
898bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
899 bool WillBeActivated) {
900 if (!Ptr.isBlockPointer() || Ptr.isZero())
901 return false;
902
903 if (!Ptr.block()->isAccessible()) {
904 if (!CheckLive(S, OpPC, Ptr, AK_Assign))
905 return false;
906 if (!CheckExtern(S, OpPC, Ptr))
907 return false;
908 return CheckDummy(S, OpPC, Ptr.block(), AK_Assign);
909 }
910 if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK_Assign))
911 return false;
912 if (!CheckRange(S, OpPC, Ptr, AK_Assign))
913 return false;
914 if (!CheckActive(S, OpPC, Ptr, AK_Assign, WillBeActivated))
915 return false;
916 if (!CheckGlobal(S, OpPC, Ptr))
917 return false;
918 if (!CheckConst(S, OpPC, Ptr))
919 return false;
920 if (!CheckVolatile(S, OpPC, Ptr, AK_Assign))
921 return false;
922 if (!S.inConstantContext() && isConstexprUnknown(Ptr))
923 return false;
924 return true;
925}
926
927static bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
928 if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
929 return false;
930 if (!Ptr.isDummy()) {
931 if (!CheckExtern(S, OpPC, Ptr))
932 return false;
933 if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
934 return false;
935 }
936 return true;
937}
938
939bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
940 if (!CheckLive(S, OpPC, Ptr, AK_Assign))
941 return false;
942 if (!CheckRange(S, OpPC, Ptr, AK_Assign))
943 return false;
944 return true;
945}
946
948 const FunctionDecl *DiagDecl) {
949 // Bail out if the function declaration itself is invalid. We will
950 // have produced a relevant diagnostic while parsing it, so just
951 // note the problematic sub-expression.
952 if (DiagDecl->isInvalidDecl())
953 return Invalid(S, OpPC);
954
955 // Diagnose failed assertions specially.
956 if (S.Current->getLocation(OpPC).isMacroID() && DiagDecl->getIdentifier()) {
957 // FIXME: Instead of checking for an implementation-defined function,
958 // check and evaluate the assert() macro.
959 StringRef Name = DiagDecl->getName();
960 bool AssertFailed =
961 Name == "__assert_rtn" || Name == "__assert_fail" || Name == "_wassert";
962 if (AssertFailed) {
963 S.FFDiag(S.Current->getLocation(OpPC),
964 diag::note_constexpr_assert_failed);
965 return false;
966 }
967 }
968
969 if (!S.getLangOpts().CPlusPlus11) {
970 S.FFDiag(S.Current->getLocation(OpPC),
971 diag::note_invalid_subexpr_in_const_expr);
972 return false;
973 }
974
975 // Invalid decls have been diagnosed before.
976 if (DiagDecl->isInvalidDecl())
977 return false;
978
979 // If this function is not constexpr because it is an inherited
980 // non-constexpr constructor, diagnose that directly.
981 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
982 if (CD && CD->isInheritingConstructor()) {
983 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
984 if (!Inherited->isConstexpr())
985 DiagDecl = CD = Inherited;
986 }
987
988 // Silently reject constructors of invalid classes. The invalid class
989 // has been rejected elsewhere before.
990 if (CD && CD->getParent()->isInvalidDecl())
991 return false;
992
993 // FIXME: If DiagDecl is an implicitly-declared special member function
994 // or an inheriting constructor, we should be much more explicit about why
995 // it's not constexpr.
996 if (CD && CD->isInheritingConstructor()) {
997 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_invalid_inhctor,
998 1)
999 << CD->getInheritedConstructor().getConstructor()->getParent();
1000 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
1001 } else {
1002 // Don't emit anything if the function isn't defined and we're checking
1003 // for a constant expression. It might be defined at the point we're
1004 // actually calling it.
1005 bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
1006 bool IsDefined = DiagDecl->isDefined();
1007 if (!IsDefined && !IsExtern && DiagDecl->isConstexpr() &&
1009 return false;
1010
1011 // If the declaration is defined, declared 'constexpr' _and_ has a body,
1012 // the below diagnostic doesn't add anything useful.
1013 if (DiagDecl->isDefined() && DiagDecl->isConstexpr() && DiagDecl->hasBody())
1014 return false;
1015
1016 S.FFDiag(S.Current->getLocation(OpPC),
1017 diag::note_constexpr_invalid_function, 1)
1018 << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
1019
1020 if (DiagDecl->getDefinition())
1021 S.Note(DiagDecl->getDefinition()->getLocation(), diag::note_declared_at);
1022 else
1023 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
1024 }
1025
1026 return false;
1027}
1028
1029static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
1030 if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
1031 const SourceLocation &Loc = S.Current->getLocation(OpPC);
1032 S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
1033 return false;
1034 }
1035
1037 return false;
1038
1039 if (F->isValid() && F->hasBody() && F->isConstexpr())
1040 return true;
1041
1042 const FunctionDecl *DiagDecl = F->getDecl();
1043 const FunctionDecl *Definition = nullptr;
1044 DiagDecl->getBody(Definition);
1045
1047 DiagDecl->isConstexpr()) {
1048 return false;
1049 }
1050
1051 // Implicitly constexpr.
1052 if (F->isLambdaStaticInvoker())
1053 return true;
1054
1055 return diagnoseCallableDecl(S, OpPC, DiagDecl);
1056}
1057
1058static bool CheckCallDepth(InterpState &S, CodePtr OpPC) {
1059 if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
1060 S.FFDiag(S.Current->getSource(OpPC),
1061 diag::note_constexpr_depth_limit_exceeded)
1062 << S.getLangOpts().ConstexprCallDepth;
1063 return false;
1064 }
1065
1066 return true;
1067}
1068
1070 if (S.Current->hasThisPointer())
1071 return true;
1072
1073 const Expr *E = S.Current->getExpr(OpPC);
1074 if (S.getLangOpts().CPlusPlus11) {
1075 bool IsImplicit = false;
1076 if (const auto *TE = dyn_cast<CXXThisExpr>(E))
1077 IsImplicit = TE->isImplicit();
1078 S.FFDiag(E, diag::note_constexpr_this) << IsImplicit;
1079 } else {
1080 S.FFDiag(E);
1081 }
1082
1083 return false;
1084}
1085
1087 APFloat::opStatus Status, FPOptions FPO) {
1088 // [expr.pre]p4:
1089 // If during the evaluation of an expression, the result is not
1090 // mathematically defined [...], the behavior is undefined.
1091 // FIXME: C++ rules require us to not conform to IEEE 754 here.
1092 if (Result.isNan()) {
1093 const SourceInfo &E = S.Current->getSource(OpPC);
1094 S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
1095 << /*NaN=*/true << S.Current->getRange(OpPC);
1096 return S.noteUndefinedBehavior();
1097 }
1098
1099 // In a constant context, assume that any dynamic rounding mode or FP
1100 // exception state matches the default floating-point environment.
1101 if (S.inConstantContext())
1102 return true;
1103
1104 if ((Status & APFloat::opInexact) &&
1105 FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) {
1106 // Inexact result means that it depends on rounding mode. If the requested
1107 // mode is dynamic, the evaluation cannot be made in compile time.
1108 const SourceInfo &E = S.Current->getSource(OpPC);
1109 S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
1110 return false;
1111 }
1112
1113 if ((Status != APFloat::opOK) &&
1114 (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic ||
1116 FPO.getAllowFEnvAccess())) {
1117 const SourceInfo &E = S.Current->getSource(OpPC);
1118 S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
1119 return false;
1120 }
1121
1122 if ((Status & APFloat::opStatus::opInvalidOp) &&
1124 const SourceInfo &E = S.Current->getSource(OpPC);
1125 // There is no usefully definable result.
1126 S.FFDiag(E);
1127 return false;
1128 }
1129
1130 return true;
1131}
1132
1134 if (S.getLangOpts().CPlusPlus20)
1135 return true;
1136
1137 const SourceInfo &E = S.Current->getSource(OpPC);
1138 S.CCEDiag(E, diag::note_constexpr_new);
1139 return true;
1140}
1141
1143 DynamicAllocator::Form AllocForm,
1144 DynamicAllocator::Form DeleteForm, const Descriptor *D,
1145 const Expr *NewExpr) {
1146 if (AllocForm == DeleteForm)
1147 return true;
1148
1149 QualType TypeToDiagnose = D->getDataType(S.getASTContext());
1150
1151 const SourceInfo &E = S.Current->getSource(OpPC);
1152 S.FFDiag(E, diag::note_constexpr_new_delete_mismatch)
1153 << static_cast<int>(DeleteForm) << static_cast<int>(AllocForm)
1154 << TypeToDiagnose;
1155 S.Note(NewExpr->getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
1156 << NewExpr->getSourceRange();
1157 return false;
1158}
1159
1160bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source,
1161 const Pointer &Ptr) {
1162 // Regular new type(...) call.
1163 if (isa_and_nonnull<CXXNewExpr>(Source))
1164 return true;
1165 // operator new.
1166 if (const auto *CE = dyn_cast_if_present<CallExpr>(Source);
1167 CE && CE->getBuiltinCallee() == Builtin::BI__builtin_operator_new)
1168 return true;
1169 // std::allocator.allocate() call
1170 if (const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(Source);
1171 MCE && MCE->getMethodDecl()->getIdentifier()->isStr("allocate"))
1172 return true;
1173
1174 // Whatever this is, we didn't heap allocate it.
1175 const SourceInfo &Loc = S.Current->getSource(OpPC);
1176 S.FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
1178
1179 if (Ptr.isTemporary())
1180 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
1181 else
1182 S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
1183 return false;
1184}
1185
1186/// We aleady know the given DeclRefExpr is invalid for some reason,
1187/// now figure out why and print appropriate diagnostics.
1188bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
1189 const ValueDecl *D = DR->getDecl();
1190 return diagnoseUnknownDecl(S, OpPC, D);
1191}
1192
1193bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK) {
1194 if (!B->isDummy())
1195 return true;
1196
1197 const ValueDecl *D = B->getDescriptor()->asValueDecl();
1198 if (!D)
1199 return false;
1200
1201 if (AK == AK_Read || AK == AK_Increment || AK == AK_Decrement)
1202 return diagnoseUnknownDecl(S, OpPC, D);
1203
1204 if (AK == AK_Destroy || S.getLangOpts().CPlusPlus14) {
1205 const SourceInfo &E = S.Current->getSource(OpPC);
1206 S.FFDiag(E, diag::note_constexpr_modify_global);
1207 }
1208 return false;
1209}
1210
1211static bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F,
1212 const CallExpr *CE, unsigned ArgSize) {
1213 auto Args = ArrayRef(CE->getArgs(), CE->getNumArgs());
1214 auto NonNullArgs = collectNonNullArgs(F->getDecl(), Args);
1215 unsigned Offset = 0;
1216 unsigned Index = 0;
1217 for (const Expr *Arg : Args) {
1218 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
1219 const Pointer &ArgPtr = S.Stk.peek<Pointer>(ArgSize - Offset);
1220 if (ArgPtr.isZero()) {
1221 const SourceLocation &Loc = S.Current->getLocation(OpPC);
1222 S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
1223 return false;
1224 }
1225 }
1226
1227 Offset += align(primSize(S.Ctx.classify(Arg).value_or(PT_Ptr)));
1228 ++Index;
1229 }
1230 return true;
1231}
1232
1234 const Pointer &BasePtr,
1235 const Descriptor *Desc) {
1236 assert(Desc->isRecord());
1237 const Record *R = Desc->ElemRecord;
1238 assert(R);
1239
1241 Pointer::pointToSameBlock(BasePtr, S.Current->getThis())) {
1242 const SourceInfo &Loc = S.Current->getSource(OpPC);
1243 S.FFDiag(Loc, diag::note_constexpr_double_destroy);
1244 return false;
1245 }
1246
1247 // Destructor of this record.
1248 const CXXDestructorDecl *Dtor = R->getDestructor();
1249 assert(Dtor);
1250 assert(!Dtor->isTrivial());
1251 const Function *DtorFunc = S.getContext().getOrCreateFunction(Dtor);
1252 if (!DtorFunc)
1253 return false;
1254
1255 S.Stk.push<Pointer>(BasePtr);
1256 return Call(S, OpPC, DtorFunc, 0);
1257}
1258
1259static bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B) {
1260 assert(B);
1261 const Descriptor *Desc = B->getDescriptor();
1262
1263 if (Desc->isPrimitive() || Desc->isPrimitiveArray())
1264 return true;
1265
1266 assert(Desc->isRecord() || Desc->isCompositeArray());
1267
1268 if (Desc->hasTrivialDtor())
1269 return true;
1270
1271 if (Desc->isCompositeArray()) {
1272 unsigned N = Desc->getNumElems();
1273 if (N == 0)
1274 return true;
1275 const Descriptor *ElemDesc = Desc->ElemDesc;
1276 assert(ElemDesc->isRecord());
1277
1278 Pointer RP(const_cast<Block *>(B));
1279 for (int I = static_cast<int>(N) - 1; I >= 0; --I) {
1280 if (!runRecordDestructor(S, OpPC, RP.atIndex(I).narrow(), ElemDesc))
1281 return false;
1282 }
1283 return true;
1284 }
1285
1286 assert(Desc->isRecord());
1287 return runRecordDestructor(S, OpPC, Pointer(const_cast<Block *>(B)), Desc);
1288}
1289
1291 if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
1292 if (const CXXDestructorDecl *DD = RD->getDestructor())
1293 return DD->isVirtual();
1294 return false;
1295}
1296
1297bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
1298 bool IsGlobalDelete) {
1299 if (!CheckDynamicMemoryAllocation(S, OpPC))
1300 return false;
1301
1302 DynamicAllocator &Allocator = S.getAllocator();
1303
1304 const Expr *Source = nullptr;
1305 const Block *BlockToDelete = nullptr;
1306 {
1307 // Extra scope for this so the block doesn't have this pointer
1308 // pointing to it when we destroy it.
1309 Pointer Ptr = S.Stk.pop<Pointer>();
1310
1311 // Deleteing nullptr is always fine.
1312 if (Ptr.isZero())
1313 return true;
1314
1315 // Remove base casts.
1316 QualType InitialType = Ptr.getType();
1317 while (Ptr.isBaseClass())
1318 Ptr = Ptr.getBase();
1319
1320 Source = Ptr.getDeclDesc()->asExpr();
1321 BlockToDelete = Ptr.block();
1322
1323 // Check that new[]/delete[] or new/delete were used, not a mixture.
1324 const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
1325 if (std::optional<DynamicAllocator::Form> AllocForm =
1326 Allocator.getAllocationForm(Source)) {
1327 DynamicAllocator::Form DeleteForm =
1328 DeleteIsArrayForm ? DynamicAllocator::Form::Array
1330 if (!CheckNewDeleteForms(S, OpPC, *AllocForm, DeleteForm, BlockDesc,
1331 Source))
1332 return false;
1333 }
1334
1335 // For the non-array case, the types must match if the static type
1336 // does not have a virtual destructor.
1337 if (!DeleteIsArrayForm && Ptr.getType() != InitialType &&
1338 !hasVirtualDestructor(InitialType)) {
1339 S.FFDiag(S.Current->getSource(OpPC),
1340 diag::note_constexpr_delete_base_nonvirt_dtor)
1341 << InitialType << Ptr.getType();
1342 return false;
1343 }
1344
1345 if (!Ptr.isRoot() || (Ptr.isOnePastEnd() && !Ptr.isZeroSizeArray()) ||
1346 (Ptr.isArrayElement() && Ptr.getIndex() != 0)) {
1347 const SourceInfo &Loc = S.Current->getSource(OpPC);
1348 S.FFDiag(Loc, diag::note_constexpr_delete_subobject)
1349 << Ptr.toDiagnosticString(S.getASTContext()) << Ptr.isOnePastEnd();
1350 return false;
1351 }
1352
1353 if (!CheckDeleteSource(S, OpPC, Source, Ptr))
1354 return false;
1355
1356 // For a class type with a virtual destructor, the selected operator delete
1357 // is the one looked up when building the destructor.
1358 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1359 QualType AllocType = Ptr.getType();
1360 auto getVirtualOperatorDelete = [](QualType T) -> const FunctionDecl * {
1361 if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
1362 if (const CXXDestructorDecl *DD = RD->getDestructor())
1363 return DD->isVirtual() ? DD->getOperatorDelete() : nullptr;
1364 return nullptr;
1365 };
1366
1367 if (const FunctionDecl *VirtualDelete =
1368 getVirtualOperatorDelete(AllocType);
1369 VirtualDelete &&
1370 !VirtualDelete
1372 S.FFDiag(S.Current->getSource(OpPC),
1373 diag::note_constexpr_new_non_replaceable)
1374 << isa<CXXMethodDecl>(VirtualDelete) << VirtualDelete;
1375 return false;
1376 }
1377 }
1378 }
1379 assert(Source);
1380 assert(BlockToDelete);
1381
1382 // Invoke destructors before deallocating the memory.
1383 if (!RunDestructors(S, OpPC, BlockToDelete))
1384 return false;
1385
1386 if (!Allocator.deallocate(Source, BlockToDelete, S)) {
1387 // Nothing has been deallocated, this must be a double-delete.
1388 const SourceInfo &Loc = S.Current->getSource(OpPC);
1389 S.FFDiag(Loc, diag::note_constexpr_double_delete);
1390 return false;
1391 }
1392
1393 return true;
1394}
1395
1397 const APSInt &Value) {
1398 llvm::APInt Min;
1399 llvm::APInt Max;
1400 ED->getValueRange(Max, Min);
1401 --Max;
1402
1403 if (ED->getNumNegativeBits() &&
1404 (Max.slt(Value.getSExtValue()) || Min.sgt(Value.getSExtValue()))) {
1405 const SourceLocation &Loc = S.Current->getLocation(OpPC);
1406 S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1407 << llvm::toString(Value, 10) << Min.getSExtValue() << Max.getSExtValue()
1408 << ED;
1409 } else if (!ED->getNumNegativeBits() && Max.ult(Value.getZExtValue())) {
1410 const SourceLocation &Loc = S.Current->getLocation(OpPC);
1411 S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1412 << llvm::toString(Value, 10) << Min.getZExtValue() << Max.getZExtValue()
1413 << ED;
1414 }
1415}
1416
1418 assert(T);
1419 assert(!S.getLangOpts().CPlusPlus23);
1420
1421 // C++1y: A constant initializer for an object o [...] may also invoke
1422 // constexpr constructors for o and its subobjects even if those objects
1423 // are of non-literal class types.
1424 //
1425 // C++11 missed this detail for aggregates, so classes like this:
1426 // struct foo_t { union { int i; volatile int j; } u; };
1427 // are not (obviously) initializable like so:
1428 // __attribute__((__require_constant_initialization__))
1429 // static const foo_t x = {{0}};
1430 // because "i" is a subobject with non-literal initialization (due to the
1431 // volatile member of the union). See:
1432 // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677
1433 // Therefore, we use the C++1y behavior.
1434
1435 if (!S.Current->isBottomFrame() &&
1438 return true;
1439 }
1440
1441 const Expr *E = S.Current->getExpr(OpPC);
1442 if (S.getLangOpts().CPlusPlus11)
1443 S.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType();
1444 else
1445 S.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
1446 return false;
1447}
1448
1449static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
1450 uint32_t Off) {
1451 if (S.getLangOpts().CPlusPlus && S.inConstantContext() &&
1452 !CheckNull(S, OpPC, Ptr, CSK_Field))
1453 return false;
1454
1455 if (!CheckRange(S, OpPC, Ptr, CSK_Field))
1456 return false;
1457 if (!CheckArray(S, OpPC, Ptr))
1458 return false;
1459 if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
1460 return false;
1461
1462 if (Ptr.isIntegralPointer()) {
1463 if (std::optional<IntPointer> IntPtr =
1464 Ptr.asIntPointer().atOffset(S.getASTContext(), Off)) {
1465 S.Stk.push<Pointer>(std::move(*IntPtr));
1466 return true;
1467 }
1468 return false;
1469 }
1470
1471 if (!Ptr.isBlockPointer()) {
1472 // FIXME: The only time we (seem to) get here is when trying to access a
1473 // field of a typeid pointer. In that case, we're supposed to diagnose e.g.
1474 // `typeid(int).name`, but we currently diagnose `&typeid(int)`.
1475 S.FFDiag(S.Current->getSource(OpPC),
1476 diag::note_constexpr_access_unreadable_object)
1478 return false;
1479 }
1480
1481 // We can't get the field of something that's not a record.
1482 if (!Ptr.getFieldDesc()->isRecord())
1483 return false;
1484
1485 if ((Ptr.getByteOffset() + Off) >= Ptr.block()->getSize())
1486 return false;
1487
1488 S.Stk.push<Pointer>(Ptr.atField(Off));
1489 return true;
1490}
1491
1492bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1493 const auto &Ptr = S.Stk.peek<Pointer>();
1494 return getField(S, OpPC, Ptr, Off);
1495}
1496
1497bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
1498 const auto &Ptr = S.Stk.pop<Pointer>();
1499 return getField(S, OpPC, Ptr, Off);
1500}
1501
1502static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
1503 const Pointer &ThisPtr) {
1504 assert(Func->isConstructor());
1505
1506 if (Func->getParentDecl()->isInvalidDecl())
1507 return false;
1508
1509 const Descriptor *D = ThisPtr.getFieldDesc();
1510 // FIXME: I think this case is not 100% correct. E.g. a pointer into a
1511 // subobject of a composite array.
1512 if (!D->ElemRecord)
1513 return true;
1514
1515 if (D->ElemRecord->getNumVirtualBases() == 0)
1516 return true;
1517
1518 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_virtual_base)
1519 << Func->getParentDecl();
1520 return false;
1521}
1522
1523bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
1524 if (!CheckLive(S, OpPC, Ptr, AK_Destroy))
1525 return false;
1526 if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Destroy))
1527 return false;
1528 if (!CheckRange(S, OpPC, Ptr, AK_Destroy))
1529 return false;
1530
1531 // Can't call a dtor on a global variable.
1532 if (Ptr.block()->isStatic()) {
1533 const SourceInfo &E = S.Current->getSource(OpPC);
1534 S.FFDiag(E, diag::note_constexpr_modify_global);
1535 return false;
1536 }
1537 return CheckActive(S, OpPC, Ptr, AK_Destroy);
1538}
1539
1540/// Opcode. Check if the function decl can be called at compile time.
1543 return false;
1544
1545 const FunctionDecl *Definition = nullptr;
1546 const Stmt *Body = FD->getBody(Definition);
1547
1548 if (Definition && Body &&
1549 (Definition->isConstexpr() || Definition->hasAttr<MSConstexprAttr>()))
1550 return true;
1551
1552 return diagnoseCallableDecl(S, OpPC, FD);
1553}
1554
1555static void compileFunction(InterpState &S, const Function *Func) {
1556 const FunctionDecl *Definition = Func->getDecl()->getDefinition();
1557 if (!Definition)
1558 return;
1559
1561 .compileFunc(Definition, const_cast<Function *>(Func));
1562}
1563
1565 uint32_t VarArgSize) {
1566 if (Func->hasThisPointer()) {
1567 size_t ArgSize = Func->getArgSize() + VarArgSize;
1568 size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1569 const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1570
1571 // If the current function is a lambda static invoker and
1572 // the function we're about to call is a lambda call operator,
1573 // skip the CheckInvoke, since the ThisPtr is a null pointer
1574 // anyway.
1575 if (!(S.Current->getFunction() &&
1577 Func->isLambdaCallOperator())) {
1578 if (!CheckInvoke(S, OpPC, ThisPtr))
1579 return false;
1580 }
1581
1583 return false;
1584 }
1585
1586 if (!Func->isFullyCompiled())
1588
1589 if (!CheckCallable(S, OpPC, Func))
1590 return false;
1591
1592 if (!CheckCallDepth(S, OpPC))
1593 return false;
1594
1595 auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize);
1596 InterpFrame *FrameBefore = S.Current;
1597 S.Current = NewFrame.get();
1598
1599 // Note that we cannot assert(CallResult.hasValue()) here since
1600 // Ret() above only sets the APValue if the curent frame doesn't
1601 // have a caller set.
1602 if (Interpret(S)) {
1603 NewFrame.release(); // Frame was delete'd already.
1604 assert(S.Current == FrameBefore);
1605 return true;
1606 }
1607
1608 // Interpreting the function failed somehow. Reset to
1609 // previous state.
1610 S.Current = FrameBefore;
1611 return false;
1612}
1613bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
1614 uint32_t VarArgSize) {
1615 assert(Func);
1616 auto cleanup = [&]() -> bool {
1618 return false;
1619 };
1620
1621 if (Func->hasThisPointer()) {
1622 size_t ArgSize = Func->getArgSize() + VarArgSize;
1623 size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1624
1625 const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1626
1627 // C++23 [expr.const]p5.6
1628 // an invocation of a virtual function ([class.virtual]) for an object whose
1629 // dynamic type is constexpr-unknown;
1630 if (ThisPtr.isDummy() && Func->isVirtual())
1631 return false;
1632
1633 // If the current function is a lambda static invoker and
1634 // the function we're about to call is a lambda call operator,
1635 // skip the CheckInvoke, since the ThisPtr is a null pointer
1636 // anyway.
1637 if (S.Current->getFunction() &&
1639 Func->isLambdaCallOperator()) {
1640 assert(ThisPtr.isZero());
1641 } else {
1642 if (!CheckInvoke(S, OpPC, ThisPtr))
1643 return cleanup();
1644 if (!Func->isConstructor() && !Func->isDestructor() &&
1645 !CheckActive(S, OpPC, ThisPtr, AK_MemberCall))
1646 return false;
1647 }
1648
1649 if (Func->isConstructor() && !checkConstructor(S, OpPC, Func, ThisPtr))
1650 return false;
1651 if (Func->isDestructor() && !CheckDestructor(S, OpPC, ThisPtr))
1652 return false;
1653
1654 if (Func->isConstructor() || Func->isDestructor())
1655 S.InitializingBlocks.push_back(ThisPtr.block());
1656 }
1657
1658 if (!Func->isFullyCompiled())
1660
1661 if (!CheckCallable(S, OpPC, Func))
1662 return cleanup();
1663
1664 // FIXME: The isConstructor() check here is not always right. The current
1665 // constant evaluator is somewhat inconsistent in when it allows a function
1666 // call when checking for a constant expression.
1667 if (Func->hasThisPointer() && S.checkingPotentialConstantExpression() &&
1668 !Func->isConstructor())
1669 return cleanup();
1670
1671 if (!CheckCallDepth(S, OpPC))
1672 return cleanup();
1673
1674 auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize);
1675 InterpFrame *FrameBefore = S.Current;
1676 S.Current = NewFrame.get();
1677
1678 InterpStateCCOverride CCOverride(S, Func->isImmediate());
1679 // Note that we cannot assert(CallResult.hasValue()) here since
1680 // Ret() above only sets the APValue if the curent frame doesn't
1681 // have a caller set.
1682 bool Success = Interpret(S);
1683 // Remove initializing block again.
1684 if (Func->isConstructor() || Func->isDestructor())
1685 S.InitializingBlocks.pop_back();
1686
1687 if (!Success) {
1688 // Interpreting the function failed somehow. Reset to
1689 // previous state.
1690 S.Current = FrameBefore;
1691 return false;
1692 }
1693
1694 NewFrame.release(); // Frame was delete'd already.
1695 assert(S.Current == FrameBefore);
1696 return true;
1697}
1698
1699static bool GetDynamicDecl(InterpState &S, CodePtr OpPC, Pointer TypePtr,
1700 const CXXRecordDecl *&DynamicDecl) {
1701 while (TypePtr.isBaseClass())
1702 TypePtr = TypePtr.getBase();
1703
1704 QualType DynamicType = TypePtr.getType();
1705 if (TypePtr.isStatic() || TypePtr.isConst()) {
1706 if (const VarDecl *VD = TypePtr.getDeclDesc()->asVarDecl();
1707 VD && !VD->isConstexpr()) {
1708 const Expr *E = S.Current->getExpr(OpPC);
1709 APValue V = TypePtr.toAPValue(S.getASTContext());
1711 S.FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
1712 << AccessKinds::AK_MemberCall << V.getAsString(S.getASTContext(), TT);
1713 return false;
1714 }
1715 }
1716
1717 if (DynamicType->isPointerType() || DynamicType->isReferenceType()) {
1718 DynamicDecl = DynamicType->getPointeeCXXRecordDecl();
1719 } else if (DynamicType->isArrayType()) {
1720 const Type *ElemType = DynamicType->getPointeeOrArrayElementType();
1721 assert(ElemType);
1722 DynamicDecl = ElemType->getAsCXXRecordDecl();
1723 } else {
1724 DynamicDecl = DynamicType->getAsCXXRecordDecl();
1725 }
1726 return true;
1727}
1728
1730 uint32_t VarArgSize) {
1731 assert(Func->hasThisPointer());
1732 assert(Func->isVirtual());
1733 size_t ArgSize = Func->getArgSize() + VarArgSize;
1734 size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1735 Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1736 const FunctionDecl *Callee = Func->getDecl();
1737
1738 const CXXRecordDecl *DynamicDecl = nullptr;
1739 if (!GetDynamicDecl(S, OpPC, ThisPtr, DynamicDecl))
1740 return false;
1741 assert(DynamicDecl);
1742
1743 const auto *StaticDecl = cast<CXXRecordDecl>(Func->getParentDecl());
1744 const auto *InitialFunction = cast<CXXMethodDecl>(Callee);
1745 const CXXMethodDecl *Overrider;
1746
1747 if (StaticDecl != DynamicDecl &&
1748 !llvm::is_contained(S.InitializingBlocks, ThisPtr.block())) {
1749 if (!DynamicDecl->isDerivedFrom(StaticDecl))
1750 return false;
1751 Overrider = S.getContext().getOverridingFunction(DynamicDecl, StaticDecl,
1752 InitialFunction);
1753
1754 } else {
1755 Overrider = InitialFunction;
1756 }
1757
1758 // C++2a [class.abstract]p6:
1759 // the effect of making a virtual call to a pure virtual function [...] is
1760 // undefined
1761 if (Overrider->isPureVirtual()) {
1762 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_pure_virtual_call,
1763 1)
1764 << Callee;
1765 S.Note(Callee->getLocation(), diag::note_declared_at);
1766 return false;
1767 }
1768
1769 if (Overrider != InitialFunction) {
1770 // DR1872: An instantiated virtual constexpr function can't be called in a
1771 // constant expression (prior to C++20). We can still constant-fold such a
1772 // call.
1773 if (!S.getLangOpts().CPlusPlus20 && Overrider->isVirtual()) {
1774 const Expr *E = S.Current->getExpr(OpPC);
1775 S.CCEDiag(E, diag::note_constexpr_virtual_call) << E->getSourceRange();
1776 }
1777
1778 Func = S.getContext().getOrCreateFunction(Overrider);
1779
1780 const CXXRecordDecl *ThisFieldDecl =
1781 ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
1782 if (Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
1783 // If the function we call is further DOWN the hierarchy than the
1784 // FieldDesc of our pointer, just go up the hierarchy of this field
1785 // the furthest we can go.
1786 while (ThisPtr.isBaseClass())
1787 ThisPtr = ThisPtr.getBase();
1788 }
1789 }
1790
1791 if (!Call(S, OpPC, Func, VarArgSize))
1792 return false;
1793
1794 // Covariant return types. The return type of Overrider is a pointer
1795 // or reference to a class type.
1796 if (Overrider != InitialFunction &&
1797 Overrider->getReturnType()->isPointerOrReferenceType() &&
1798 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
1799 QualType OverriderPointeeType =
1800 Overrider->getReturnType()->getPointeeType();
1801 QualType InitialPointeeType =
1802 InitialFunction->getReturnType()->getPointeeType();
1803 // We've called Overrider above, but calling code expects us to return what
1804 // InitialFunction returned. According to the rules for covariant return
1805 // types, what InitialFunction returns needs to be a base class of what
1806 // Overrider returns. So, we need to do an upcast here.
1807 unsigned Offset = S.getContext().collectBaseOffset(
1808 InitialPointeeType->getAsRecordDecl(),
1809 OverriderPointeeType->getAsRecordDecl());
1810 return GetPtrBasePop(S, OpPC, Offset, /*IsNullOK=*/true);
1811 }
1812
1813 return true;
1814}
1815
1816bool CallBI(InterpState &S, CodePtr OpPC, const CallExpr *CE,
1817 uint32_t BuiltinID) {
1818 // A little arbitrary, but the current interpreter allows evaluation
1819 // of builtin functions in this mode, with some exceptions.
1820 if (BuiltinID == Builtin::BI__builtin_operator_new &&
1822 return false;
1823
1824 return InterpretBuiltin(S, OpPC, CE, BuiltinID);
1825}
1826
1827bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
1828 const CallExpr *CE) {
1829 const Pointer &Ptr = S.Stk.pop<Pointer>();
1830
1831 if (Ptr.isZero()) {
1832 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_null_callee)
1833 << const_cast<Expr *>(CE->getCallee()) << CE->getSourceRange();
1834 return false;
1835 }
1836
1837 if (!Ptr.isFunctionPointer())
1838 return Invalid(S, OpPC);
1839
1840 const FunctionPointer &FuncPtr = Ptr.asFunctionPointer();
1841 const Function *F = FuncPtr.getFunction();
1842 assert(F);
1843 // Don't allow calling block pointers.
1844 if (!F->getDecl())
1845 return Invalid(S, OpPC);
1846
1847 // This happens when the call expression has been cast to
1848 // something else, but we don't support that.
1849 if (S.Ctx.classify(F->getDecl()->getReturnType()) !=
1851 return false;
1852
1853 // Check argument nullability state.
1854 if (F->hasNonNullAttr()) {
1855 if (!CheckNonNullArgs(S, OpPC, F, CE, ArgSize))
1856 return false;
1857 }
1858
1859 // Can happen when casting function pointers around.
1860 QualType CalleeType = CE->getCallee()->getType();
1861 if (CalleeType->isPointerType() &&
1863 F->getDecl()->getType(), CalleeType->getPointeeType())) {
1864 return false;
1865 }
1866
1867 assert(ArgSize >= F->getWrittenArgSize());
1868 uint32_t VarArgSize = ArgSize - F->getWrittenArgSize();
1869
1870 // We need to do this explicitly here since we don't have the necessary
1871 // information to do it automatically.
1872 if (F->isThisPointerExplicit())
1873 VarArgSize -= align(primSize(PT_Ptr));
1874
1875 if (F->isVirtual())
1876 return CallVirt(S, OpPC, F, VarArgSize);
1877
1878 return Call(S, OpPC, F, VarArgSize);
1879}
1880
1881static void startLifetimeRecurse(const Pointer &Ptr) {
1882 if (const Record *R = Ptr.getRecord()) {
1883 Ptr.startLifetime();
1884 for (const Record::Field &Fi : R->fields())
1885 startLifetimeRecurse(Ptr.atField(Fi.Offset));
1886 return;
1887 }
1888
1889 if (const Descriptor *FieldDesc = Ptr.getFieldDesc();
1890 FieldDesc->isCompositeArray()) {
1891 assert(Ptr.getLifetime() == Lifetime::Started);
1892 for (unsigned I = 0; I != FieldDesc->getNumElems(); ++I)
1894 return;
1895 }
1896
1897 Ptr.startLifetime();
1898}
1899
1901 const auto &Ptr = S.Stk.peek<Pointer>();
1902 if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
1903 return false;
1904 startLifetimeRecurse(Ptr.narrow());
1905 return true;
1906}
1907
1908// FIXME: It might be better to the recursing as part of the generated code for
1909// a destructor?
1910static void endLifetimeRecurse(const Pointer &Ptr) {
1911 if (const Record *R = Ptr.getRecord()) {
1912 Ptr.endLifetime();
1913 for (const Record::Field &Fi : R->fields())
1914 endLifetimeRecurse(Ptr.atField(Fi.Offset));
1915 return;
1916 }
1917
1918 if (const Descriptor *FieldDesc = Ptr.getFieldDesc();
1919 FieldDesc->isCompositeArray()) {
1920 // No endLifetime() for array roots.
1921 assert(Ptr.getLifetime() == Lifetime::Started);
1922 for (unsigned I = 0; I != FieldDesc->getNumElems(); ++I)
1924 return;
1925 }
1926
1927 Ptr.endLifetime();
1928}
1929
1930/// Ends the lifetime of the peek'd pointer.
1932 const auto &Ptr = S.Stk.peek<Pointer>();
1933 if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
1934 return false;
1935
1936 // FIXME: We need per-element lifetime information for primitive arrays.
1937 if (Ptr.isArrayElement())
1938 return true;
1939
1940 endLifetimeRecurse(Ptr.narrow());
1941 return true;
1942}
1943
1944/// Ends the lifetime of the pop'd pointer.
1946 const auto &Ptr = S.Stk.pop<Pointer>();
1947 if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
1948 return false;
1949
1950 // FIXME: We need per-element lifetime information for primitive arrays.
1951 if (Ptr.isArrayElement())
1952 return true;
1953
1954 endLifetimeRecurse(Ptr.narrow());
1955 return true;
1956}
1957
1959 std::optional<uint64_t> ArraySize) {
1960 const Pointer &Ptr = S.Stk.peek<Pointer>();
1961
1962 if (Ptr.inUnion() && Ptr.getBase().getRecord()->isUnion())
1963 Ptr.activate();
1964
1965 if (Ptr.isZero()) {
1966 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)
1967 << AK_Construct;
1968 return false;
1969 }
1970
1971 if (!Ptr.isBlockPointer())
1972 return false;
1973
1975
1976 // Similar to CheckStore(), but with the additional CheckTemporary() call and
1977 // the AccessKinds are different.
1978 if (!Ptr.block()->isAccessible()) {
1979 if (!CheckExtern(S, OpPC, Ptr))
1980 return false;
1981 if (!CheckLive(S, OpPC, Ptr, AK_Construct))
1982 return false;
1983 return CheckDummy(S, OpPC, Ptr.block(), AK_Construct);
1984 }
1985 if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Construct))
1986 return false;
1987
1988 // CheckLifetime for this and all base pointers.
1989 for (Pointer P = Ptr;;) {
1990 if (!CheckLifetime(S, OpPC, P.getLifetime(), AK_Construct))
1991 return false;
1992
1993 if (P.isRoot())
1994 break;
1995 P = P.getBase();
1996 }
1997
1998 if (!CheckRange(S, OpPC, Ptr, AK_Construct))
1999 return false;
2000 if (!CheckGlobal(S, OpPC, Ptr))
2001 return false;
2002 if (!CheckConst(S, OpPC, Ptr))
2003 return false;
2004 if (!S.inConstantContext() && isConstexprUnknown(Ptr))
2005 return false;
2006
2007 if (!InvalidNewDeleteExpr(S, OpPC, E))
2008 return false;
2009
2010 const auto *NewExpr = cast<CXXNewExpr>(E);
2011 QualType StorageType = Ptr.getFieldDesc()->getDataType(S.getASTContext());
2012 const ASTContext &ASTCtx = S.getASTContext();
2013 QualType AllocType;
2014 if (ArraySize) {
2015 AllocType = ASTCtx.getConstantArrayType(
2016 NewExpr->getAllocatedType(),
2017 APInt(64, static_cast<uint64_t>(*ArraySize), false), nullptr,
2019 } else {
2020 AllocType = NewExpr->getAllocatedType();
2021 }
2022
2023 unsigned StorageSize = 1;
2024 unsigned AllocSize = 1;
2025 if (const auto *CAT = dyn_cast<ConstantArrayType>(AllocType))
2026 AllocSize = CAT->getZExtSize();
2027 if (const auto *CAT = dyn_cast<ConstantArrayType>(StorageType))
2028 StorageSize = CAT->getZExtSize();
2029
2030 if (AllocSize > StorageSize ||
2031 !ASTCtx.hasSimilarType(ASTCtx.getBaseElementType(AllocType),
2032 ASTCtx.getBaseElementType(StorageType))) {
2033 S.FFDiag(S.Current->getLocation(OpPC),
2034 diag::note_constexpr_placement_new_wrong_type)
2035 << StorageType << AllocType;
2036 return false;
2037 }
2038
2039 // Can't activate fields in a union, unless the direct base is the union.
2040 if (Ptr.inUnion() && !Ptr.isActive() && !Ptr.getBase().getRecord()->isUnion())
2041 return CheckActive(S, OpPC, Ptr, AK_Construct);
2042
2043 return true;
2044}
2045
2047 assert(E);
2048
2049 if (const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
2050 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
2051
2052 if (NewExpr->getNumPlacementArgs() > 0) {
2053 // This is allowed pre-C++26, but only an std function.
2054 if (S.getLangOpts().CPlusPlus26 || S.Current->isStdFunction())
2055 return true;
2056 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_placement)
2057 << /*C++26 feature*/ 1 << E->getSourceRange();
2058 } else if (
2059 !OperatorNew
2060 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
2061 S.FFDiag(S.Current->getSource(OpPC),
2062 diag::note_constexpr_new_non_replaceable)
2063 << isa<CXXMethodDecl>(OperatorNew) << OperatorNew;
2064 return false;
2065 } else if (!S.getLangOpts().CPlusPlus26 &&
2066 NewExpr->getNumPlacementArgs() == 1 &&
2067 !OperatorNew->isReservedGlobalPlacementOperator()) {
2068 if (!S.getLangOpts().CPlusPlus26) {
2069 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_placement)
2070 << /*Unsupported*/ 0 << E->getSourceRange();
2071 return false;
2072 }
2073 return true;
2074 }
2075 } else {
2076 const auto *DeleteExpr = cast<CXXDeleteExpr>(E);
2077 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
2078 if (!OperatorDelete
2079 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
2080 S.FFDiag(S.Current->getSource(OpPC),
2081 diag::note_constexpr_new_non_replaceable)
2082 << isa<CXXMethodDecl>(OperatorDelete) << OperatorDelete;
2083 return false;
2084 }
2085 }
2086
2087 return false;
2088}
2089
2091 const FixedPoint &FP) {
2092 const Expr *E = S.Current->getExpr(OpPC);
2095 E->getExprLoc(), diag::warn_fixedpoint_constant_overflow)
2096 << FP.toDiagnosticString(S.getASTContext()) << E->getType();
2097 }
2098 S.CCEDiag(E, diag::note_constexpr_overflow)
2099 << FP.toDiagnosticString(S.getASTContext()) << E->getType();
2100 return S.noteUndefinedBehavior();
2101}
2102
2103bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index) {
2104 const SourceInfo &Loc = S.Current->getSource(OpPC);
2105 S.FFDiag(Loc,
2106 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
2107 << Index;
2108 return false;
2109}
2110
2112 const Pointer &Ptr, unsigned BitWidth) {
2113 const SourceInfo &E = S.Current->getSource(OpPC);
2114 S.CCEDiag(E, diag::note_constexpr_invalid_cast)
2115 << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
2116
2117 if (Ptr.isDummy())
2118 return false;
2119 if (Ptr.isFunctionPointer())
2120 return true;
2121
2122 if (Ptr.isBlockPointer() && !Ptr.isZero()) {
2123 // Only allow based lvalue casts if they are lossless.
2125 BitWidth)
2126 return Invalid(S, OpPC);
2127 }
2128 return true;
2129}
2130
2131bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
2132 const Pointer &Ptr = S.Stk.pop<Pointer>();
2133
2134 if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
2135 return false;
2136
2137 auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
2138 Result.copy(APInt(BitWidth, Ptr.getIntegerRepresentation()));
2139
2141 return true;
2142}
2143
2144bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
2145 const Pointer &Ptr = S.Stk.pop<Pointer>();
2146
2147 if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
2148 return false;
2149
2150 auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
2151 Result.copy(APInt(BitWidth, Ptr.getIntegerRepresentation()));
2152
2154 return true;
2155}
2156
2157bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits,
2158 bool TargetIsUCharOrByte) {
2159 // This is always fine.
2160 if (!HasIndeterminateBits)
2161 return true;
2162
2163 // Indeterminate bits can only be bitcast to unsigned char or std::byte.
2164 if (TargetIsUCharOrByte)
2165 return true;
2166
2167 const Expr *E = S.Current->getExpr(OpPC);
2168 QualType ExprType = E->getType();
2169 S.FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
2170 << ExprType << S.getLangOpts().CharIsSigned << E->getSourceRange();
2171 return false;
2172}
2173
2174bool GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr,
2175 const Type *TypeInfoType) {
2176 S.Stk.push<Pointer>(TypePtr, TypeInfoType);
2177 return true;
2178}
2179
2180bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType) {
2181 const auto &P = S.Stk.pop<Pointer>();
2182
2183 if (!P.isBlockPointer())
2184 return false;
2185
2186 // Pick the most-derived type.
2187 CanQualType T = P.getDeclPtr().getType()->getCanonicalTypeUnqualified();
2188 // ... unless we're currently constructing this object.
2189 // FIXME: We have a similar check to this in more places.
2190 if (S.Current->getFunction()) {
2191 for (const InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) {
2192 if (const Function *Func = Frame->getFunction();
2193 Func && (Func->isConstructor() || Func->isDestructor()) &&
2194 P.block() == Frame->getThis().block()) {
2196 Func->getParentDecl());
2197 break;
2198 }
2199 }
2200 }
2201
2202 S.Stk.push<Pointer>(T->getTypePtr(), TypeInfoType);
2203 return true;
2204}
2205
2207 const auto *E = cast<CXXTypeidExpr>(S.Current->getExpr(OpPC));
2208 S.CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
2209 << E->getExprOperand()->getType()
2210 << E->getExprOperand()->getSourceRange();
2211 return false;
2212}
2213
2215 const Pointer &RHS) {
2216 unsigned LHSOffset = LHS.isOnePastEnd() ? LHS.getNumElems() : LHS.getIndex();
2217 unsigned RHSOffset = RHS.isOnePastEnd() ? RHS.getNumElems() : RHS.getIndex();
2218 unsigned LHSLength = (LHS.getNumElems() - 1) * LHS.elemSize();
2219 unsigned RHSLength = (RHS.getNumElems() - 1) * RHS.elemSize();
2220
2221 StringRef LHSStr((const char *)LHS.atIndex(0).getRawAddress(), LHSLength);
2222 StringRef RHSStr((const char *)RHS.atIndex(0).getRawAddress(), RHSLength);
2223 int32_t IndexDiff = RHSOffset - LHSOffset;
2224 if (IndexDiff < 0) {
2225 if (static_cast<int32_t>(LHSLength) < -IndexDiff)
2226 return false;
2227 LHSStr = LHSStr.drop_front(-IndexDiff);
2228 } else {
2229 if (static_cast<int32_t>(RHSLength) < IndexDiff)
2230 return false;
2231 RHSStr = RHSStr.drop_front(IndexDiff);
2232 }
2233
2234 unsigned ShorterCharWidth;
2235 StringRef Shorter;
2236 StringRef Longer;
2237 if (LHSLength < RHSLength) {
2238 ShorterCharWidth = LHS.elemSize();
2239 Shorter = LHSStr;
2240 Longer = RHSStr;
2241 } else {
2242 ShorterCharWidth = RHS.elemSize();
2243 Shorter = RHSStr;
2244 Longer = LHSStr;
2245 }
2246
2247 // The null terminator isn't included in the string data, so check for it
2248 // manually. If the longer string doesn't have a null terminator where the
2249 // shorter string ends, they aren't potentially overlapping.
2250 for (unsigned NullByte : llvm::seq(ShorterCharWidth)) {
2251 if (Shorter.size() + NullByte >= Longer.size())
2252 break;
2253 if (Longer[Shorter.size() + NullByte])
2254 return false;
2255 }
2256 return Shorter == Longer.take_front(Shorter.size());
2257}
2258
2259static void copyPrimitiveMemory(InterpState &S, const Pointer &Ptr,
2260 PrimType T) {
2261
2262 if (T == PT_IntAPS) {
2263 auto &Val = Ptr.deref<IntegralAP<true>>();
2264 if (!Val.singleWord()) {
2265 uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
2266 Val.take(NewMemory);
2267 }
2268 } else if (T == PT_IntAP) {
2269 auto &Val = Ptr.deref<IntegralAP<false>>();
2270 if (!Val.singleWord()) {
2271 uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
2272 Val.take(NewMemory);
2273 }
2274 } else if (T == PT_Float) {
2275 auto &Val = Ptr.deref<Floating>();
2276 if (!Val.singleWord()) {
2277 uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
2278 Val.take(NewMemory);
2279 }
2280 }
2281}
2282
2283template <typename T>
2284static void copyPrimitiveMemory(InterpState &S, const Pointer &Ptr) {
2285 assert(needsAlloc<T>());
2286 auto &Val = Ptr.deref<T>();
2287 if (!Val.singleWord()) {
2288 uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
2289 Val.take(NewMemory);
2290 }
2291}
2292
2293static void finishGlobalRecurse(InterpState &S, const Pointer &Ptr) {
2294 if (const Record *R = Ptr.getRecord()) {
2295 for (const Record::Field &Fi : R->fields()) {
2296 if (Fi.Desc->isPrimitive()) {
2297 TYPE_SWITCH_ALLOC(Fi.Desc->getPrimType(), {
2298 copyPrimitiveMemory<T>(S, Ptr.atField(Fi.Offset));
2299 });
2300 copyPrimitiveMemory(S, Ptr.atField(Fi.Offset), Fi.Desc->getPrimType());
2301 } else
2302 finishGlobalRecurse(S, Ptr.atField(Fi.Offset));
2303 }
2304 return;
2305 }
2306
2307 if (const Descriptor *D = Ptr.getFieldDesc(); D && D->isArray()) {
2308 unsigned NumElems = D->getNumElems();
2309 if (NumElems == 0)
2310 return;
2311
2312 if (D->isPrimitiveArray()) {
2313 PrimType PT = D->getPrimType();
2314 if (!needsAlloc(PT))
2315 return;
2316 assert(NumElems >= 1);
2317 const Pointer EP = Ptr.atIndex(0);
2318 bool AllSingleWord = true;
2319 TYPE_SWITCH_ALLOC(PT, {
2320 if (!EP.deref<T>().singleWord()) {
2322 AllSingleWord = false;
2323 }
2324 });
2325 if (AllSingleWord)
2326 return;
2327 for (unsigned I = 1; I != D->getNumElems(); ++I) {
2328 const Pointer EP = Ptr.atIndex(I);
2329 copyPrimitiveMemory(S, EP, PT);
2330 }
2331 } else {
2332 assert(D->isCompositeArray());
2333 for (unsigned I = 0; I != D->getNumElems(); ++I) {
2334 const Pointer EP = Ptr.atIndex(I).narrow();
2335 finishGlobalRecurse(S, EP);
2336 }
2337 }
2338 }
2339}
2340
2342 const Pointer &Ptr = S.Stk.pop<Pointer>();
2343
2344 finishGlobalRecurse(S, Ptr);
2345 if (Ptr.canBeInitialized()) {
2346 Ptr.initialize();
2347 Ptr.activate();
2348 }
2349
2350 return true;
2351}
2352
2353// https://github.com/llvm/llvm-project/issues/102513
2354#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
2355#pragma optimize("", off)
2356#endif
2358 // The current stack frame when we started Interpret().
2359 // This is being used by the ops to determine wheter
2360 // to return from this function and thus terminate
2361 // interpretation.
2362 const InterpFrame *StartFrame = S.Current;
2363 assert(!S.Current->isRoot());
2364 CodePtr PC = S.Current->getPC();
2365
2366 // Empty program.
2367 if (!PC)
2368 return true;
2369
2370 for (;;) {
2371 auto Op = PC.read<Opcode>();
2372 CodePtr OpPC = PC;
2373
2374 switch (Op) {
2375#define GET_INTERP
2376#include "Opcodes.inc"
2377#undef GET_INTERP
2378 }
2379 }
2380}
2381// https://github.com/llvm/llvm-project/issues/102513
2382#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
2383#pragma optimize("", on)
2384#endif
2385
2386} // namespace interp
2387} // namespace clang
Defines the clang::ASTContext interface.
#define V(N, I)
Defines the clang::Expr interface and subclasses for C++ expressions.
static const FunctionDecl * getVirtualOperatorDelete(QualType T)
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName="<stdin>")
Clean up any erroneous/redundant code in the given Ranges in Code.
static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset)
Definition Interp.cpp:39
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK)
Definition Interp.cpp:214
static bool BCP(InterpState &S, CodePtr &RealPC, int32_t Offset, PrimType PT)
Definition Interp.cpp:64
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition Interp.cpp:240
static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset)
Definition Interp.cpp:44
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
Definition Interp.cpp:177
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, const ValueDecl *D)
Definition Interp.cpp:137
static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset)
Definition Interp.cpp:51
static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
Definition Interp.cpp:128
static bool RetValue(InterpState &S, CodePtr &Pt)
Definition Interp.cpp:31
static StringRef getIdentifier(const Token &Tok)
#define TYPE_SWITCH_ALLOC(Expr, B)
Definition PrimType.h:269
#define TYPE_SWITCH(Expr, B)
Definition PrimType.h:211
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
bool hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U) const
Determine whether two function types are the same, ignoring exception specifications in cases where t...
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
bool hasSimilarType(QualType T1, QualType T2) const
Determine if two types are similar, according to the C++ rules.
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:909
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents a C++ destructor within a class.
Definition DeclCXX.h:2869
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
bool isVirtual() const
Definition DeclCXX.h:2184
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2943
Expr * getCallee()
Definition Expr.h:3090
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3134
Expr ** getArgs()
Retrieve the call arguments.
Definition Expr.h:3137
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1602
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1270
ValueDecl * getDecl()
Definition Expr.h:1338
bool isInvalidDecl() const
Definition DeclBase.h:588
SourceLocation getLocation() const
Definition DeclBase.h:439
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Represents an enum.
Definition Decl.h:4010
unsigned getNumNegativeBits() const
Returns the width in bits required to store all the negative enumerators of this enum.
Definition Decl.h:4220
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:5184
This represents one expression.
Definition Expr.h:112
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:276
QualType getType() const
Definition Expr.h:144
LangOptions::FPExceptionModeKind getExceptionMode() const
RoundingMode getRoundingMode() const
Represents a member of a struct/union/class.
Definition Decl.h:3160
Represents a function declaration or definition.
Definition Decl.h:2000
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition Decl.cpp:3279
QualType getReturnType() const
Definition Decl.h:2845
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2377
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:2888
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition Decl.h:2470
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
Definition Decl.h:2353
bool isUsableAsGlobalAllocationFunctionInConstantEvaluation(UnsignedOrNone *AlignmentParam=nullptr, bool *IsNothrow=nullptr) const
Determines whether this function is one of the replaceable global allocation functions described in i...
Definition Decl.cpp:3426
FunctionDecl * getDefinition()
Get the definition for this declaration.
Definition Decl.h:2282
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3199
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:3246
@ FPE_Ignore
Assume that floating-point exceptions are masked.
This represents a decl that may have a name.
Definition Decl.h:274
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8376
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8365
Encodes a location in the source.
Stmt - This represents one statement.
Definition Stmt.h:85
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
Definition TargetInfo.h:489
The base class of the type hierarchy.
Definition TypeBase.h:1833
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isPointerType() const
Definition TypeBase.h:8529
bool isReferenceType() const
Definition TypeBase.h:8553
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:753
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9009
bool isAnyComplexType() const
Definition TypeBase.h:8664
bool isPointerOrReferenceType() const
Definition TypeBase.h:8533
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1569
A memory block, either on the stack or in the heap.
Definition InterpBlock.h:44
unsigned getSize() const
Returns the size of the block.
Definition InterpBlock.h:87
bool isExtern() const
Checks if the block is extern.
Definition InterpBlock.h:77
const Descriptor * getDescriptor() const
Returns the block's descriptor.
Definition InterpBlock.h:73
bool isStatic() const
Checks if the block has static storage duration.
Definition InterpBlock.h:79
bool isTemporary() const
Checks if the block is temporary.
Definition InterpBlock.h:81
std::byte * rawData()
Returns a pointer to the raw data, including metadata.
UnsignedOrNone getDeclID() const
Returns the declaration ID.
Definition InterpBlock.h:89
bool isDummy() const
Definition InterpBlock.h:84
unsigned getEvalID() const
The Evaluation ID this block was created in.
Definition InterpBlock.h:94
bool isWeak() const
Definition InterpBlock.h:82
bool isAccessible() const
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:57
Compilation context for expressions.
Definition Compiler.h:112
unsigned collectBaseOffset(const RecordDecl *BaseDecl, const RecordDecl *DerivedDecl) const
Definition Context.cpp:644
const Function * getOrCreateFunction(const FunctionDecl *FuncDecl)
Definition Context.cpp:501
ASTContext & getASTContext() const
Returns the AST context.
Definition Context.h:79
OptPrimType classify(QualType T) const
Classifies a type.
Definition Context.cpp:364
const CXXMethodDecl * getOverridingFunction(const CXXRecordDecl *DynamicDecl, const CXXRecordDecl *StaticDecl, const CXXMethodDecl *InitialFunction) const
Definition Context.cpp:465
unsigned getEvalID() const
Definition Context.h:147
Manages dynamic memory allocations done during bytecode interpretation.
bool deallocate(const Expr *Source, const Block *BlockToDelete, InterpState &S)
Deallocate the given source+block combination.
std::optional< Form > getAllocationForm(const Expr *Source) const
Checks whether the allocation done at the given source is an array allocation.
Wrapper around fixed point types.
Definition FixedPoint.h:23
std::string toDiagnosticString(const ASTContext &Ctx) const
Definition FixedPoint.h:81
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Definition Floating.h:35
Base class for stack frames, shared between VM and walker.
Definition Frame.h:25
const Function * getFunction() const
Bytecode function.
Definition Function.h:88
bool isDestructor() const
Checks if the function is a destructor.
Definition Function.h:166
bool isVirtual() const
Checks if the function is virtual.
Definition Function.h:159
bool hasNonNullAttr() const
Definition Function.h:133
bool isConstructor() const
Checks if the function is a constructor.
Definition Function.h:164
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
Definition Function.h:111
bool hasBody() const
Checks if the function already has a body attached.
Definition Function.h:198
bool isConstexpr() const
Definition Function.h:161
bool isThisPointerExplicit() const
Definition Function.h:217
unsigned getWrittenArgSize() const
Definition Function.h:213
bool isLambdaStaticInvoker() const
Returns whether this function is a lambda static invoker, which we generate custom byte code for.
Definition Function.h:174
bool isValid() const
Checks if the function is valid to call.
Definition Function.h:156
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Definition IntegralAP.h:36
Wrapper around numeric types.
Definition Integral.h:66
static Integral from(ValT Value, unsigned NumBits=0)
Definition Integral.h:208
Frame storing local variables.
Definition InterpFrame.h:27
const Expr * getExpr(CodePtr PC) const
InterpFrame * Caller
The frame of the previous function.
Definition InterpFrame.h:30
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
CodePtr getRetPC() const
Returns the return address of the frame.
CodePtr getPC() const
Returns the PC of the frame's code start.
SourceLocation getLocation(CodePtr PC) const
const Pointer & getThis() const
Returns the 'this' pointer.
const Function * getFunction() const
Returns the current function.
Definition InterpFrame.h:76
SourceRange getRange(CodePtr PC) const
bool isRoot() const
Checks if the frame is a root frame - return should quit the interpreter.
unsigned getDepth() const
void clearTo(size_t NewSize)
T pop()
Returns the value from the top of the stack and removes it.
Definition InterpStack.h:39
void push(Tys &&...Args)
Constructs a value in place on the top of the stack.
Definition InterpStack.h:33
size_t size() const
Returns the size of the stack in bytes.
Definition InterpStack.h:77
void discard()
Discards the top value from the stack.
Definition InterpStack.h:50
T & peek() const
Returns a reference to the value on the top of the stack.
Definition InterpStack.h:62
Interpreter context.
Definition InterpState.h:43
Context & getContext() const
bool noteUndefinedBehavior() override
Definition InterpState.h:82
DynamicAllocator & getAllocator()
Context & Ctx
Interpreter Context.
llvm::SmallVector< const Block * > InitializingBlocks
List of blocks we're currently running either constructors or destructors for.
ASTContext & getASTContext() const override
Definition InterpState.h:70
InterpStack & Stk
Temporary stack.
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
InterpFrame * Current
The current frame.
T allocAP(unsigned BitWidth)
const LangOptions & getLangOpts() const
Definition InterpState.h:71
Program & P
Reference to the module containing all bytecode.
PrimType value_or(PrimType PT) const
Definition PrimType.h:68
A pointer to a memory block, live or dead.
Definition Pointer.h:92
Pointer narrow() const
Restricts the scope of an array element pointer.
Definition Pointer.h:189
UnsignedOrNone getDeclID() const
Returns the declaration ID.
Definition Pointer.h:582
bool isVolatile() const
Checks if an object or a subfield is volatile.
Definition Pointer.h:575
bool isInitialized() const
Checks if an object was initialized.
Definition Pointer.cpp:447
bool isStatic() const
Checks if the storage is static.
Definition Pointer.h:500
bool isDynamic() const
Checks if the storage has been dynamically allocated.
Definition Pointer.h:515
bool inUnion() const
Definition Pointer.h:408
bool isZeroSizeArray() const
Checks if the pointer is pointing to a zero-size array.
Definition Pointer.h:660
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
Definition Pointer.h:157
bool isDummy() const
Checks if the pointer points to a dummy value.
Definition Pointer.h:553
bool isExtern() const
Checks if the storage is extern.
Definition Pointer.h:494
int64_t getIndex() const
Returns the index into an array.
Definition Pointer.h:618
bool isActive() const
Checks if the object is active.
Definition Pointer.h:542
bool isConst() const
Checks if an object or a subfield is mutable.
Definition Pointer.h:563
Pointer atField(unsigned Off) const
Creates a pointer to a field.
Definition Pointer.h:174
T & deref() const
Dereferences the pointer, if it's live.
Definition Pointer.h:669
bool isMutable() const
Checks if the field is mutable.
Definition Pointer.h:526
bool isConstInMutable() const
Definition Pointer.h:568
unsigned getNumElems() const
Returns the number of elements.
Definition Pointer.h:602
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition Pointer.h:421
void activate() const
Activats a field.
Definition Pointer.cpp:570
bool isIntegralPointer() const
Definition Pointer.h:475
QualType getType() const
Returns the type of the innermost field.
Definition Pointer.h:341
bool isArrayElement() const
Checks if the pointer points to an array.
Definition Pointer.h:427
bool isLive() const
Checks if the pointer is live.
Definition Pointer.h:273
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition Pointer.h:312
uint64_t getByteOffset() const
Returns the byte offset from the start.
Definition Pointer.h:591
bool isTypeidPointer() const
Definition Pointer.h:477
std::string toDiagnosticString(const ASTContext &Ctx) const
Converts the pointer to a string usable in diagnostics.
Definition Pointer.cpp:434
bool isZero() const
Checks if the pointer is null.
Definition Pointer.h:259
const IntPointer & asIntPointer() const
Definition Pointer.h:461
bool isRoot() const
Pointer points directly to a block.
Definition Pointer.h:443
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition Pointer.h:287
static bool pointToSameBlock(const Pointer &A, const Pointer &B)
Checks if both given pointers point to the same block.
Definition Pointer.cpp:646
APValue toAPValue(const ASTContext &ASTCtx) const
Converts the pointer to an APValue.
Definition Pointer.cpp:172
void endLifetime() const
Definition Pointer.h:738
bool isOnePastEnd() const
Checks if the index is one past end.
Definition Pointer.h:635
uint64_t getIntegerRepresentation() const
Definition Pointer.h:144
bool isPastEnd() const
Checks if the pointer points past the end of the object.
Definition Pointer.h:649
const FieldDecl * getField() const
Returns the field information.
Definition Pointer.h:487
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
Definition Pointer.h:657
void startLifetime() const
Definition Pointer.h:746
bool isBlockPointer() const
Definition Pointer.h:474
bool isTemporary() const
Checks if the storage is temporary.
Definition Pointer.h:507
const FunctionPointer & asFunctionPointer() const
Definition Pointer.h:465
SourceLocation getDeclLoc() const
Definition Pointer.h:297
const Block * block() const
Definition Pointer.h:608
bool isFunctionPointer() const
Definition Pointer.h:476
Pointer getDeclPtr() const
Definition Pointer.h:361
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
Definition Pointer.h:331
bool isBaseClass() const
Checks if a structure is a base class.
Definition Pointer.h:548
size_t elemSize() const
Returns the element size of the innermost field.
Definition Pointer.h:364
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
Definition Pointer.h:450
Lifetime getLifetime() const
Definition Pointer.h:730
void initialize() const
Initializes a field.
Definition Pointer.cpp:498
const std::byte * getRawAddress() const
If backed by actual data (i.e.
Definition Pointer.h:612
bool isField() const
Checks if the item is a field in an object.
Definition Pointer.h:279
const Record * getRecord() const
Returns the record descriptor of a class.
Definition Pointer.h:480
UnsignedOrNone getCurrentDecl() const
Returns the current declaration ID.
Definition Program.h:159
Structure/Class descriptor.
Definition Record.h:25
bool isUnion() const
Checks if the record is a union.
Definition Record.h:57
const CXXDestructorDecl * getDestructor() const
Returns the destructor of the record, if any.
Definition Record.h:65
unsigned getNumVirtualBases() const
Definition Record.h:105
llvm::iterator_range< const_field_iter > fields() const
Definition Record.h:76
Describes the statement/declaration an opcode was generated from.
Definition Source.h:74
bool checkingForUndefinedBehavior() const
Are we checking an expression for overflow?
Definition State.h:103
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
Definition State.cpp:63
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
Definition State.cpp:21
OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation does not produce a C++11 core constant expression.
Definition State.cpp:42
bool checkingPotentialConstantExpression() const
Are we checking whether the expression is a potential constant expression?
Definition State.h:99
Defines the clang::TargetInfo interface.
bool arePotentiallyOverlappingStringLiterals(const Pointer &LHS, const Pointer &RHS)
Definition Interp.cpp:2214
bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off)
Definition Interp.cpp:1497
static bool CheckCallDepth(InterpState &S, CodePtr OpPC)
Definition Interp.cpp:1058
static bool diagnoseCallableDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *DiagDecl)
Definition Interp.cpp:947
static void startLifetimeRecurse(const Pointer &Ptr)
Definition Interp.cpp:1881
bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
Definition Interp.cpp:2144
static bool CheckLifetime(InterpState &S, CodePtr OpPC, Lifetime LT, AccessKinds AK)
Definition Interp.cpp:735
static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition Interp.cpp:641
bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
Definition Interp.cpp:2131
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
Definition Interp.cpp:939
bool CheckFunctionDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *FD)
Opcode. Check if the function decl can be called at compile time.
Definition Interp.cpp:1541
bool EndLifetimePop(InterpState &S, CodePtr OpPC)
Ends the lifetime of the pop'd pointer.
Definition Interp.cpp:1945
static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
Definition Interp.cpp:1029
static bool runRecordDestructor(InterpState &S, CodePtr OpPC, const Pointer &BasePtr, const Descriptor *Desc)
Definition Interp.cpp:1233
bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType)
Definition Interp.cpp:2180
bool LT(InterpState &S, CodePtr OpPC)
Definition Interp.h:1275
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:574
bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC, DynamicAllocator::Form AllocForm, DynamicAllocator::Form DeleteForm, const Descriptor *D, const Expr *NewExpr)
Diagnose mismatched new[]/delete or new/delete[] pairs.
Definition Interp.cpp:1142
bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B)
Checks a direct load of a primitive value from a global or local variable.
Definition Interp.cpp:764
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:1188
bool EndLifetime(InterpState &S, CodePtr OpPC)
Ends the lifetime of the peek'd pointer.
Definition Interp.cpp:1931
bool GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr, const Type *TypeInfoType)
Typeid support.
Definition Interp.cpp:2174
static bool CheckWeak(InterpState &S, CodePtr OpPC, const Block *B)
Definition Interp.cpp:747
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Checks if the Descriptor is of a constexpr or const global variable.
Definition Interp.cpp:470
bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, unsigned BitWidth)
Definition Interp.cpp:2111
static bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B)
Definition Interp.cpp:1259
bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off)
1) Peeks a Pointer 2) Pushes Pointer.atField(Off) on the stack
Definition Interp.cpp:1492
bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK, bool WillActivate)
Definition Interp.cpp:328
static bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *CE, unsigned ArgSize)
Definition Interp.cpp:1211
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
Definition Interp.cpp:616
static void finishGlobalRecurse(InterpState &S, const Pointer &Ptr)
Definition Interp.cpp:2293
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if Ptr is a one-past-the-end pointer.
Definition Interp.cpp:563
bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC, const FixedPoint &FP)
Definition Interp.cpp:2090
static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t Off)
Definition Interp.cpp:1449
static bool hasVirtualDestructor(QualType T)
Definition Interp.cpp:1290
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a value can be loaded from a block.
Definition Interp.cpp:818
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition PrimType.h:189
bool CheckBCPResult(InterpState &S, const Pointer &Ptr)
Definition Interp.cpp:308
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
Definition Interp.cpp:541
bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC)
Checks if dynamic memory allocation is available in the current language mode.
Definition Interp.cpp:1133
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
Definition Interp.cpp:436
bool DiagTypeid(InterpState &S, CodePtr OpPC)
Definition Interp.cpp:2206
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
This is not used by any of the opcodes directly.
Definition Interp.cpp:867
bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits, bool TargetIsUCharOrByte)
Definition Interp.cpp:2157
static void popArg(InterpState &S, const Expr *Arg)
Definition Interp.cpp:256
static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func, const Pointer &ThisPtr)
Definition Interp.cpp:1502
llvm::APInt APInt
Definition FixedPoint.h:19
void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED, const APSInt &Value)
Definition Interp.cpp:1396
bool StartLifetime(InterpState &S, CodePtr OpPC)
Definition Interp.cpp:1900
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
Definition Interp.cpp:530
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:1160
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result, APFloat::opStatus Status, FPOptions FPO)
Checks if the result of a floating-point operation is valid in the current context.
Definition Interp.cpp:1086
PrimType
Enumeration of the primitive types of the VM.
Definition PrimType.h:34
static bool GetDynamicDecl(InterpState &S, CodePtr OpPC, Pointer TypePtr, const CXXRecordDecl *&DynamicDecl)
Definition Interp.cpp:1699
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, uint32_t BuiltinID)
Interpret a builtin function.
bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
Definition Interp.cpp:1564
constexpr bool needsAlloc()
Definition PrimType.h:129
bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index)
Definition Interp.cpp:2103
bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK)
Checks if a pointer is a dummy pointer.
Definition Interp.cpp:1193
bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E, std::optional< uint64_t > ArraySize)
Check if the initializer and storage types of a placement-new expression match.
Definition Interp.cpp:1958
bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T)
Definition Interp.cpp:1417
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
Definition Interp.cpp:428
static void compileFunction(InterpState &S, const Function *Func)
Definition Interp.cpp:1555
bool CheckThis(InterpState &S, CodePtr OpPC)
Checks the 'this' pointer.
Definition Interp.cpp:1069
bool FinishInitGlobal(InterpState &S, CodePtr OpPC)
Definition Interp.cpp:2341
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC, const Function *Func)
Definition Interp.cpp:261
static void copyPrimitiveMemory(InterpState &S, const Pointer &Ptr, PrimType T)
Definition Interp.cpp:2259
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
Definition PrimType.cpp:23
bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm, bool IsGlobalDelete)
Definition Interp.cpp:1297
bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E)
Definition Interp.cpp:2046
bool CallBI(InterpState &S, CodePtr OpPC, const CallExpr *CE, uint32_t BuiltinID)
Definition Interp.cpp:1816
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B)
Definition Interp.cpp:796
static bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition Interp.cpp:927
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
Definition Interp.cpp:410
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr, bool WillBeActivated)
Checks if a value can be stored in a block.
Definition Interp.cpp:898
bool isConstexprUnknown(const Pointer &P)
Definition Interp.cpp:298
bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK)
Definition Interp.h:1821
bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition Interp.cpp:688
llvm::BitVector collectNonNullArgs(const FunctionDecl *F, ArrayRef< const Expr * > Args)
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, const CallExpr *CE)
Definition Interp.cpp:1827
bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
Definition Interp.cpp:1729
static void endLifetimeRecurse(const Pointer &Ptr)
Definition Interp.cpp:1910
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
Definition Interp.cpp:594
bool Interpret(InterpState &S)
Interpreter entry point.
Definition Interp.cpp:2357
llvm::APSInt APSInt
Definition FixedPoint.h:20
bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition Interp.cpp:1523
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ Success
Annotation was successful.
Definition Parser.h:65
@ SC_Extern
Definition Specifiers.h:251
CheckSubobjectKind
The order of this enum is important for diagnostics.
Definition State.h:42
@ CSK_Field
Definition State.h:45
@ Result
The result type of a method or function.
Definition TypeBase.h:905
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
Definition State.h:26
@ AK_Construct
Definition State.h:35
@ 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_Destroy
Definition State.h:36
@ AK_Decrement
Definition State.h:31
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
Describes a memory block created by an allocation site.
Definition Descriptor.h:121
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition Descriptor.h:249
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition Descriptor.h:263
bool hasTrivialDtor() const
Whether variables of this descriptor need their destructor called or not.
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
Definition Descriptor.h:256
const ValueDecl * asValueDecl() const
Definition Descriptor.h:214
QualType getType() const
const Decl * asDecl() const
Definition Descriptor.h:210
const Descriptor *const ElemDesc
Descriptor of the array element.
Definition Descriptor.h:154
unsigned getMetadataSize() const
Returns the size of the metadata.
Definition Descriptor.h:246
SourceLocation getLocation() const
QualType getDataType(const ASTContext &Ctx) const
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition Descriptor.h:254
const VarDecl * asVarDecl() const
Definition Descriptor.h:218
bool isRecord() const
Checks if the descriptor is of a record.
Definition Descriptor.h:268
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition Descriptor.h:152
const Expr * asExpr() const
Definition Descriptor.h:211
bool isArray() const
Checks if the descriptor is of an array.
Definition Descriptor.h:266
Descriptor used for global variables.
Definition Descriptor.h:50
Inline descriptor embedded in structures and arrays.
Definition Descriptor.h:66
std::optional< IntPointer > atOffset(const ASTContext &ASTCtx, unsigned Offset) const
Definition Pointer.cpp:891