clang 24.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/ScopeExit.h"
27#include "llvm/ADT/StringExtras.h"
28
29using namespace clang;
30using namespace clang::interp;
31
32#if __has_cpp_attribute(clang::musttail)
33#define MUSTTAIL [[clang::musttail]]
34#elif __has_cpp_attribute(msvc::musttail)
35#define MUSTTAIL [[msvc::musttail]]
36#elif __has_attribute(musttail)
37#define MUSTTAIL __attribute__((musttail))
38#endif
39
40// On MSVC, musttail does not guarantee tail calls in debug mode.
41// We disable it on MSVC generally since it doesn't seem to be able
42// to handle the way we use tailcalls.
43// PPC can't tail-call external calls, which is a problem for InterpNext.
44#if defined(_MSC_VER) || defined(__powerpc__) || !defined(MUSTTAIL) || \
45 defined(__i386__) || defined(__sparc__)
46#undef MUSTTAIL
47#define MUSTTAIL
48#define USE_TAILCALLS 0
49#else
50#define USE_TAILCALLS 1
51#endif
52
54 llvm::report_fatal_error("Interpreter cannot return values");
55}
56
57//===----------------------------------------------------------------------===//
58// Jmp, Jt, Jf
59//===----------------------------------------------------------------------===//
60
61static bool Jmp(InterpState &S, CodePtr OpPC, int32_t Offset) {
62 S.PC += Offset;
63 return S.noteStep(OpPC);
64}
65
66static bool Jt(InterpState &S, CodePtr OpPC, int32_t Offset) {
67 if (S.Stk.pop<bool>()) {
68 S.PC += Offset;
69 return S.noteStep(OpPC);
70 }
71 return true;
72}
73
74static bool Jf(InterpState &S, CodePtr OpPC, int32_t Offset) {
75 if (!S.Stk.pop<bool>()) {
76 S.PC += Offset;
77 return S.noteStep(OpPC);
78 }
79 return true;
80}
81
83 const ValueDecl *VD) {
84 const SourceInfo &E = S.Current->getSource(OpPC);
85 S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
86 S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
87}
88
89static void noteValueLocation(InterpState &S, const Block *B) {
90 const Descriptor *Desc = B->getDescriptor();
91
92 if (B->isDynamic())
93 S.Note(Desc->getLocation(), diag::note_constexpr_dynamic_alloc_here);
94 else if (B->isTemporary())
95 S.Note(Desc->getLocation(), diag::note_constexpr_temporary_here);
96 else
97 S.Note(Desc->getLocation(), diag::note_declared_at);
98}
99
100static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
101 const ValueDecl *VD,
102 AccessKinds AK = AK_Read);
104 const ValueDecl *D, AccessKinds AK = AK_Read) {
105 // This function tries pretty hard to produce a good diagnostic. Just skip
106 // that if nobody will see it anyway.
107 if (!S.diagnosing())
108 return false;
109
110 if (isa<ParmVarDecl>(D)) {
111 if (D->getType()->isReferenceType()) {
112 if (S.inConstantContext() && S.getLangOpts().CPlusPlus &&
113 !S.getLangOpts().CPlusPlus11) {
114 diagnoseNonConstVariable(S, OpPC, D);
115 return false;
116 }
117 }
118
119 const SourceInfo &Loc = S.Current->getSource(OpPC);
120 if (S.getLangOpts().CPlusPlus23 && D->getType()->isReferenceType()) {
121 S.FFDiag(Loc, diag::note_constexpr_access_unknown_variable, 1)
122 << AK_Read << D;
123 S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
124 } else if (S.getLangOpts().CPlusPlus11) {
125 S.FFDiag(Loc, diag::note_constexpr_function_param_value_unknown, 1) << D;
126 S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
127 } else {
128 S.FFDiag(Loc);
129 }
130 return false;
131 }
132
133 if (!D->getType().isConstQualified()) {
134 diagnoseNonConstVariable(S, OpPC, D, AK);
135 } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
136 if (!VD->getAnyInitializer()) {
137 diagnoseMissingInitializer(S, OpPC, VD);
138 } else {
139 const SourceInfo &Loc = S.Current->getSource(OpPC);
140 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
141 S.Note(VD->getLocation(), diag::note_declared_at);
142 }
143 }
144
145 return false;
146}
147
149 return AK == AK_Assign || AK == AK_Increment || AK == AK_Decrement ||
150 AK == AK_Construct || AK == AK_Destroy;
151}
152
154 const ValueDecl *VD, AccessKinds AK) {
155 if (!S.diagnosing())
156 return;
157
158 if (!S.getLangOpts().CPlusPlus) {
159 S.FFDiag(S.Current->getSource(OpPC));
160 return;
161 }
162
163 if (const auto *VarD = dyn_cast<VarDecl>(VD);
164 VarD && VarD->getType().isConstQualified() &&
165 (VarD->isConstexpr() || !VarD->getType()->isArrayType()) &&
166 !VarD->getAnyInitializer()) {
167 diagnoseMissingInitializer(S, OpPC, VD);
168 return;
169 }
170
171 // Rather random, but this is to match the diagnostic output of the current
172 // interpreter.
173 if (isa<ObjCIvarDecl>(VD))
174 return;
175
177 SourceInfo Loc = S.Current->getSource(OpPC);
178 if (isModification(AK)) {
179 S.FFDiag(Loc, diag::note_constexpr_modify_global);
180 } else {
181 S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
182 S.Note(VD->getLocation(), diag::note_declared_at);
183 }
184 return;
185 }
186
187 S.FFDiag(S.Current->getSource(OpPC),
188 S.getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
189 : diag::note_constexpr_ltor_non_integral,
190 1)
191 << VD << VD->getType();
192 S.Note(VD->getLocation(), diag::note_declared_at);
193}
194
195static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Block *B,
196 AccessKinds AK) {
197 if (B->getDeclID()) {
198 if (!(B->isStatic() && B->isTemporary()))
199 return true;
200
201 const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
202 B->getDescriptor()->asExpr());
203 if (!MTE)
204 return true;
205
206 // FIXME(perf): Since we do this check on every Load from a static
207 // temporary, it might make sense to cache the value of the
208 // isUsableInConstantExpressions call.
210 (B->getEvalID() != S.EvalID &&
211 !MTE->isUsableInConstantExpressions(S.getASTContext()))) {
212 const SourceInfo &E = S.Current->getSource(OpPC);
213 S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
214 noteValueLocation(S, B);
215 return false;
216 }
217 }
218
219 return true;
220}
221
222static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
223 if (auto ID = Ptr.getDeclID()) {
224 if (!Ptr.isStatic())
225 return true;
226
227 if (S.P.getCurrentDecl() == ID)
228 return true;
229
230 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
231 return false;
232 }
233 return true;
234}
235
236namespace clang {
237namespace interp {
238PRESERVE_NONE static bool BCP(InterpState &S, CodePtr OpPC, int32_t Offset,
239 PrimType PT);
240
242 const APSInt *Value, unsigned Bits) {
243 switch (Failure) {
245 assert(Value);
246 S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_negative_shift)
247 << *Value;
248 break;
250 assert(Value);
251 const Expr *E = S.Current->getExpr(OpPC);
252 S.CCEDiag(E, diag::note_constexpr_large_shift)
253 << *Value << E->getType() << Bits;
254 break;
255 }
257 assert(Value);
258 S.CCEDiag(S.Current->getExpr(OpPC), diag::note_constexpr_lshift_of_negative)
259 << *Value;
260 break;
262 S.CCEDiag(S.Current->getExpr(OpPC), diag::note_constexpr_lshift_discards);
263 break;
264 }
265 return S.noteUndefinedBehavior();
266}
267
269 assert(S.Current);
270 assert(Func);
271
272 // Pop variadic parameter values from the stack.
273 if (S.Current->Caller && Func->isVariadic()) {
274 unsigned VariadicArgSize =
276 unsigned TargetStackSize = S.Stk.size() - VariadicArgSize;
277 while (S.Stk.size() != TargetStackSize) {
278 S.Stk.discardSlow();
279 }
280 }
281
282 // And in any case, remove the fixed parameters (the non-variadic ones)
283 // at the end.
284 for (const Function::ParamDescriptor &PDesc : Func->args_reverse())
285 TYPE_SWITCH(PDesc.T, S.Stk.discard<T>());
286
287 if (Func->hasImplicitThisPointer())
288 S.Stk.discard<Pointer>();
289 if (Func->hasRVO())
290 S.Stk.discard<Pointer>();
291}
292
293bool isConstexprUnknown(const Block *B) {
294 if (B->isDummy())
295 return isa_and_nonnull<ParmVarDecl>(B->getDescriptor()->asValueDecl());
297}
298
300 if (!P.isBlockPointer() || P.isZero())
301 return false;
302 return isConstexprUnknown(P.block());
303}
304
305bool CheckBCPResult(InterpState &S, const Pointer &Ptr) {
306 if (Ptr.isDummy())
307 return false;
308 if (Ptr.isZero())
309 return true;
310 if (Ptr.isFunctionPointer())
311 return false;
312 if (Ptr.isIntegralPointer())
313 return true;
314 if (Ptr.isTypeidPointer())
315 return true;
316
317 if (Ptr.getType()->isAnyComplexType())
318 return true;
319
320 if (const Expr *Base = Ptr.getRootExpr())
321 return isa<StringLiteral>(Base) && Ptr.getIndex() == 0;
322 return false;
323}
324
325bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
326 AccessKinds AK, bool WillActivate) {
327 if (Ptr.isActive())
328 return true;
329
330 assert(Ptr.inUnion());
331
332 // Find the outermost union.
333 PtrView U = Ptr.view().getBase();
334 PtrView C = Ptr.view();
335 while (!U.isRoot() && !U.isActive()) {
336 // A little arbitrary, but this is what the current interpreter does.
337 // See the AnonymousUnion test in test/AST/ByteCode/unions.cpp.
338 // GCC's output is more similar to what we would get without
339 // this condition.
340 if (U.getRecord() && U.getRecord()->isAnonymousUnion())
341 break;
342
343 C = U;
344 U = U.getBase();
345 }
346 assert(C.isField());
347 assert(C.getBase() == U);
348
349 // Consider:
350 // union U {
351 // struct {
352 // int x;
353 // int y;
354 // } a;
355 // }
356 //
357 // When activating x, we will also activate a. If we now try to read
358 // from y, we will get to CheckActive, because y is not active. In that
359 // case, our U will be a (not a union). We return here and let later code
360 // handle this.
361 if (!U.getFieldDesc()->isUnion())
362 return true;
363
364 // When we will activate Ptr, check that none of the unions in its path have a
365 // non-trivial default constructor.
366 if (WillActivate) {
367 bool Fails = false;
368 PtrView It = Ptr.view();
369 while (!It.isRoot() && !It.isActive()) {
370 if (const Record *R = It.getRecord(); R && R->isUnion()) {
371 if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(R->getDecl());
372 CXXRD && !CXXRD->hasTrivialDefaultConstructor()) {
373 Fails = true;
374 break;
375 }
376 }
377 It = It.getBase();
378 }
379 if (!Fails)
380 return true;
381 }
382
383 // Get the inactive field descriptor.
384 assert(!C.isActive());
385 const FieldDecl *InactiveField = C.getField();
386 assert(InactiveField);
387
388 // Find the active field of the union.
389 const Record *R = U.getRecord();
390 assert(R && R->isUnion() && "Not a union");
391
392 const FieldDecl *ActiveField = nullptr;
393 for (const Record::Field &F : R->fields()) {
394 PtrView Field = U.atField(F.Offset);
395 if (Field.isActive()) {
396 ActiveField = Field.getField();
397 break;
398 }
399 }
400
401 S.FFDiag(S.Current->getSource(OpPC),
402 diag::note_constexpr_access_inactive_union_member)
403 << AK << InactiveField << !ActiveField << ActiveField;
404 return false;
405}
406
407bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
408 if (!Ptr.isExtern())
409 return true;
410
411 if (!Ptr.isPastEnd() &&
412 (Ptr.isInitialized() ||
413 (Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl)))
414 return true;
415
416 if (S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus &&
417 Ptr.isConst())
418 return false;
419
420 const auto *VD = Ptr.getDeclDesc()->asValueDecl();
421 if (!Ptr.isConstexprUnknown() || !S.checkingPotentialConstantExpression())
422 diagnoseNonConstVariable(S, OpPC, VD);
423 return false;
424}
425
426bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
427 if (!Ptr.isUnknownSizeArray())
428 return true;
429 const SourceInfo &E = S.Current->getSource(OpPC);
430 S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
431 return false;
432}
433
434bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
435 AccessKinds AK) {
436 if (Ptr.isZero()) {
437 const auto &Src = S.Current->getSource(OpPC);
438
439 if (Ptr.isField())
440 S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
441 else
442 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
443
444 return false;
445 }
446
447 if (!Ptr.isLive()) {
448 const auto &Src = S.Current->getSource(OpPC);
449
450 if (Ptr.isDynamic()) {
451 S.FFDiag(Src, diag::note_constexpr_access_deleted_object) << AK;
452 } else if (!S.checkingPotentialConstantExpression()) {
453 S.FFDiag(Src, diag::note_constexpr_access_uninit)
454 << AK << /*uninitialized=*/false << S.Current->getRange(OpPC);
455 noteValueLocation(S, Ptr.block());
456 }
457
458 return false;
459 }
460
461 return true;
462}
463
464bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc,
465 AccessKinds AK) {
466 assert(Desc);
467
468 const auto *D = Desc->asVarDecl();
470 // If we're checking for a constant destructor for this variable, we can
471 // only read from it if it is constant.
472 if (D->getType().isConstQualified())
473 return true;
474 } else 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 = 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, AK);
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, AK);
513 return false;
514 }
515 return true;
516 }
517
518 diagnoseNonConstVariable(S, OpPC, D, AK);
519 return false;
520}
521
522static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
523 AccessKinds AK = AK_Read) {
525 return CheckConstant(S, OpPC, Ptr.getDeclDesc(), AK);
526
527 if (!Ptr.isStatic() || !Ptr.isBlockPointer())
528 return true;
529 if (!Ptr.getDeclID())
530 return true;
531 return CheckConstant(S, OpPC, Ptr.getDeclDesc(), AK);
532}
533
534bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
535 CheckSubobjectKind CSK) {
536 if (!Ptr.isZero())
537 return true;
538 const SourceInfo &Loc = S.Current->getSource(OpPC);
539 S.FFDiag(Loc, diag::note_constexpr_null_subobject)
540 << CSK << S.Current->getRange(OpPC);
541
542 return false;
543}
544
545bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
546 CheckSubobjectKind CSK) {
547 if (!Ptr.isElementPastEnd() && !Ptr.isZeroSizeArray())
548 return true;
549 const SourceInfo &Loc = S.Current->getSource(OpPC);
550 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
551 << CSK << S.Current->getRange(OpPC);
552 return false;
553}
554
555bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
556 CheckSubobjectKind CSK) {
557 if (!Ptr.isOnePastEnd())
558 return true;
559
560 const SourceInfo &Loc = S.Current->getSource(OpPC);
561 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
562 << CSK << S.Current->getRange(OpPC);
563 return false;
564}
565
566bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
567 uint32_t Offset) {
568 uint32_t MinOffset = Ptr.block()->getMetadataSize();
569 uint32_t PtrOffset = Ptr.getByteOffset();
570
571 // We subtract Offset from PtrOffset. The result must be at least
572 // MinOffset.
573 if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
574 return true;
575
576 const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
577 QualType ExprTy = E->getType();
578 if (ExprTy->isPointerOrReferenceType())
579 ExprTy = ExprTy->getPointeeType();
580
581 QualType TargetQT = ExprTy;
582 QualType MostDerivedQT = Ptr.getDeclPtr().getType();
583
584 if (MostDerivedQT->isPointerOrReferenceType())
585 MostDerivedQT = MostDerivedQT->getPointeeType();
586
587 S.CCEDiag(E, diag::note_constexpr_invalid_downcast)
588 << MostDerivedQT << TargetQT;
589
590 return false;
591}
592
593bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
594 assert(Ptr.isLive() && "Pointer is not live");
595 if (!Ptr.isConst())
596 return true;
597
598 if (Ptr.isMutable() && !Ptr.isConstInMutable())
599 return true;
600
601 if (!Ptr.isBlockPointer())
602 return false;
603
604 // The This pointer is writable in constructors and destructors,
605 // even if isConst() returns true.
606 for (PtrView V : llvm::reverse(S.InitializingPtrs)) {
607 if (V.block() != Ptr.block())
608 continue;
609 if (!V.getFieldDesc()->IsConst) {
610 // If the pointer being initialized is not declared as const,
611 // Ptr is const because of a parent of V, but that is irrelevant
612 // since V is being initialized and NOT const.
613 // This is fine, so return true.
614 return true;
615 }
616
617 // We know that Ptr is const because of a parent field and we also
618 // know that V is explicitly marked const.
619 // But since V is in InitializingPtrs, the fact that it is const doesn't
620 // matter and it is writable.
621 // What we now need to check is whether there is a pointer between Ptr and V
622 // that is marked const but NOT in InitializingPtrs. If that is the case,
623 // Ptr is currently not writable.
624 bool FoundProblem = false;
625 for (PtrView P = Ptr.view(); P != V; P = P.getBase()) {
626 if (P.getFieldDesc()->IsConst) {
627 FoundProblem = true;
628 break;
629 }
630 }
631
632 // We couldn't find any pointer that's explicitly marked const, so
633 // Ptr is writable right now.
634 if (!FoundProblem)
635 return true;
636 // We only need to find the right block once.
637 break;
638 }
639
641 QualType Ty = Ptr.getType();
642 if (!Ptr.getFieldDesc()->IsConst)
643 Ty.addConst();
644 const SourceInfo &Loc = S.Current->getSource(OpPC);
645 S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
646 }
647 return false;
648}
649
651 assert(Ptr.isLive() && "Pointer is not live");
652 if (!Ptr.isMutable())
653 return true;
654
656 // Never allowed when checking for constant destruction.
657 // Diagnose below.
658 } else if (S.getLangOpts().CPlusPlus14 &&
659 S.lifetimeStartedInEvaluation(Ptr.block())) {
660 // In C++14 onwards, it is permitted to read a mutable member whose
661 // lifetime began within the evaluation.
662 return true;
663 }
664
665 // Find the reason this pointer is mutable.
666 PtrView MutablePtr = Ptr;
667 while (!MutablePtr.isRoot() && MutablePtr.getBase().isMutable())
668 MutablePtr = MutablePtr.getBase();
669
670 const SourceInfo &Loc = S.Current->getSource(OpPC);
671 const FieldDecl *Field = MutablePtr.getField();
672 S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK << Field;
673 S.Note(Field->getLocation(), diag::note_declared_at);
674 return false;
675}
676
677static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
678 AccessKinds AK) {
679 assert(Ptr.isLive());
680
681 if (!Ptr.isVolatile())
682 return true;
683
684 if (!S.getLangOpts().CPlusPlus)
685 return Invalid(S, OpPC);
686
687 // Volatile object can be written-to and read if they are being constructed.
688 if (S.initializingBlock(Ptr.block()))
689 return true;
690
691 // The reason why Ptr is volatile might be further up the hierarchy.
692 // Find that pointer.
693 Pointer P = Ptr;
694 while (!P.isRoot()) {
696 break;
697 P = P.getBase();
698 }
699
700 const NamedDecl *ND = nullptr;
701 int DiagKind;
702 SourceLocation Loc;
703 if (const auto *F = P.getField()) {
704 DiagKind = 2;
705 Loc = F->getLocation();
706 ND = F;
707 } else if (auto *VD = P.getFieldDesc()->asValueDecl()) {
708 DiagKind = 1;
709 Loc = VD->getLocation();
710 ND = VD;
711 } else {
712 DiagKind = 0;
713 if (const auto *E = P.getFieldDesc()->asExpr())
714 Loc = E->getExprLoc();
715 }
716
717 S.FFDiag(S.Current->getLocation(OpPC),
718 diag::note_constexpr_access_volatile_obj, 1)
719 << AK << DiagKind << ND;
720 S.Note(Loc, diag::note_constexpr_volatile_here) << DiagKind;
721 return false;
722}
723
725 AccessKinds AK) {
726 assert(Ptr.isLive());
727 assert(!Ptr.isInitialized());
728 return diagnoseUninitialized(S, OpPC, Ptr.isExtern(), Ptr.block(),
729 Ptr.getLifetime(), AK);
730}
731
732bool diagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern,
733 const Block *B, Lifetime LT, AccessKinds AK) {
735 // Extern and static member declarations might be initialized later.
736 if (Extern)
737 return false;
738
739 if (const VarDecl *VD = B->getDescriptor()->asVarDecl();
740 VD && VD->isStaticDataMember())
741 return false;
742 }
743
744 const Descriptor *Desc = B->getDescriptor();
745
746 if (const auto *VD = Desc->asVarDecl();
747 VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
748
749 if (VD == S.EvaluatingDecl &&
750 !(S.getLangOpts().CPlusPlus23 && VD->getType()->isReferenceType())) {
751 if (!S.getLangOpts().CPlusPlus14 &&
752 !VD->getType().isConstant(S.getASTContext())) {
753 // Diagnose as non-const read.
754 diagnoseNonConstVariable(S, OpPC, VD);
755 } else {
756 // Diagnose as "read of object outside its lifetime".
757 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
758 << AK << /*IsIndeterminate=*/false;
759 S.Note(VD->getFirstDecl()->getLocation(), diag::note_declared_at);
760 }
761 return false;
762 }
763
764 if (VD->getAnyInitializer()) {
765 const SourceInfo &Loc = S.Current->getSource(OpPC);
766 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
767 S.Note(VD->getLocation(), diag::note_declared_at);
768 } else {
769 diagnoseMissingInitializer(S, OpPC, VD);
770 }
771 return false;
772 }
773
775 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
776 << AK << /*uninitialized=*/(LT == Lifetime::Started)
777 << S.Current->getRange(OpPC);
778 noteValueLocation(S, B);
779 }
780 return false;
781}
782
784 const Block *B, AccessKinds AK) {
785 if (LT == Lifetime::Started)
786 return true;
787
789 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
790 << AK << /*uninitialized=*/false << S.Current->getRange(OpPC);
791 noteValueLocation(S, B);
792 }
793 return false;
794}
795static bool CheckLifetime(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
796 AccessKinds AK) {
797 return CheckLifetime(S, OpPC, Ptr.getLifetime(), Ptr.block(), AK);
798}
799
800static bool CheckWeak(InterpState &S, CodePtr OpPC, const Block *B) {
801 if (!B->isWeak())
802 return true;
803
804 const auto *VD = B->getDescriptor()->asVarDecl();
805 assert(VD);
806 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_var_init_weak)
807 << VD;
808 S.Note(VD->getLocation(), diag::note_declared_at);
809
810 return false;
811}
812
813// The list of checks here is just the one from CheckLoad, but with the
814// ones removed that are impossible on primitive global values.
815// For example, since those can't be members of structs, they also can't
816// be mutable.
817bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
818 const auto &Desc = B->getBlockDesc<GlobalInlineDescriptor>();
819 if (!B->isAccessible()) {
820 if (!CheckExtern(S, OpPC, Pointer(const_cast<Block *>(B))))
821 return false;
822 if (!CheckDummy(S, OpPC, B, AK_Read))
823 return false;
824 return CheckWeak(S, OpPC, B);
825 }
826
827 if (!CheckConstant(S, OpPC, B->getDescriptor()))
828 return false;
829 if (Desc.InitState != GlobalInitState::Initialized)
830 return diagnoseUninitialized(S, OpPC, B->isExtern(), B);
831 if (!CheckTemporary(S, OpPC, B, AK_Read))
832 return false;
833 if (B->getDescriptor()->IsVolatile) {
834 if (!S.getLangOpts().CPlusPlus)
835 return Invalid(S, OpPC);
836
837 const ValueDecl *D = B->getDescriptor()->asValueDecl();
838 S.FFDiag(S.Current->getLocation(OpPC),
839 diag::note_constexpr_access_volatile_obj, 1)
840 << AK_Read << 1 << D;
841 S.Note(D->getLocation(), diag::note_constexpr_volatile_here) << 1;
842 return false;
843 }
844 return true;
845}
846
847// Similarly, for local loads.
848bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
849 assert(!B->isExtern());
850 const auto &Desc = *reinterpret_cast<const InlineDescriptor *>(B->rawData());
851 const Descriptor *BlockDesc = B->getDescriptor();
852 if (!Desc.IsInitialized)
853 return diagnoseUninitialized(S, OpPC, /*Extern=*/false, B, Desc.LifeState);
854 if (!CheckLifetime(S, OpPC, Desc.LifeState, B, AK_Read))
855 return false;
856 if (BlockDesc->IsVolatile) {
857 if (!S.getLangOpts().CPlusPlus)
858 return Invalid(S, OpPC);
859
860 const ValueDecl *D = BlockDesc->asValueDecl();
861 S.FFDiag(S.Current->getLocation(OpPC),
862 diag::note_constexpr_access_volatile_obj, 1)
863 << AK_Read << 1 << D;
864 S.Note(D->getLocation(), diag::note_constexpr_volatile_here) << 1;
865 return false;
866 }
867
868 // A non-const local variable while we don't have a parent frame. This must be
869 // a local variable in a statement expression.
870 if (S.Current->isBottomFrame() && !BlockDesc->IsConst &&
872 if (const ValueDecl *VD = BlockDesc->asValueDecl())
873 diagnoseNonConstVariable(S, OpPC, VD);
874 return false;
875 }
876 return true;
877}
878
879bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
880 AccessKinds AK) {
881 if (Ptr.isZero()) {
882 const auto &Src = S.Current->getSource(OpPC);
883
884 if (Ptr.isField())
885 S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
886 else
887 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
888 return false;
889 }
890 // Block and string pointers are the only ones we can actually read from.
891 if (!Ptr.isReadablePointerType())
892 return false;
893
894 if (Ptr.isBlockPointer() && !Ptr.block()->isAccessible()) {
895 if (!CheckLive(S, OpPC, Ptr, AK))
896 return false;
897 if (!CheckExtern(S, OpPC, Ptr))
898 return false;
899 if (!CheckDummy(S, OpPC, Ptr.block(), AK))
900 return false;
901 return CheckWeak(S, OpPC, Ptr.block());
902 }
903
904 if (!CheckConstant(S, OpPC, Ptr, AK))
905 return false;
906 if (!CheckRange(S, OpPC, Ptr, AK))
907 return false;
908 if (!CheckActive(S, OpPC, Ptr, AK))
909 return false;
910 if (!Ptr.isInitialized())
911 return diagnoseUninitialized(S, OpPC, Ptr, AK);
912 if (!CheckLifetime(S, OpPC, Ptr, AK))
913 return false;
914 if (Ptr.isBlockPointer() && !CheckTemporary(S, OpPC, Ptr.block(), AK))
915 return false;
916
917 if (!CheckMutable(S, OpPC, Ptr))
918 return false;
919 if (!CheckVolatile(S, OpPC, Ptr, AK))
920 return false;
921 if (isConstexprUnknown(Ptr))
922 return false;
923
924 if (Ptr.isBlockPointer() && !Ptr.isArrayRoot()) {
925 // According to GCC info page:
926 //
927 // 6.28 Compound Literals
928 //
929 // As an optimization, G++ sometimes gives array compound literals
930 // longer lifetimes: when the array either appears outside a function or
931 // has a const-qualified type. If foo and its initializer had elements
932 // of type char *const rather than char *, or if foo were a global
933 // variable, the array would have static storage duration. But it is
934 // probably safest just to avoid the use of array compound literals in
935 // C++ code.
936 //
937 // Obey that rule by checking constness for converted array types.
938 const Descriptor *Desc = Ptr.getFieldDesc();
939 if (const auto *CLE =
940 dyn_cast_if_present<CompoundLiteralExpr>(Desc->asExpr())) {
941 if (QualType CLETy = CLE->getType();
942 CLETy->isArrayType() && !CLETy.isConstant(S.getASTContext())) {
943 S.FFDiag(S.Current->getLocation(OpPC),
944 diag::note_invalid_subexpr_in_const_expr)
945 << S.Current->getRange(OpPC);
946 S.Note(CLE->getExprLoc(), diag::note_declared_at);
947 return false;
948 }
949 }
950 }
951 return true;
952}
953
954/// This is not used by any of the opcodes directly. It's used by
955/// EvalEmitter to do the final lvalue-to-rvalue conversion.
956bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
957 assert(!Ptr.isZero());
958 if (!Ptr.isReadablePointerType())
959 return false;
960
961 if (Ptr.isBlockPointer() && !Ptr.block()->isAccessible()) {
962 if (!CheckLive(S, OpPC, Ptr, AK_Read))
963 return false;
964 if (!CheckExtern(S, OpPC, Ptr))
965 return false;
966 if (!CheckDummy(S, OpPC, Ptr.block(), AK_Read))
967 return false;
968 return CheckWeak(S, OpPC, Ptr.block());
969 }
970
971 if (!CheckConstant(S, OpPC, Ptr))
972 return false;
973
974 if (!CheckActive(S, OpPC, Ptr, AK_Read))
975 return false;
976 if (!CheckLifetime(S, OpPC, Ptr, AK_Read))
977 return false;
978 if (!Ptr.isInitialized())
979 return diagnoseUninitialized(S, OpPC, Ptr, AK_Read);
980 if (Ptr.isBlockPointer() && !CheckTemporary(S, OpPC, Ptr.block(), AK_Read))
981 return false;
982 if (!CheckMutable(S, OpPC, Ptr))
983 return false;
984 if (Ptr.isConstexprUnknown())
985 return false;
986 return true;
987}
988
989bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
990 bool WillBeActivated) {
991 if (!Ptr.isBlockPointer() || Ptr.isZero())
992 return false;
993
994 if (!Ptr.block()->isAccessible()) {
995 if (!CheckLive(S, OpPC, Ptr, AK_Assign))
996 return false;
997 if (!CheckExtern(S, OpPC, Ptr))
998 return false;
999 return CheckDummy(S, OpPC, Ptr.block(), AK_Assign);
1000 }
1001 if (!WillBeActivated && !CheckLifetime(S, OpPC, Ptr, AK_Assign))
1002 return false;
1003 if (!CheckRange(S, OpPC, Ptr, AK_Assign))
1004 return false;
1005 if (!CheckActive(S, OpPC, Ptr, AK_Assign, WillBeActivated))
1006 return false;
1007 if (!CheckGlobal(S, OpPC, Ptr))
1008 return false;
1009 if (!CheckConst(S, OpPC, Ptr))
1010 return false;
1011 if (!CheckVolatile(S, OpPC, Ptr, AK_Assign))
1012 return false;
1013 if (!CheckMutable(S, OpPC, Ptr, AK_Assign))
1014 return false;
1015 if (isConstexprUnknown(Ptr))
1016 return false;
1017 return true;
1018}
1019
1020static bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
1021 bool IsCtor, bool IsDtor) {
1022 if (!Ptr.isDummy() && !isConstexprUnknown(Ptr)) {
1023 if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
1024 return false;
1025 if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
1026 return false;
1027 if (!(IsCtor || IsDtor) && !CheckLifetime(S, OpPC, Ptr, AK_MemberCall))
1028 return false;
1029 }
1030 return true;
1031}
1032
1033bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
1034 if (!CheckLive(S, OpPC, Ptr, AK_Assign))
1035 return false;
1036 if (!CheckRange(S, OpPC, Ptr, AK_Assign))
1037 return false;
1038 return true;
1039}
1040
1042 const FunctionDecl *DiagDecl) {
1043 // Bail out if the function declaration itself is invalid. We will
1044 // have produced a relevant diagnostic while parsing it, so just
1045 // note the problematic sub-expression.
1046 if (DiagDecl->isInvalidDecl())
1047 return Invalid(S, OpPC);
1048
1049 // Diagnose failed assertions specially.
1050 if (S.Current->getLocation(OpPC).isMacroID() && DiagDecl->getIdentifier()) {
1051 // FIXME: Instead of checking for an implementation-defined function,
1052 // check and evaluate the assert() macro.
1053 StringRef Name = DiagDecl->getName();
1054 bool AssertFailed =
1055 Name == "__assert_rtn" || Name == "__assert_fail" || Name == "_wassert";
1056 if (AssertFailed) {
1057 S.FFDiag(S.Current->getLocation(OpPC),
1058 diag::note_constexpr_assert_failed);
1059 return false;
1060 }
1061 }
1062
1063 if (!S.getLangOpts().CPlusPlus11) {
1064 S.FFDiag(S.Current->getLocation(OpPC),
1065 diag::note_invalid_subexpr_in_const_expr);
1066 return false;
1067 }
1068
1069 // If this function is not constexpr because it is an inherited
1070 // non-constexpr constructor, diagnose that directly.
1071 const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
1072 if (CD && CD->isInheritingConstructor()) {
1073 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
1074 if (!Inherited->isConstexpr())
1075 DiagDecl = CD = Inherited;
1076 }
1077
1078 // Silently reject constructors of invalid classes. The invalid class
1079 // has been rejected elsewhere before.
1080 if (CD && CD->getParent()->isInvalidDecl())
1081 return false;
1082
1083 // FIXME: If DiagDecl is an implicitly-declared special member function
1084 // or an inheriting constructor, we should be much more explicit about why
1085 // it's not constexpr.
1086 if (CD && CD->isInheritingConstructor()) {
1087 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_invalid_inhctor,
1088 1)
1089 << CD->getInheritedConstructor().getConstructor()->getParent();
1090 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
1091 } else {
1092 // Don't emit anything if the function isn't defined and we're checking
1093 // for a constant expression. It might be defined at the point we're
1094 // actually calling it.
1095 bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
1096 bool IsDefined = DiagDecl->isDefined();
1097 if (!IsDefined && !IsExtern && DiagDecl->isConstexpr() &&
1099 return false;
1100
1101 // If the declaration is defined, declared 'constexpr' _and_ has a body,
1102 // the below diagnostic doesn't add anything useful.
1103 if (DiagDecl->isDefined() && DiagDecl->isConstexpr() && DiagDecl->hasBody())
1104 return false;
1105
1106 S.FFDiag(S.Current->getLocation(OpPC),
1107 diag::note_constexpr_invalid_function, 1)
1108 << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
1109
1110 const FunctionDecl *Definition;
1111 bool HasBody = DiagDecl->hasBody(Definition);
1112 if (HasBody && Definition)
1113 S.Note(Definition->getLocation(), diag::note_declared_at);
1114 else
1115 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
1116 }
1117
1118 return false;
1119}
1120
1121static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
1122 if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
1123 const SourceLocation &Loc = S.Current->getLocation(OpPC);
1124 S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
1125 return false;
1126 }
1127
1128 if (F->isValid() && F->hasBody() &&
1130 F->getDecl()->hasAttr<MSConstexprAttr>())))
1131 return true;
1132
1133 const FunctionDecl *DiagDecl = F->getDecl();
1134 const FunctionDecl *Definition = nullptr;
1135 DiagDecl->hasBody(Definition);
1136
1138 DiagDecl->isConstexpr()) {
1139 return false;
1140 }
1141
1142 return diagnoseCallableDecl(S, OpPC, DiagDecl);
1143}
1144
1145static bool CheckCallDepth(InterpState &S, CodePtr OpPC) {
1146 if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
1147 S.FFDiag(S.Current->getSource(OpPC),
1148 diag::note_constexpr_depth_limit_exceeded)
1149 << S.getLangOpts().ConstexprCallDepth;
1150 return false;
1151 }
1152
1153 return true;
1154}
1155
1157 if (S.Current->hasThisPointer())
1158 return true;
1159
1160 const Expr *E = S.Current->getExpr(OpPC);
1161 if (S.getLangOpts().CPlusPlus11) {
1162 bool IsImplicit = false;
1163 if (const auto *TE = dyn_cast<CXXThisExpr>(E))
1164 IsImplicit = TE->isImplicit();
1165 S.FFDiag(E, diag::note_constexpr_this) << IsImplicit;
1166 } else {
1167 S.FFDiag(E);
1168 }
1169
1170 return false;
1171}
1172
1173bool CheckFloatStatus(InterpState &S, CodePtr OpPC, APFloat::opStatus Status,
1174 FPOptions FPO) {
1175 // In a constant context, assume that any dynamic rounding mode or FP
1176 // exception state matches the default floating-point environment.
1177 if (S.inConstantContext())
1178 return true;
1179
1180 if ((Status & APFloat::opInexact) &&
1181 FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) {
1182 // Inexact result means that it depends on rounding mode. If the requested
1183 // mode is dynamic, the evaluation cannot be made in compile time.
1184 const SourceInfo &E = S.Current->getSource(OpPC);
1185 S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
1186 return false;
1187 }
1188
1189 if ((Status != APFloat::opOK) &&
1190 (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic ||
1192 FPO.getAllowFEnvAccess())) {
1193 const SourceInfo &E = S.Current->getSource(OpPC);
1194 S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
1195 return false;
1196 }
1197
1198 if ((Status & APFloat::opStatus::opInvalidOp) &&
1200 const SourceInfo &E = S.Current->getSource(OpPC);
1201 // There is no usefully definable result.
1202 S.FFDiag(E);
1203 return false;
1204 }
1205
1206 return true;
1207}
1208
1210 APFloat::opStatus Status, FPOptions FPO) {
1211 // FIXME: The standard quote below is deleted by P3899R3.
1212 // [expr.pre]p4:
1213 // If during the evaluation of an expression, the result is not
1214 // mathematically defined [...], the behavior is undefined.
1215 // FIXME: C++ rules require us to not conform to IEEE 754 here.
1216 // FIXME: The NaN check should not be applied outside of "constant contexts"
1217 // because it prevents NaN propagation and the "invalid" status is the
1218 // responsibility of CheckFloatStatus.
1219 if (Result.isNan()) {
1220 const SourceInfo &E = S.Current->getSource(OpPC);
1221 S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
1222 << /*NaN=*/true << S.Current->getRange(OpPC);
1223 return S.noteUndefinedBehavior();
1224 }
1225
1226 return CheckFloatStatus(S, OpPC, Status, FPO);
1227}
1228
1230 if (S.getLangOpts().CPlusPlus20)
1231 return true;
1232
1233 const SourceInfo &E = S.Current->getSource(OpPC);
1234 S.CCEDiag(E, diag::note_constexpr_new);
1235 return true;
1236}
1237
1239 DynamicAllocator::Form AllocForm,
1240 DynamicAllocator::Form DeleteForm, const Descriptor *D,
1241 const Expr *NewExpr) {
1242 if (AllocForm == DeleteForm)
1243 return true;
1244
1245 QualType TypeToDiagnose = D->getDataType(S.getASTContext());
1246
1247 const SourceInfo &E = S.Current->getSource(OpPC);
1248 S.FFDiag(E, diag::note_constexpr_new_delete_mismatch)
1249 << static_cast<int>(DeleteForm) << static_cast<int>(AllocForm)
1250 << TypeToDiagnose;
1251 S.Note(NewExpr->getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
1252 << NewExpr->getSourceRange();
1253 return false;
1254}
1255
1256bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source,
1257 const Pointer &Ptr) {
1258 // Regular new type(...) call.
1259 if (isa_and_nonnull<CXXNewExpr>(Source))
1260 return true;
1261 // operator new.
1262 if (const auto *CE = dyn_cast_if_present<CallExpr>(Source);
1263 CE && CE->getBuiltinCallee() == Builtin::BI__builtin_operator_new)
1264 return true;
1265 // std::allocator.allocate() call
1266 if (const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(Source);
1267 MCE && MCE->getMethodDecl()->getIdentifier()->isStr("allocate"))
1268 return true;
1269
1270 // Whatever this is, we didn't heap allocate it.
1271 const SourceInfo &Loc = S.Current->getSource(OpPC);
1272 S.FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
1273 << Ptr.toDiagnosticString(S.getASTContext());
1274 noteValueLocation(S, Ptr.block());
1275 return false;
1276}
1277
1278/// We aleady know the given DeclRefExpr is invalid for some reason,
1279/// now figure out why and print appropriate diagnostics.
1280bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
1281 const ValueDecl *D = DR->getDecl();
1282 return diagnoseUnknownDecl(S, OpPC, D);
1283}
1284
1286 bool InitializerFailed) {
1287 assert(DR);
1288
1289 if (InitializerFailed) {
1290 const SourceInfo &Loc = S.Current->getSource(OpPC);
1291 const auto *VD = cast<VarDecl>(DR->getDecl());
1292 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
1293 S.Note(VD->getLocation(), diag::note_declared_at);
1294 return false;
1295 }
1296
1297 return CheckDeclRef(S, OpPC, DR);
1298}
1299
1300bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK) {
1301 if (!B->isDummy())
1302 return true;
1303
1304 const ValueDecl *D = B->getDescriptor()->asValueDecl();
1305 if (!D)
1306 return false;
1307
1308 if (AK == AK_Read || AK == AK_Increment || AK == AK_Decrement)
1309 return diagnoseUnknownDecl(S, OpPC, D, AK);
1310
1311 if (AK == AK_Destroy || S.getLangOpts().CPlusPlus14) {
1312 const SourceInfo &E = S.Current->getSource(OpPC);
1313 S.FFDiag(E, diag::note_constexpr_modify_global);
1314 }
1315 return false;
1316}
1317
1318static bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F,
1319 const CallExpr *CE, unsigned ArgSize) {
1320 auto Args = ArrayRef(CE->getArgs(), CE->getNumArgs());
1321 auto NonNullArgs = collectNonNullArgs(F->getDecl(), Args);
1322 unsigned Offset = 0;
1323 unsigned Index = 0;
1324 for (const Expr *Arg : Args) {
1325 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
1326 const Pointer &ArgPtr = S.Stk.peek<Pointer>(ArgSize - Offset);
1327 if (ArgPtr.isZero()) {
1328 const SourceLocation &Loc = S.Current->getLocation(OpPC);
1329 S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
1330 return false;
1331 }
1332 }
1333
1334 Offset += align(primSize(S.Ctx.classify(Arg).value_or(PT_Ptr)));
1335 ++Index;
1336 }
1337 return true;
1338}
1339
1341 const Pointer &BasePtr,
1342 const Descriptor *Desc) {
1343 assert(Desc->isRecord());
1344 const Record *R = Desc->ElemRecord;
1345 assert(R);
1346
1347 if (!S.Current->isBottomFrame() && S.Current->hasThisPointer() &&
1349 Pointer::pointToSameBlock(BasePtr, S.Current->getThis())) {
1350 const SourceInfo &Loc = S.Current->getSource(OpPC);
1351 S.FFDiag(Loc, diag::note_constexpr_double_destroy);
1352 return false;
1353 }
1354
1355 // Destructor of this record.
1356 const CXXDestructorDecl *Dtor = R->getDestructor();
1357 assert(Dtor);
1358 assert(!Dtor->isTrivial());
1359 const Function *DtorFunc = S.getContext().getOrCreateFunction(Dtor);
1360 if (!DtorFunc)
1361 return false;
1362
1363 S.Stk.push<Pointer>(BasePtr);
1364 return Call(S, OpPC, DtorFunc, 0);
1365}
1366
1367static bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B) {
1368 assert(B);
1369 const Descriptor *Desc = B->getDescriptor();
1370
1371 if (Desc->isPrimitive() || Desc->isPrimitiveArray())
1372 return true;
1373
1374 assert(Desc->isRecord() || Desc->isCompositeArray());
1375
1376 if (Desc->hasTrivialDtor())
1377 return true;
1378
1379 if (Desc->isCompositeArray()) {
1380 unsigned N = Desc->getNumElems();
1381 if (N == 0)
1382 return true;
1383 const Descriptor *ElemDesc = Desc->ElemDesc;
1384 assert(ElemDesc->isRecord());
1385
1386 Pointer RP(const_cast<Block *>(B));
1387 for (int I = static_cast<int>(N) - 1; I >= 0; --I) {
1388 if (!runRecordDestructor(S, OpPC, RP.atIndex(I).narrow(), ElemDesc))
1389 return false;
1390 }
1391 return true;
1392 }
1393
1394 assert(Desc->isRecord());
1395 return runRecordDestructor(S, OpPC, Pointer(const_cast<Block *>(B)), Desc);
1396}
1397
1399 if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
1400 if (const CXXDestructorDecl *DD = RD->getDestructor())
1401 return DD->isVirtual();
1402 return false;
1403}
1404
1405bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
1406 bool IsGlobalDelete) {
1407 if (!CheckDynamicMemoryAllocation(S, OpPC))
1408 return false;
1409
1410 DynamicAllocator &Allocator = S.getAllocator();
1411
1412 const Expr *Source = nullptr;
1413 const Block *BlockToDelete = nullptr;
1414 {
1415 // Extra scope for this so the block doesn't have this pointer
1416 // pointing to it when we destroy it.
1417 Pointer Ptr = S.Stk.pop<Pointer>();
1418
1419 // Deleteing nullptr is always fine.
1420 if (Ptr.isZero())
1421 return true;
1422
1423 if (!Ptr.isBlockPointer())
1424 return false;
1425
1426 // Remove base casts.
1427 QualType InitialType = Ptr.getType();
1428 Ptr = Ptr.expand().stripBaseCasts();
1429
1430 Source = Ptr.getRootExpr();
1431 BlockToDelete = Ptr.block();
1432
1433 // Check that new[]/delete[] or new/delete were used, not a mixture.
1434 const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
1435 if (std::optional<DynamicAllocator::Form> AllocForm =
1436 Allocator.getAllocationForm(Source)) {
1437 DynamicAllocator::Form DeleteForm =
1438 DeleteIsArrayForm ? DynamicAllocator::Form::Array
1440 if (!CheckNewDeleteForms(S, OpPC, *AllocForm, DeleteForm, BlockDesc,
1441 Source))
1442 return false;
1443 }
1444
1445 // For the non-array case, the types must match if the static type
1446 // does not have a virtual destructor.
1447 if (!DeleteIsArrayForm && Ptr.getType() != InitialType &&
1448 !hasVirtualDestructor(InitialType)) {
1449 S.FFDiag(S.Current->getSource(OpPC),
1450 diag::note_constexpr_delete_base_nonvirt_dtor)
1451 << InitialType << Ptr.getType();
1452 return false;
1453 }
1454
1455 if (!Ptr.isRoot() || (Ptr.isOnePastEnd() && !Ptr.isZeroSizeArray()) ||
1456 (Ptr.isArrayElement() && Ptr.getIndex() != 0)) {
1457 const SourceInfo &Loc = S.Current->getSource(OpPC);
1458 S.FFDiag(Loc, diag::note_constexpr_delete_subobject)
1459 << Ptr.toDiagnosticString(S.getASTContext()) << Ptr.isOnePastEnd();
1460 return false;
1461 }
1462
1463 if (!CheckDeleteSource(S, OpPC, Source, Ptr))
1464 return false;
1465
1466 // For a class type with a virtual destructor, the selected operator delete
1467 // is the one looked up when building the destructor.
1468 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1469 QualType AllocType = Ptr.getType();
1470 auto getVirtualOperatorDelete = [](QualType T) -> const FunctionDecl * {
1471 if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
1472 if (const CXXDestructorDecl *DD = RD->getDestructor())
1473 return DD->isVirtual() ? DD->getOperatorDelete() : nullptr;
1474 return nullptr;
1475 };
1476
1477 if (const FunctionDecl *VirtualDelete =
1478 getVirtualOperatorDelete(AllocType);
1479 VirtualDelete &&
1480 !VirtualDelete
1482 S.FFDiag(S.Current->getSource(OpPC),
1483 diag::note_constexpr_new_non_replaceable)
1484 << isa<CXXMethodDecl>(VirtualDelete) << VirtualDelete;
1485 return false;
1486 }
1487 }
1488 }
1489 assert(Source);
1490 assert(BlockToDelete);
1491
1492 // Invoke destructors before deallocating the memory.
1493 if (!RunDestructors(S, OpPC, BlockToDelete))
1494 return false;
1495
1496 if (!Allocator.deallocate(Source, BlockToDelete)) {
1497 // Nothing has been deallocated, this must be a double-delete.
1498 const SourceInfo &Loc = S.Current->getSource(OpPC);
1499 S.FFDiag(Loc, diag::note_constexpr_double_delete);
1500 return false;
1501 }
1502
1503 return true;
1504}
1505
1507 const APSInt &Value) {
1508 llvm::APInt Min;
1509 llvm::APInt Max;
1510 ED->getValueRange(Max, Min);
1511 --Max;
1512
1513 if (ED->getNumNegativeBits() &&
1514 (Max.slt(Value.getSExtValue()) || Min.sgt(Value.getSExtValue()))) {
1515 const SourceLocation &Loc = S.Current->getLocation(OpPC);
1516 S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1517 << llvm::toString(Value, 10) << Min.getSExtValue() << Max.getSExtValue()
1518 << ED;
1519 } else if (!ED->getNumNegativeBits() && Max.ult(Value.getZExtValue())) {
1520 const SourceLocation &Loc = S.Current->getLocation(OpPC);
1521 S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1522 << llvm::toString(Value, 10) << Min.getZExtValue() << Max.getZExtValue()
1523 << ED;
1524 }
1525}
1526
1528 assert(T);
1529 assert(!S.getLangOpts().CPlusPlus23);
1530
1531 // C++1y: A constant initializer for an object o [...] may also invoke
1532 // constexpr constructors for o and its subobjects even if those objects
1533 // are of non-literal class types.
1534 //
1535 // C++11 missed this detail for aggregates, so classes like this:
1536 // struct foo_t { union { int i; volatile int j; } u; };
1537 // are not (obviously) initializable like so:
1538 // __attribute__((__require_constant_initialization__))
1539 // static const foo_t x = {{0}};
1540 // because "i" is a subobject with non-literal initialization (due to the
1541 // volatile member of the union). See:
1542 // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677
1543 // Therefore, we use the C++1y behavior.
1544
1545 if (!S.Current->isBottomFrame() &&
1548 return true;
1549 }
1550
1551 const Expr *E = S.Current->getExpr(OpPC);
1552 if (S.getLangOpts().CPlusPlus11)
1553 S.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType();
1554 else
1555 S.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
1556 return false;
1557}
1558
1560 const Pointer &Ptr, unsigned Offset) {
1561 assert(Ptr.isTypeidPointer());
1562 const Record *R = S.getContext().getRecord(
1563 Ptr.asTypeidPointer().TypeInfoType->getAsRecordDecl());
1564 if (!R)
1565 return false;
1566 const Record::Field *Field = R->findField(Offset);
1567 if (!Field)
1568 return false;
1569
1570 std::string TypeIdStr;
1571 llvm::raw_string_ostream SS(TypeIdStr);
1572 SS << "typeid(";
1573 QualType(Ptr.asTypeidPointer().TypePtr, 0)
1575 SS << ").";
1576 SS << Field->Decl->getNameAsString();
1577
1578 S.FFDiag(S.Current->getSource(OpPC),
1579 diag::note_constexpr_access_unreadable_object)
1580 << AK_Read << TypeIdStr;
1581 return false;
1582}
1583
1584static bool allowNullSubObj(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
1585 return Ptr.isZero() && S.emitRelaxedDiag(S.Current->getSource(OpPC).getLoc(),
1586 diag::note_constexpr_null_subobject);
1587}
1588
1589static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
1590 uint32_t Off) {
1591 if (S.getLangOpts().CPlusPlus && S.inConstantContext() &&
1592 !allowNullSubObj(S, OpPC, Ptr) && !CheckNull(S, OpPC, Ptr, CSK_Field))
1593 return false;
1594
1595 if (!CheckRange(S, OpPC, Ptr, CSK_Field))
1596 return false;
1597 if (!CheckArray(S, OpPC, Ptr))
1598 return false;
1599 if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
1600 return false;
1601
1602 if (Ptr.isIntegralPointer()) {
1603 if (std::optional<IntPointer> IntPtr =
1604 Ptr.asIntPointer().atOffset(S.Ctx, Off)) {
1605 S.Stk.push<Pointer>(std::move(*IntPtr));
1606 return true;
1607 }
1608 return false;
1609 }
1610
1611 if (Ptr.isOpaquePointer()) {
1612 const OpaquePointer &OP = Ptr.asOpaquePointer();
1613 const RecordDecl *RD = OP.getFieldType()->getAsRecordDecl();
1614 if (!RD)
1615 return false;
1616 const Record *R = S.getContext().getRecord(RD);
1617 if (!R)
1618 return false;
1619
1620 const Record::Field *F = R->findField(Off);
1621 if (!F)
1622 return false;
1623
1625 OP.PathLength + 1, OP.Path, PointerPathEntry::field(F->Decl));
1626
1627 S.Stk.push<Pointer>(OP.withPath(NewPath, OP.PathLength + 1,
1628 F->Decl->getType().getTypePtr()),
1629 Ptr.getByteOffset());
1630
1631 return true;
1632 }
1633
1634 if (!Ptr.isBlockPointer()) {
1635 // If we're trying to get the field of a TypeId pointer, try to produce a
1636 // proper diagnostic.
1637 if (Ptr.isTypeidPointer())
1638 return diagnoseTypeIdField(S, OpPC, Ptr, Off);
1639 return false;
1640 }
1641
1642 // We can't get the field of something that's not a record.
1643 if (!Ptr.getFieldDesc()->isRecord())
1644 return false;
1645
1646 if ((Ptr.getByteOffset() + Off) >= Ptr.block()->getSize())
1647 return false;
1648
1649 S.Stk.push<Pointer>(Ptr.atField(Off));
1650 return true;
1651}
1652
1653bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1654 const auto &Ptr = S.Stk.peek<Pointer>();
1655 return getField(S, OpPC, Ptr, Off);
1656}
1657
1658bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
1659 const auto &Ptr = S.Stk.pop<Pointer>();
1660 return getField(S, OpPC, Ptr, Off);
1661}
1662
1663static bool getBase(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
1664 uint32_t Off, bool NullOK) {
1665 if (!NullOK && !CheckNull(S, OpPC, Ptr, CSK_Base))
1666 return false;
1667
1668 if (Ptr.isOpaquePointer()) {
1669 const OpaquePointer &OP = Ptr.asOpaquePointer();
1670 const RecordDecl *RD = OP.getFieldType()->getAsRecordDecl();
1671 if (!RD)
1672 return false;
1673 const Record *R = S.getContext().getRecord(RD);
1674 assert(R);
1675
1676 const Record::Base *B = R->findBase(Off);
1677 if (!B)
1678 return false;
1679
1681 OP.PathLength + 1, OP.Path,
1683 S.Stk.push<Pointer>(
1684 OP.withPath(
1685 NewPath, OP.PathLength + 1,
1687 Ptr.getByteOffset());
1688 return true;
1689 }
1690
1691 if (!Ptr.isBlockPointer()) {
1692 if (!Ptr.isIntegralPointer())
1693 return false;
1694 S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.Ctx, Off));
1695 return true;
1696 }
1697
1698 if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
1699 return false;
1700
1701 // In case this isn't something we can get the base of at all,
1702 // just return the pointer itself so it can be diagnosed later.
1703 if (!Ptr.getFieldDesc()->isRecord()) {
1704 S.Stk.push<Pointer>(Ptr);
1705 return true;
1706 }
1707
1708 const Pointer &Result = Ptr.atField(Off);
1709 if (Result.isPastEnd() || !Result.isBaseClass())
1710 return false;
1711 S.Stk.push<Pointer>(Result);
1712 return true;
1713}
1714
1715bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
1716 const auto &Ptr = S.Stk.peek<Pointer>();
1717 return getBase(S, OpPC, Ptr.narrow(), Off, /*NullOK=*/true);
1718}
1719bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK) {
1720 const auto &Ptr = S.Stk.pop<Pointer>();
1721 return getBase(S, OpPC, Ptr.narrow(), Off, NullOK);
1722}
1723
1724bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK,
1725 const Type *TargetType) {
1726 const Pointer &Ptr = S.Stk.pop<Pointer>().narrow();
1727 if (!NullOK && !CheckNull(S, OpPC, Ptr, CSK_Derived))
1728 return false;
1729
1730 if (!Ptr.isBlockPointer()) {
1731 // FIXME: We don't have the necessary information in integral pointers.
1732 // The Descriptor only has a record, but that does of course not include
1733 // the potential derived classes of said record.
1734 S.Stk.push<Pointer>(Ptr);
1735 return true;
1736 }
1737
1738 if (!Ptr.getFieldDesc()->isRecord()) {
1739 S.Stk.push<Pointer>(Ptr);
1740 return true;
1741 }
1742
1743 if (!CheckSubobject(S, OpPC, Ptr, CSK_Derived))
1744 return false;
1745 if (!CheckDowncast(S, OpPC, Ptr, Off))
1746 return false;
1747
1748 const Record *TargetRecord = Ptr.atFieldSub(Off).getRecord();
1749 assert(TargetRecord);
1750
1751 if (TargetRecord->getDecl()->getCanonicalDecl() !=
1752 TargetType->getAsCXXRecordDecl()->getCanonicalDecl()) {
1753 QualType MostDerivedType = Ptr.getDeclDesc()->getType();
1754 S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_downcast)
1755 << MostDerivedType << QualType(TargetType, 0);
1756 return false;
1757 }
1758
1759 S.Stk.push<Pointer>(Ptr.atFieldSub(Off));
1760 return true;
1761}
1762
1763static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
1764 const Pointer &ThisPtr) {
1765 assert(Func->isConstructor());
1766
1767 if (Func->getParentDecl()->isInvalidDecl())
1768 return false;
1769
1770 const Descriptor *D = ThisPtr.getFieldDesc();
1771 // FIXME: I think this case is not 100% correct. E.g. a pointer into a
1772 // subobject of a composite array.
1773 if (!D->ElemRecord)
1774 return true;
1775
1776 if (S.getLangOpts().CPlusPlus26)
1777 return true;
1778
1779 if (D->ElemRecord->getNumVirtualBases() == 0)
1780 return true;
1781
1782 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_virtual_base)
1783 << Func->getParentDecl();
1784 return false;
1785}
1786
1788 const Pointer &Ptr) {
1789 assert(Ptr.getLifetime() != Lifetime::Started);
1790 // Try to use the declaration for better diagnostics
1791 if (const Decl *D = Ptr.getDeclDesc()->asDecl()) {
1792 auto *ND = cast<NamedDecl>(D);
1793 S.FFDiag(ND->getLocation(), diag::note_constexpr_destroy_out_of_lifetime)
1794 << ND->getNameAsString();
1795 } else {
1796 S.FFDiag(Ptr.getDeclDesc()->getLocation(),
1797 diag::note_constexpr_destroy_out_of_lifetime)
1798 << Ptr.toDiagnosticString(S.getASTContext());
1799 }
1800 return false;
1801}
1802
1803bool checkDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
1804 if (!CheckLive(S, OpPC, Ptr, AK_Destroy))
1805 return false;
1806 if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Destroy))
1807 return false;
1808 if (!CheckRange(S, OpPC, Ptr, AK_Destroy))
1809 return false;
1810
1811 if (Ptr.getLifetime() == Lifetime::Destroyed)
1812 return diagnoseOutOfLifetimeDestroy(S, OpPC, Ptr);
1813 if (Ptr.getLifetime() == Lifetime::Ended)
1814 return CheckLifetime(S, OpPC, Ptr, AK_Destroy);
1815
1816 // We _can_ call the destructor on the global variable we're checking constant
1817 // destruction for.
1818 if (S.checkingConstantDestruction(Ptr))
1819 return true;
1820
1821 // Can't call a dtor on a global variable.
1822 if (Ptr.block()->isStatic()) {
1823 const SourceInfo &E = S.Current->getSource(OpPC);
1824 S.FFDiag(E, diag::note_constexpr_modify_global);
1825 return false;
1826 }
1827 return CheckActive(S, OpPC, Ptr, AK_Destroy);
1828}
1829
1830/// Opcode. Check if the function decl can be called at compile time.
1833 return false;
1834
1835 const FunctionDecl *Definition = nullptr;
1836 bool HasBody = FD->hasBody(Definition);
1837
1838 if (Definition && HasBody &&
1839 (Definition->isConstexpr() || (S.Current->MSVCConstexprAllowed &&
1840 Definition->hasAttr<MSConstexprAttr>())))
1841 return true;
1842
1843 return diagnoseCallableDecl(S, OpPC, FD);
1844}
1845
1846bool CheckBitCast(InterpState &S, CodePtr OpPC, const Type *TargetType,
1847 bool SrcIsVoidPtr) {
1848 const auto &Ptr = S.Stk.peek<Pointer>();
1849 if (Ptr.isZero())
1850 return true;
1851 if (!Ptr.isBlockPointer())
1852 return true;
1853
1854 if (TargetType->isIntegerType())
1855 return true;
1856
1857 if (SrcIsVoidPtr && S.getLangOpts().CPlusPlus) {
1858 bool HasValidResult = !Ptr.isZero();
1859
1860 if (HasValidResult) {
1861 if (S.getStdAllocatorCaller("allocate"))
1862 return true;
1863
1864 const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
1865 if (S.getLangOpts().CPlusPlus26 &&
1866 S.getASTContext().hasSimilarType(Ptr.getType(),
1867 QualType(TargetType, 0)))
1868 return true;
1869
1870 S.CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
1871 << E->getSubExpr()->getType() << S.getLangOpts().CPlusPlus26
1872 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
1873 } else if (!S.getLangOpts().CPlusPlus26) {
1874 const SourceInfo &E = S.Current->getSource(OpPC);
1875 S.CCEDiag(E, diag::note_constexpr_invalid_cast)
1876 << diag::ConstexprInvalidCastKind::CastFrom << "'void *'"
1877 << S.Current->getRange(OpPC);
1878 }
1879 }
1880
1881 QualType PtrType = Ptr.getType();
1882 if (PtrType->isRecordType() &&
1883 PtrType->getAsRecordDecl() != TargetType->getAsRecordDecl()) {
1884 S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast)
1885 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
1886 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
1887 }
1888 return true;
1889}
1890
1891static void compileFunction(InterpState &S, const Function *Func) {
1892 const FunctionDecl *Definition;
1893 if (!Func->getDecl()->hasBody(Definition))
1894 return;
1895 if (!Definition)
1896 return;
1897
1899 .compileFunc(Definition, const_cast<Function *>(Func));
1900}
1901
1903 uint32_t VarArgSize) {
1904 if (Func->hasThisPointer()) {
1905 size_t ArgSize = Func->getArgSize() + VarArgSize;
1906 size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1907 const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1908
1909 // If the current function is a lambda static invoker and
1910 // the function we're about to call is a lambda call operator,
1911 // skip the CheckInvoke, since the ThisPtr is a null pointer
1912 // anyway.
1913 if (!(S.Current->getFunction() &&
1915 Func->isLambdaCallOperator())) {
1916 if (!CheckInvoke(S, OpPC, ThisPtr, Func->isConstructor(),
1917 Func->isDestructor()))
1918 return false;
1919 }
1920
1922 return false;
1923 }
1924
1925 if (!Func->isFullyCompiled())
1927
1928 if (!CheckCallable(S, OpPC, Func))
1929 return false;
1930
1931 if (!CheckCallDepth(S, OpPC))
1932 return false;
1933
1934 auto *Memory = new char[InterpFrame::allocSize(Func)];
1935 auto *NewFrame = new (Memory) InterpFrame(S, Func, S.PC, VarArgSize);
1936 InterpFrame *FrameBefore = S.Current;
1937 S.Current = NewFrame;
1938
1939 InterpStateCCOverride CCOverride(S, Func->isImmediate());
1940 if (Interpret(S)) {
1941 assert(S.Current == FrameBefore);
1942 return true;
1943 }
1944
1945 InterpFrame::free(NewFrame);
1946 // Interpreting the function failed somehow. Reset to
1947 // previous state.
1948 S.Current = FrameBefore;
1949 return false;
1950}
1951
1952bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
1953 uint32_t VarArgSize) {
1954
1955 // C doesn't have constexpr functions.
1956 if (!S.getLangOpts().CPlusPlus)
1957 return Invalid(S, OpPC);
1958
1959 assert(Func);
1960 auto cleanup = [&]() -> bool {
1962 return false;
1963 };
1964
1965 bool InstancePtrTracked = false;
1966 if (Func->hasThisPointer()) {
1967 size_t ArgSize = Func->getArgSize() + VarArgSize;
1968 size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1969
1970 const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1971
1972 // C++23 [expr.const]p5.6
1973 // an invocation of a virtual function ([class.virtual]) for an object whose
1974 // dynamic type is constexpr-unknown;
1975 if (ThisPtr.isDummy() && Func->isVirtual())
1976 return false;
1977
1978 // If the current function is a lambda static invoker and
1979 // the function we're about to call is a lambda call operator,
1980 // skip the CheckInvoke, since the ThisPtr is a null pointer
1981 // anyway.
1982 if (S.Current->getFunction() &&
1984 Func->isLambdaCallOperator()) {
1985 assert(ThisPtr.isZero());
1986 } else {
1987 if (!CheckInvoke(S, OpPC, ThisPtr, Func->isConstructor(),
1988 Func->isDestructor()))
1989 return cleanup();
1990
1991 if (Func->isCopyOrMoveOperator() || Func->isCopyOrMoveConstructor()) {
1992 const Pointer &RVOPtr =
1993 S.Stk.peek<Pointer>(ThisOffset - align(sizeof(Pointer)));
1994 if (!CheckInvoke(S, OpPC, RVOPtr, /*IsCtor=*/true, /*IsDtor=*/false))
1995 return cleanup();
1996 }
1997
1998 if (!Func->isConstructor() && !Func->isDestructor() &&
1999 !CheckActive(S, OpPC, ThisPtr, AK_MemberCall))
2000 return false;
2001 }
2002
2003 if (Func->isConstructor() && !checkConstructor(S, OpPC, Func, ThisPtr))
2004 return false;
2005 if (Func->isDestructor() && !checkDestructor(S, OpPC, ThisPtr))
2006 return false;
2007
2008 InstancePtrTracked = (Func->isConstructor() || Func->isDestructor());
2009 if (InstancePtrTracked)
2010 S.InitializingPtrs.push_back(ThisPtr.view());
2011 }
2012
2013 if (!Func->isFullyCompiled())
2015
2016 if (!CheckCallable(S, OpPC, Func))
2017 return cleanup();
2018
2019 // Do not evaluate any function calls in checkingPotentialConstantExpression
2020 // mode. Constructors will be aborted later when their initializers are
2021 // evaluated.
2022 if (S.checkingPotentialConstantExpression() && !Func->isConstructor())
2023 return false;
2024
2025 if (!CheckCallDepth(S, OpPC))
2026 return cleanup();
2027
2028 auto *Memory = new char[InterpFrame::allocSize(Func)];
2029 auto *NewFrame = new (Memory) InterpFrame(S, Func, S.PC, VarArgSize);
2030 InterpFrame *FrameBefore = S.Current;
2031 S.Current = NewFrame;
2032
2033 InterpStateCCOverride CCOverride(S, Func->isImmediate());
2034 bool Success = Interpret(S);
2035 // Remove initializing block again.
2036 if (InstancePtrTracked)
2037 S.InitializingPtrs.pop_back();
2038
2039 if (!Success) {
2040 InterpFrame::free(NewFrame);
2041 // Interpreting the function failed somehow. Reset to
2042 // previous state.
2043 S.Current = FrameBefore;
2044 return false;
2045 }
2046
2047 assert(S.Current == FrameBefore);
2048 return true;
2049}
2050
2051static bool getDynamicDecl(InterpState &S, CodePtr OpPC, PtrView TypePtr,
2052 const CXXRecordDecl *&DynamicDecl) {
2053
2054 if (S.InitializingPtrs.empty()) {
2055 TypePtr = TypePtr.stripBaseCasts();
2056 } else {
2057 auto depth = [](PtrView V) -> unsigned {
2058 unsigned C = 1;
2059 while (!V.isRoot()) {
2060 ++C;
2061 V = V.getBase();
2062 }
2063 return C;
2064 };
2065 // Consider a 'normal' diamond hierarchy:
2066 // A A 3
2067 // | |
2068 // B C 2
2069 // \ /
2070 // \ /
2071 // D 1
2072 // When we use a pointer of D*, cast it to B's A* and
2073 // use it during the construction of C*, the expected
2074 // dynamic type is B.
2075 PtrView InitPtr = S.InitializingPtrs.back();
2076 assert(depth(TypePtr) >= depth(InitPtr));
2077 unsigned D = depth(TypePtr) - depth(InitPtr);
2078 for (unsigned I = 0; I != D; ++I)
2079 TypePtr = TypePtr.getBase();
2080 }
2081
2082 QualType DynamicType = TypePtr.getType();
2083 if (TypePtr.Pointee->isStatic() || TypePtr.isConst()) {
2084 if (const VarDecl *VD = Pointer(TypePtr).getRootVarDecl();
2085 VD && !VD->isConstexpr()) {
2086 const Expr *E = S.Current->getExpr(OpPC);
2087 APValue V = Pointer(TypePtr).toAPValue(S.getASTContext());
2089 S.FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
2090 << AK_MemberCall << V.getAsString(S.getASTContext(), TT);
2091 return false;
2092 }
2093 }
2094
2095 if (DynamicType->isPointerType() || DynamicType->isReferenceType()) {
2096 DynamicDecl = DynamicType->getPointeeCXXRecordDecl();
2097 } else if (DynamicType->isArrayType()) {
2098 const Type *ElemType = DynamicType->getPointeeOrArrayElementType();
2099 assert(ElemType);
2100 DynamicDecl = ElemType->getAsCXXRecordDecl();
2101 } else {
2102 DynamicDecl = DynamicType->getAsCXXRecordDecl();
2103 }
2104 return DynamicDecl != nullptr;
2105}
2106
2107namespace {
2108struct DynamicCastResult {
2109 UnsignedOrNone Offset = std::nullopt;
2110 bool Ambiguous = false;
2111
2112 bool valid() const { return !Ambiguous && Offset; }
2113
2114 void setOffset(unsigned O) {
2115 if (!Offset)
2116 Offset = O;
2117 else {
2118 Ambiguous = true;
2119 }
2120 }
2121
2122 void merge(DynamicCastResult C) {
2123 Ambiguous |= C.Ambiguous;
2124 if (C.Offset) {
2125 if (!Offset)
2126 Offset = C.Offset;
2127 else
2128 Ambiguous = true;
2129 }
2130 }
2131};
2132} // namespace
2133
2134// Walk UP the type hierarchy, starting at the decl of R to find Needle.
2135static DynamicCastResult findRecordBase(const ASTContext &Ctx, const Record *R,
2136 QualType Needle) {
2137 DynamicCastResult Res;
2138
2139 if (Ctx.hasSimilarType(Needle, Ctx.getCanonicalTagType(R->getDecl())))
2140 Res.setOffset(0);
2141
2142 for (const Record::Base &B : R->bases()) {
2143 auto N = findRecordBase(Ctx, B.R, Needle);
2144 if (N.Offset)
2145 N.Offset = *N.Offset + B.Offset;
2146 Res.merge(N);
2147 }
2148
2149 return Res;
2150}
2151
2152bool DynamicCast(InterpState &S, CodePtr OpPC, const Type *DestTypePtr,
2153 bool IsReferenceCast) {
2154 const auto &Ptr = S.Stk.pop<Pointer>();
2155 QualType TargetType = QualType(DestTypePtr, 0);
2156
2157 if (Ptr.isConstexprUnknown()) {
2158 QualType T = Ptr.getType();
2159 const Expr *E = S.Current->getExpr(OpPC);
2160 APValue V = Ptr.toAPValue(S.getASTContext());
2162 S.FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
2163 << AK_DynamicCast << V.getAsString(S.getASTContext(), TT);
2164 return false;
2165 }
2166
2167 if (!Ptr.isBlockPointer() || !Ptr.getRecord())
2168 return false;
2169
2170 if (!Ptr.isInitialized())
2171 return diagnoseUninitialized(S, OpPC, Ptr, AK_Read);
2172
2173 // Our given pointer, limited by the base that's currently being initialized,
2174 // if any.
2175 PtrView LimitedPtr;
2176 if (S.InitializingPtrs.empty() ||
2177 S.InitializingPtrs.back().block() != Ptr.block()) {
2178 LimitedPtr = Ptr.stripBaseCasts().view();
2179 } else {
2180 LimitedPtr = S.InitializingPtrs.back();
2181 assert(LimitedPtr.block() == Ptr.block());
2182 }
2183 assert(LimitedPtr.getRecord());
2184
2185 // C++ [expr.dynamic.cast]p7:
2186 // If T is "pointer to cv void", then the result is a pointer to the most
2187 // derived object
2188 if (TargetType->isVoidType()) {
2189 S.Stk.push<Pointer>(LimitedPtr);
2190 return true;
2191 }
2192
2193 assert(!TargetType.isNull());
2194 assert(!TargetType->isVoidType());
2195 assert(TargetType->isRecordType());
2196
2197 // Helper lambdas.
2198 auto typesMatch = [&](QualType A, QualType B) -> bool {
2199 return S.getASTContext().hasSimilarType(A, B);
2200 };
2201 auto getRecord = [](PtrView P) -> const CXXRecordDecl * {
2202 assert(P.getRecord());
2203 return cast<CXXRecordDecl>(P.getRecord()->getDecl());
2204 };
2205
2206 auto baseIsPrivate = [&](PtrView P) -> bool {
2207 if (P.isRoot() || !P.isBaseClass())
2208 return false;
2209
2210 CXXBasePaths Paths;
2211 getRecord(P.getBase())->isDerivedFrom(getRecord(P), Paths);
2212
2213 // Through virtual bases, there might be more than one "direct" base. They
2214 // can have different access specifiers. They must all be private to be
2215 // considered private.
2216 return llvm::all_of(Paths, [](const CXXBasePath &P) -> bool {
2217 return P.Access == AS_private;
2218 });
2219 };
2220
2221 enum {
2222 DiagPrivateBase = 0,
2223 DiagNoBase = 1,
2224 DiagAmbiguous = 2,
2225 DiagPrivateSibling = 3
2226 };
2227
2228 auto diag = [&](int DiagKind, QualType ResultType) -> bool {
2229 // Pointer casts return nullptr on failure.
2230 if (!IsReferenceCast) {
2231 S.Stk.push<Pointer>(0, DestTypePtr);
2232 return true;
2233 }
2235 S.FFDiag(S.Current->getSource(OpPC),
2236 diag::note_constexpr_dynamic_cast_to_reference_failed)
2237 << DiagKind << ResultType << DynamicType << TargetType;
2238 return false;
2239 };
2240
2241 // Check if Ptr's dynamic type is derived from our target type at all.
2242 // If it isn't, diagnose this as "operand does not have base class of type
2243 // [...]".
2244 {
2245 CXXBasePaths Paths;
2246 getRecord(LimitedPtr)
2247 ->isDerivedFrom(TargetType->getAsCXXRecordDecl(), Paths);
2248 if (std::distance(Paths.begin(), Paths.end()) == 0 &&
2249 !typesMatch(LimitedPtr.getType(), TargetType)) {
2250 return diag(DiagNoBase, TargetType);
2251 }
2252 }
2253
2254 // Current base is already private.
2255 if (baseIsPrivate(Ptr.view()))
2256 return diag(DiagPrivateBase, Ptr.getType());
2257
2258 std::optional<PtrView> Result;
2259 // First, check simple downcasts without ambiguities.
2260 for (PtrView Iter = Ptr.view();;) {
2261 if (Iter.isRoot() || !Iter.isBaseClass())
2262 break;
2263
2264 if (typesMatch(TargetType, Iter.getType())) {
2265 Result = Iter;
2266 break;
2267 }
2268 // Moving DOWN the type hierarchy.
2269 Iter = Iter.getBase();
2270 }
2271
2272 // Simply walking down the type hierarchy has produced a valid result, use
2273 // that.
2274 if (Result) {
2275 if (baseIsPrivate(*Result))
2276 return diag(DiagPrivateBase, Result->getType());
2277 S.Stk.push<Pointer>(*Result);
2278 return true;
2279 }
2280
2281 // Otherwise, we need to do a deep hierarchy check.
2282 bool Ambiguous = false;
2283 for (PtrView Iter = LimitedPtr;;) {
2284 // If we can move up the hierarchy from this level and reach the target type
2285 // unambiguously, we're fine.
2286 auto R = findRecordBase(S.getASTContext(), Iter.getRecord(), TargetType);
2287
2288 if (R.valid()) {
2289 Result = Iter.atField(*R.Offset);
2290 break;
2291 }
2292 if (R.Ambiguous) {
2293 Ambiguous = true;
2294 break;
2295 }
2296
2297 if (Iter.isRoot() || !Iter.isBaseClass())
2298 break;
2299 // This moves us DOWN the type hierarchy.
2300 Iter = Iter.getBase();
2301 }
2302
2303 if (Ambiguous)
2304 return diag(DiagAmbiguous, TargetType);
2305
2306 if (Result) {
2307 // Might still be invalid due to resulting in a private base though.
2308 if (baseIsPrivate(*Result))
2309 return diag(DiagPrivateSibling, TargetType);
2310 S.Stk.push<Pointer>(*Result);
2311 return true;
2312 }
2313
2314 // We couldn't find the requested base.
2315 return diag(DiagNoBase, TargetType);
2316}
2317
2319 uint32_t VarArgSize) {
2320 assert(Func->hasThisPointer());
2321 assert(Func->isVirtual());
2322 size_t ArgSize = Func->getArgSize() + VarArgSize;
2323 size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
2324 Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
2325
2326 if (!ThisPtr.isBlockPointer())
2327 return false;
2328
2329 const FunctionDecl *Callee = Func->getDecl();
2330
2331 const CXXRecordDecl *DynamicDecl = nullptr;
2332 if (!getDynamicDecl(S, OpPC, ThisPtr.view(), DynamicDecl))
2333 return false;
2334 assert(DynamicDecl);
2335
2336 const auto *StaticDecl = Func->getParentDecl();
2337 const auto *InitialFunction = cast<CXXMethodDecl>(Callee);
2338 const CXXMethodDecl *Overrider;
2339
2340 if (StaticDecl != DynamicDecl) {
2341 if (!DynamicDecl->isDerivedFrom(StaticDecl))
2342 return false;
2343 Overrider = S.getContext().getOverridingFunction(DynamicDecl, StaticDecl,
2344 InitialFunction);
2345
2346 } else {
2347 Overrider = InitialFunction;
2348 }
2349
2350 // C++2a [class.abstract]p6:
2351 // the effect of making a virtual call to a pure virtual function [...] is
2352 // undefined
2353 if (Overrider->isPureVirtual()) {
2354 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_pure_virtual_call,
2355 1)
2356 << Callee;
2357 S.Note(Callee->getLocation(), diag::note_declared_at);
2358 return false;
2359 }
2360
2361 if (Overrider != InitialFunction) {
2362 // DR1872: An instantiated virtual constexpr function can't be called in a
2363 // constant expression (prior to C++20). We can still constant-fold such a
2364 // call.
2365 if (!S.getLangOpts().CPlusPlus20 && Overrider->isVirtual()) {
2366 const Expr *E = S.Current->getExpr(OpPC);
2367 S.CCEDiag(E, diag::note_constexpr_virtual_call) << E->getSourceRange();
2368 }
2369
2370 Func = S.getContext().getOrCreateFunction(Overrider);
2371
2372 const CXXRecordDecl *ThisFieldDecl =
2373 ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
2374 if (Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
2375 // If the function we call is further DOWN the hierarchy than the
2376 // FieldDesc of our pointer, just go up the hierarchy of this field
2377 // the furthest we can go.
2378 ThisPtr = ThisPtr.stripBaseCasts();
2379 }
2380 }
2381
2382 if (!Call(S, OpPC, Func, VarArgSize))
2383 return false;
2384
2385 // Covariant return types. The return type of Overrider is a pointer
2386 // or reference to a class type.
2387 if (Overrider != InitialFunction &&
2388 Overrider->getReturnType()->isPointerOrReferenceType() &&
2389 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
2390 QualType OverriderPointeeType =
2391 Overrider->getReturnType()->getPointeeType();
2392 QualType InitialPointeeType =
2393 InitialFunction->getReturnType()->getPointeeType();
2394
2395 // Nothing to do if the types already match.
2396 if (S.getASTContext().hasSimilarType(InitialPointeeType,
2397 OverriderPointeeType))
2398 return true;
2399
2400 // We've called Overrider above, but calling code expects us to return what
2401 // InitialFunction returned. According to the rules for covariant return
2402 // types, what InitialFunction returns needs to be a base class of what
2403 // Overrider returns. So, we need to do an upcast here.
2404 unsigned Offset = S.getContext().collectBaseOffset(
2405 InitialPointeeType->getAsRecordDecl(),
2406 OverriderPointeeType->getAsRecordDecl());
2407 return GetPtrBasePop(S, OpPC, Offset, /*IsNullOK=*/true);
2408 }
2409
2410 return true;
2411}
2412
2413bool CallBI(InterpState &S, CodePtr OpPC, const CallExpr *CE,
2414 uint32_t BuiltinID) {
2415 // A little arbitrary, but the current interpreter allows evaluation
2416 // of builtin functions in this mode, with some exceptions.
2417 if (BuiltinID == Builtin::BI__builtin_operator_new &&
2419 return false;
2420
2421 return InterpretBuiltin(S, OpPC, CE, BuiltinID);
2422}
2423
2424bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
2425 const CallExpr *CE) {
2426 const Pointer &Ptr = S.Stk.pop<Pointer>();
2427
2428 if (Ptr.isZero()) {
2429 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_null_callee)
2430 << const_cast<Expr *>(CE->getCallee()) << CE->getSourceRange();
2431 return false;
2432 }
2433
2434 if (!Ptr.isFunctionPointer())
2435 return Invalid(S, OpPC);
2436
2437 const Function *F = Ptr.asFunctionPointer().Func;
2438 assert(F);
2439 // Don't allow calling block pointers.
2440 if (!F->getDecl())
2441 return Invalid(S, OpPC);
2442
2443 // This happens when the call expression has been cast to
2444 // something else, but we don't support that.
2445 if (S.Ctx.classify(F->getDecl()->getReturnType()) !=
2447 return false;
2448
2449 // Check argument nullability state.
2450 if (F->hasNonNullAttr()) {
2451 if (!CheckNonNullArgs(S, OpPC, F, CE, ArgSize))
2452 return false;
2453 }
2454
2455 // Can happen when casting function pointers around.
2456 QualType CalleeType = CE->getCallee()->getType();
2457 if (CalleeType->isPointerType() &&
2459 F->getDecl()->getType(), CalleeType->getPointeeType())) {
2460 return false;
2461 }
2462
2463 // We nedd to compile (and check) early for function pointer calls
2464 // because the Call/CallVirt below might access the instance pointer
2465 // but the Function's information about them is wrong.
2466 if (!F->isFullyCompiled())
2467 compileFunction(S, F);
2468
2469 if (!CheckCallable(S, OpPC, F))
2470 return false;
2471
2472 assert(ArgSize >= F->getWrittenArgSize());
2473 uint32_t VarArgSize = ArgSize - F->getWrittenArgSize();
2474
2475 // We need to do this explicitly here since we don't have the necessary
2476 // information to do it automatically.
2477 if (F->hasExplicitThisPointer())
2478 VarArgSize -= align(primSize(PT_Ptr));
2479
2480 if (F->isVirtual())
2481 return CallVirt(S, OpPC, F, VarArgSize);
2482
2483 return Call(S, OpPC, F, VarArgSize);
2484}
2485
2487 if (const Record *R = Ptr.getRecord()) {
2488 Ptr.startLifetime();
2489
2490 for (const Record::Field &Fi : R->fields()) {
2491 PtrView FP = Ptr.atField(Fi.Offset);
2492 if (FP.getLifetime() != Lifetime::Started)
2494 }
2495 return;
2496 }
2497
2498 if (const Descriptor *FieldDesc = Ptr.getFieldDesc();
2499 FieldDesc->isCompositeArray()) {
2500 for (unsigned I = 0; I != FieldDesc->getNumElems(); ++I) {
2501 PtrView EP = Ptr.atIndex(I).narrow();
2502 if (EP.getLifetime() != Lifetime::Started)
2504 }
2505 return;
2506 }
2507
2508 Ptr.startLifetime();
2509}
2510
2513 return true;
2514
2515 const auto &Ptr = S.Current->getThis();
2516 if (!Ptr.isBlockPointer())
2517 return false;
2518 startLifetimeRecurse(Ptr.view());
2519 return true;
2520}
2521
2524 return true;
2525
2526 const auto &Ptr = S.Current->getThis();
2527 if (!Ptr.isBlockPointer())
2528 return false;
2529 Ptr.startLifetime();
2530 return true;
2531}
2532
2533// FIXME: It might be better to the recursing as part of the generated code for
2534// a destructor?
2536 if (const Record *R = Ptr.getRecord()) {
2537 Ptr.setLifeState(L);
2538 for (const Record::Field &Fi : R->fields())
2539 setLifeStateRecurse(Ptr.atField(Fi.Offset), L);
2540 return;
2541 }
2542
2543 if (const Descriptor *FieldDesc = Ptr.getFieldDesc();
2544 FieldDesc->isCompositeArray()) {
2545 // No endLifetime() for primitive array roots.
2546 if (Ptr.getFieldDesc()->isPrimitiveArray())
2547 assert(Ptr.getLifetime() == Lifetime::Started);
2548 for (unsigned I = 0; I != FieldDesc->getNumElems(); ++I)
2549 setLifeStateRecurse(Ptr.atIndex(I).narrow(), L);
2550 return;
2551 }
2552
2553 Ptr.setLifeState(L);
2554}
2555
2556/// Ends the lifetime of the peek'd pointer.
2558 const auto &Ptr = S.Stk.peek<Pointer>();
2559 if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
2560 return false;
2561
2562 setLifeStateRecurse(Ptr.view().narrow(), Lifetime::Ended);
2563 return true;
2564}
2565
2566/// Ends the lifetime of the pop'd pointer.
2568 const auto &Ptr = S.Stk.pop<Pointer>();
2569 if (!checkDestructor(S, OpPC, Ptr))
2570 return false;
2571 setLifeStateRecurse(Ptr.view().narrow(), Lifetime::Ended);
2572 return true;
2573}
2574
2576 const auto &Ptr = S.Stk.peek<Pointer>();
2577 if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
2578 return false;
2579
2580 setLifeStateRecurse(Ptr.view().narrow(), Lifetime::Destroyed);
2581 return true;
2582}
2583
2585 std::optional<uint64_t> ArraySize) {
2586 Pointer &Orig = S.Stk.peek<Pointer>();
2587 Pointer Ptr = Orig;
2588
2589 auto directBaseIsUnion = [](const Pointer &Ptr) -> bool {
2590 if (Ptr.isArrayElement())
2591 return false;
2592 const Record *R = Ptr.getBase().getRecord();
2593 return R && R->isUnion();
2594 };
2595
2596 if (Ptr.inUnion() && directBaseIsUnion(Ptr))
2597 Ptr.activate();
2598
2599 if (Ptr.isZero()) {
2600 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)
2601 << AK_Construct;
2602 return false;
2603 }
2604
2605 if (!Ptr.isBlockPointer())
2606 return false;
2607
2608 if (!CheckRange(S, OpPC, Ptr, AK_Construct))
2609 return false;
2610
2611 startLifetimeRecurse(Ptr.view());
2612
2613 // Similar to CheckStore(), but with the additional CheckTemporary() call and
2614 // the AccessKinds are different.
2615 if (!Ptr.block()->isAccessible()) {
2616 if (!CheckExtern(S, OpPC, Ptr))
2617 return false;
2618 if (!CheckLive(S, OpPC, Ptr, AK_Construct))
2619 return false;
2620 return CheckDummy(S, OpPC, Ptr.block(), AK_Construct);
2621 }
2622 if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Construct))
2623 return false;
2624
2625 // CheckLifetime for this and all base pointers.
2626 for (PtrView P = Ptr.view();;) {
2627 if (!CheckLifetime(S, OpPC, P.getLifetime(), P.Pointee, AK_Construct))
2628 return false;
2629
2630 if (P.isRoot())
2631 break;
2632 P = P.getBase();
2633 }
2634
2635 if (!CheckRange(S, OpPC, Ptr, AK_Construct))
2636 return false;
2637 if (!CheckGlobal(S, OpPC, Ptr))
2638 return false;
2639 if (!CheckConst(S, OpPC, Ptr))
2640 return false;
2641 if (!S.inConstantContext() && isConstexprUnknown(Ptr))
2642 return false;
2643
2644 if (!InvalidNewDeleteExpr(S, OpPC, E))
2645 return false;
2646
2647 const auto *NewExpr = cast<CXXNewExpr>(E);
2648 const ASTContext &ASTCtx = S.getASTContext();
2649 QualType StorageType = Ptr.getType();
2650 QualType AllocType;
2651 if (ArraySize) {
2652 AllocType = ASTCtx.getConstantArrayType(
2653 NewExpr->getAllocatedType(),
2654 APInt(64, static_cast<uint64_t>(*ArraySize), false), nullptr,
2656 } else {
2657 AllocType = NewExpr->getAllocatedType();
2658 }
2659
2660 if (AllocType->isArrayType() && Ptr.isArrayElement() &&
2661 Ptr.expand().getIndex() == 0) {
2662 // The destination of placement new is pointing to the first element
2663 // of an array. There's a special case in [expr.const]: "[...] if T is an
2664 // array type, to the first element of such an object [...]". Handle
2665 // that case here by using the base of the Pointer.
2666 QualType AllocElementType =
2667 ASTCtx.getAsArrayType(AllocType)->getElementType();
2668 if (ASTCtx.hasSimilarType(AllocElementType, StorageType)) {
2669 StorageType = Ptr.expand().getArray().getType();
2670 Orig = Orig.expand();
2671 }
2672 }
2673
2674 if (!ASTCtx.hasSimilarType(AllocType, StorageType)) {
2675 S.FFDiag(S.Current->getLocation(OpPC),
2676 diag::note_constexpr_placement_new_wrong_type)
2677 << StorageType << AllocType;
2678 return false;
2679 }
2680
2681 // Can't activate fields in a union, unless the direct base is the union.
2682 if (Ptr.inUnion() && !Ptr.isActive() && !directBaseIsUnion(Ptr))
2683 return CheckActive(S, OpPC, Ptr, AK_Construct);
2684
2685 return true;
2686}
2687
2689 assert(E);
2690
2691 if (const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
2692 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
2693
2694 if (NewExpr->getNumPlacementArgs() > 0) {
2695 // This is allowed pre-C++26, but only an std function or if
2696 // [[msvc::constexpr]] was used.
2697 if (S.getLangOpts().CPlusPlus26 || S.Current->isStdFunction() ||
2699 return true;
2700
2701 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_placement)
2702 << /*C++26 feature*/ 1 << E->getSourceRange();
2703 } else if (
2704 !OperatorNew
2705 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
2706 S.FFDiag(S.Current->getSource(OpPC),
2707 diag::note_constexpr_new_non_replaceable)
2708 << isa<CXXMethodDecl>(OperatorNew) << OperatorNew;
2709 return false;
2710 } else if (!S.getLangOpts().CPlusPlus26 &&
2711 NewExpr->getNumPlacementArgs() == 1 &&
2712 !OperatorNew->isReservedGlobalPlacementOperator()) {
2713 if (!S.getLangOpts().CPlusPlus26) {
2714 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_placement)
2715 << /*Unsupported*/ 0 << E->getSourceRange();
2716 return false;
2717 }
2718 return true;
2719 }
2720 } else {
2721 const auto *DeleteExpr = cast<CXXDeleteExpr>(E);
2722 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
2723 if (!OperatorDelete
2724 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
2725 S.FFDiag(S.Current->getSource(OpPC),
2726 diag::note_constexpr_new_non_replaceable)
2727 << isa<CXXMethodDecl>(OperatorDelete) << OperatorDelete;
2728 return false;
2729 }
2730 }
2731
2732 return false;
2733}
2734
2736 const FixedPoint &FP) {
2737 const Expr *E = S.Current->getExpr(OpPC);
2740 E->getExprLoc(), diag::warn_fixedpoint_constant_overflow)
2741 << FP.toDiagnosticString(S.getASTContext()) << E->getType();
2742 }
2743 S.CCEDiag(E, diag::note_constexpr_overflow)
2744 << FP.toDiagnosticString(S.getASTContext()) << E->getType();
2745 return S.noteUndefinedBehavior();
2746}
2747
2748bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index) {
2749 const SourceInfo &Loc = S.Current->getSource(OpPC);
2750 S.FFDiag(Loc,
2751 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
2752 << Index;
2753 return false;
2754}
2755
2757 const Pointer &Ptr, unsigned BitWidth) {
2758 SourceInfo E = S.Current->getSource(OpPC);
2759
2760 S.CCEDiag(E, diag::note_constexpr_invalid_cast_ptrtoint)
2761 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2762 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
2763 if (Ptr.isBlockPointer() && !Ptr.isZero())
2764 S.CCEDiag(E, diag::note_constexpr_has_lvalue) << S.Current->getRange(OpPC);
2765 if (Ptr.isIntegralPointer())
2766 return true;
2767
2768 if (Ptr.isDummy()) {
2769 if (!CheckIntegralAddressCast(S, OpPC, BitWidth))
2770 return false;
2771 return Ptr.getIndex() == 0;
2772 }
2773
2774 if (!Ptr.isZero()) {
2775 // Only allow based lvalue casts if they are lossless.
2776 if (!CheckIntegralAddressCast(S, OpPC, BitWidth))
2777 return Invalid(S, OpPC);
2778 }
2779 return true;
2780}
2781
2782bool CheckIntegralAddressCast(InterpState &S, CodePtr OpPC, unsigned BitWidth) {
2784 BitWidth);
2785}
2786
2787bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
2788 const Pointer &Ptr = S.Stk.pop<Pointer>();
2789
2790 if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
2791 return false;
2792
2793 auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
2794 Result.copy(APInt(BitWidth, Ptr.getIntegerRepresentation()));
2795
2797 return true;
2798}
2799
2800bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
2801 const Pointer &Ptr = S.Stk.pop<Pointer>();
2802
2803 if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
2804 return false;
2805
2806 auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
2807 Result.copy(APInt(BitWidth, Ptr.getIntegerRepresentation()));
2808
2810 return true;
2811}
2812
2813bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits,
2814 bool TargetIsUCharOrByte) {
2815 // This is always fine.
2816 if (!HasIndeterminateBits)
2817 return true;
2818
2819 // Indeterminate bits can only be bitcast to unsigned char or std::byte.
2820 if (TargetIsUCharOrByte)
2821 return true;
2822
2823 const Expr *E = S.Current->getExpr(OpPC);
2824 QualType ExprType = E->getType();
2825 S.FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
2826 << ExprType << S.getLangOpts().CharIsSigned << E->getSourceRange();
2827 return false;
2828}
2829
2831 if (isConstexprUnknown(B)) {
2832 S.Stk.push<Pointer>(B);
2833 return true;
2834 }
2835
2836 const auto &ID = B->getBlockDesc<const InlineDescriptor>();
2837 if (!ID.IsInitialized) {
2839 S.FFDiag(S.Current->getSource(OpPC),
2840 diag::note_constexpr_use_uninit_reference);
2841 return false;
2842 }
2843
2844 assert(B->getDescriptor()->getPrimType() == PT_Ptr);
2845 S.Stk.push<Pointer>(B->deref<Pointer>());
2846 return true;
2847}
2848
2849bool GetTypeid(InterpState &S, const Type *TypePtr, const Type *TypeInfoType) {
2850 S.Stk.push<Pointer>(TypePtr, TypeInfoType);
2851 return true;
2852}
2853
2854bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType) {
2855 const auto &P = S.Stk.pop<Pointer>();
2856
2857 if (!P.isBlockPointer())
2858 return false;
2859
2860 if (P.isConstexprUnknown()) {
2861 QualType DynamicType = P.getType();
2862 const Expr *E = S.Current->getExpr(OpPC);
2863 APValue V = P.toAPValue(S.getASTContext());
2865 S.FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
2866 << AK_TypeId << V.getAsString(S.getASTContext(), TT);
2867 return false;
2868 }
2869
2870 // Pick the most-derived type.
2871 CanQualType T = P.stripBaseCasts().getType()->getCanonicalTypeUnqualified();
2872 // ... unless we're currently constructing this object.
2873 // FIXME: We have a similar check to this in more places.
2874 if (S.Current->getFunction()) {
2875 for (const InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) {
2876 if (const Function *Func = Frame->getFunction();
2877 Func && (Func->isConstructor() || Func->isDestructor()) &&
2878 P.block() == Frame->getThis().block()) {
2880 Func->getParentDecl());
2881 break;
2882 }
2883 }
2884 }
2885
2886 S.Stk.push<Pointer>(T->getTypePtr(), TypeInfoType);
2887 return true;
2888}
2889
2891 const auto *E = cast<CXXTypeidExpr>(S.Current->getExpr(OpPC));
2892 S.CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
2893 << E->getExprOperand()->getType()
2894 << E->getExprOperand()->getSourceRange();
2895 return false;
2896}
2897
2899 const Pointer &RHS) {
2900 assert(LHS.isStringPointer());
2901 assert(RHS.isStringPointer());
2902
2903 unsigned LHSOffset = LHS.isOnePastEnd() ? LHS.getNumElems() : LHS.getIndex();
2904 unsigned RHSOffset = RHS.isOnePastEnd() ? RHS.getNumElems() : RHS.getIndex();
2905 const auto *LHSLit = cast<StringLiteral>(LHS.getRootExpr());
2906 const auto *RHSLit = cast<StringLiteral>(RHS.getRootExpr());
2907
2908 StringRef LHSStr(LHSLit->getBytes());
2909 unsigned LHSLength = LHSStr.size();
2910 StringRef RHSStr(RHSLit->getBytes());
2911 unsigned RHSLength = RHSStr.size();
2912
2913 int32_t IndexDiff = RHSOffset - LHSOffset;
2914 if (IndexDiff < 0) {
2915 if (static_cast<int32_t>(LHSLength) < -IndexDiff)
2916 return false;
2917 LHSStr = LHSStr.drop_front(-IndexDiff);
2918 } else {
2919 if (static_cast<int32_t>(RHSLength) < IndexDiff)
2920 return false;
2921 RHSStr = RHSStr.drop_front(IndexDiff);
2922 }
2923
2924 unsigned ShorterCharWidth;
2925 StringRef Shorter;
2926 StringRef Longer;
2927 if (LHSLength < RHSLength) {
2928 ShorterCharWidth = LHSLit->getCharByteWidth();
2929 Shorter = LHSStr;
2930 Longer = RHSStr;
2931 } else {
2932 ShorterCharWidth = RHSLit->getCharByteWidth();
2933 Shorter = RHSStr;
2934 Longer = LHSStr;
2935 }
2936
2937 // The null terminator isn't included in the string data, so check for it
2938 // manually. If the longer string doesn't have a null terminator where the
2939 // shorter string ends, they aren't potentially overlapping.
2940 for (unsigned NullByte : llvm::seq(ShorterCharWidth)) {
2941 if (Shorter.size() + NullByte >= Longer.size())
2942 break;
2943 if (Longer[Shorter.size() + NullByte])
2944 return false;
2945 }
2946 return Shorter == Longer.take_front(Shorter.size());
2947}
2948
2950 if (T == PT_IntAPS) {
2951 auto &Val = Ptr.deref<IntegralAP<true>>();
2952 if (!Val.singleWord()) {
2953 uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
2954 Val.take(NewMemory);
2955 }
2956 } else if (T == PT_IntAP) {
2957 auto &Val = Ptr.deref<IntegralAP<false>>();
2958 if (!Val.singleWord()) {
2959 uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
2960 Val.take(NewMemory);
2961 }
2962 } else if (T == PT_Float) {
2963 auto &Val = Ptr.deref<Floating>();
2964 if (!Val.singleWord()) {
2965 uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
2966 Val.take(NewMemory);
2967 }
2968 } else if (T == PT_MemberPtr) {
2969 auto &Val = Ptr.deref<MemberPointer>();
2970 unsigned PathLength = Val.getPathLength();
2971 auto *NewPath = new (S.P) const CXXRecordDecl *[PathLength];
2972 std::copy_n(Val.path(), PathLength, NewPath);
2973 Val.takePath(NewPath);
2974 }
2975}
2976
2977template <typename T>
2979 assert(needsAlloc<T>());
2980 if constexpr (std::is_same_v<T, MemberPointer>) {
2981 auto &Val = Ptr.deref<MemberPointer>();
2982 unsigned PathLength = Val.getPathLength();
2983 auto *NewPath = new (S.P) const CXXRecordDecl *[PathLength];
2984 std::copy_n(Val.path(), PathLength, NewPath);
2985 Val.takePath(NewPath);
2986 } else {
2987 auto &Val = Ptr.deref<T>();
2988 if (!Val.singleWord()) {
2989 uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
2990 Val.take(NewMemory);
2991 }
2992 }
2993}
2994
2996 if (const Record *R = Ptr.getRecord()) {
2997 for (const Record::Field &Fi : R->fields()) {
2998 if (Fi.Desc->isPrimitive()) {
2999 TYPE_SWITCH_ALLOC(Fi.Desc->getPrimType(), {
3000 copyPrimitiveMemory<T>(S, Ptr.atField(Fi.Offset));
3001 });
3002 } else {
3003 finishGlobalRecurse(S, Ptr.atField(Fi.Offset));
3004 }
3005 }
3006 return;
3007 }
3008
3009 if (const Descriptor *D = Ptr.getFieldDesc(); D && D->isArray()) {
3010 unsigned NumElems = D->getNumElems();
3011 if (NumElems == 0)
3012 return;
3013
3014 if (D->isPrimitiveArray()) {
3015 PrimType PT = D->getPrimType();
3016 if (!needsAlloc(PT))
3017 return;
3018 assert(NumElems >= 1);
3019 PtrView EP = Ptr.atIndex(0);
3020 bool AllSingleWord = true;
3021 TYPE_SWITCH_ALLOC(PT, {
3022 if (!EP.deref<T>().singleWord()) {
3024 AllSingleWord = false;
3025 }
3026 });
3027 if (AllSingleWord)
3028 return;
3029 for (unsigned I = 1; I != D->getNumElems(); ++I) {
3030 PtrView EP = Ptr.atIndex(I);
3031 copyPrimitiveMemory(S, EP, PT);
3032 }
3033 } else {
3034 assert(D->isCompositeArray());
3035 for (unsigned I = 0; I != D->getNumElems(); ++I) {
3036 PtrView EP = Ptr.atIndex(I).narrow();
3037 finishGlobalRecurse(S, EP);
3038 }
3039 }
3040 }
3041}
3042
3044 const Pointer &Ptr = S.Stk.pop<Pointer>();
3045
3046 finishGlobalRecurse(S, Ptr.view());
3047 if (Ptr.canBeInitialized()) {
3048 Ptr.initialize();
3049 Ptr.activate();
3050 }
3051
3052 return true;
3053}
3054
3055bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, bool Fatal) {
3056 const SourceLocation &Loc = S.Current->getLocation(OpPC);
3057
3058 switch (Kind) {
3060 S.CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3061 << diag::ConstexprInvalidCastKind::Reinterpret
3062 << S.Current->getRange(OpPC);
3063 return !Fatal;
3065 // Don't emit anything as we'll emit diag
3066 // for this in CheckPointerToIntegralCast
3067 assert(!Fatal);
3068 return true;
3070 S.CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3071 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3072 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
3073 return !Fatal;
3074 case CastKind::Volatile:
3076 const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
3077 if (S.getLangOpts().CPlusPlus)
3078 S.FFDiag(E, diag::note_constexpr_access_volatile_type)
3079 << AK_Read << E->getSubExpr()->getType();
3080 else
3081 S.FFDiag(E);
3082 }
3083
3084 return false;
3085 case CastKind::Dynamic:
3086 assert(!S.getLangOpts().CPlusPlus20);
3087 S.CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3088 << diag::ConstexprInvalidCastKind::Dynamic;
3089 return true;
3090 }
3091 llvm_unreachable("Unhandled CastKind");
3092 return false;
3093}
3094
3095// Destroy one scope: deallocate all local variables of the scope and diagnose
3096// out-of-lifetime destroys.
3097bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I) {
3098 assert(S.Current->getFunction());
3099 for (auto &Local : S.Current->getFunction()->getScope(I).locals_reverse()) {
3100 Block *LocalBlock = S.Current->getLocalBlock(Local.Offset);
3101
3102 if (!LocalBlock->isInitialized())
3103 continue;
3104
3105 if (LocalBlock->getBlockDesc<InlineDescriptor>().LifeState ==
3107 const Pointer Ptr = S.Current->getLocalPointer(Local.Offset);
3108 return diagnoseOutOfLifetimeDestroy(S, OpPC, Ptr);
3109 }
3110
3111 S.deallocate(LocalBlock);
3112 }
3113
3114 return true;
3115}
3116
3117// Perform a cast towards the class of the Decl (either up or down the
3118// hierarchy).
3120 const MemberPointer &MemberPtr,
3121 int32_t BaseOffset,
3122 const RecordDecl *BaseDecl) {
3123 const CXXRecordDecl *Expected;
3124 if (MemberPtr.getPathLength() >= 2)
3125 Expected = MemberPtr.getPathEntry(MemberPtr.getPathLength() - 2);
3126 else
3127 Expected = MemberPtr.getRecordDecl();
3128
3129 assert(Expected);
3130 if (Expected->getCanonicalDecl() != BaseDecl->getCanonicalDecl()) {
3131 // C++11 [expr.static.cast]p12: In a conversion from (D::*) to (B::*),
3132 // if B does not contain the original member and is not a base or
3133 // derived class of the class containing the original member, the result
3134 // of the cast is undefined.
3135 // C++11 [conv.mem]p2 does not cover this case for a cast from (B::*) to
3136 // (D::*). We consider that to be a language defect.
3137 return false;
3138 }
3139
3140 unsigned OldPathLength = MemberPtr.getPathLength();
3141 unsigned NewPathLength = OldPathLength - 1;
3142 bool IsDerivedMember = NewPathLength != 0;
3143 auto *NewPath = S.allocMemberPointerPath(NewPathLength);
3144 std::copy_n(MemberPtr.path(), NewPathLength, NewPath);
3145
3146 S.Stk.push<MemberPointer>(MemberPtr.atInstanceBase(BaseOffset, NewPathLength,
3147 NewPath, IsDerivedMember));
3148 return true;
3149}
3150
3152 const MemberPointer &MemberPtr,
3153 int32_t BaseOffset,
3154 const RecordDecl *BaseDecl,
3155 bool IsDerivedMember) {
3156 unsigned OldPathLength = MemberPtr.getPathLength();
3157 unsigned NewPathLength = OldPathLength + 1;
3158
3159 auto *NewPath = S.allocMemberPointerPath(NewPathLength);
3160 std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
3161 NewPath[OldPathLength] = cast<CXXRecordDecl>(BaseDecl);
3162
3163 S.Stk.push<MemberPointer>(MemberPtr.atInstanceBase(BaseOffset, NewPathLength,
3164 NewPath, IsDerivedMember));
3165 return true;
3166}
3167
3168/// DerivedToBaseMemberPointer
3170 const RecordDecl *BaseDecl) {
3171 const auto &Ptr = S.Stk.pop<MemberPointer>();
3172
3173 if (!Ptr.isDerivedMember() && Ptr.hasPath())
3174 return castBackMemberPointer(S, Ptr, Off, BaseDecl);
3175
3176 bool IsDerivedMember = Ptr.isDerivedMember() || !Ptr.hasPath();
3177 return appendToMemberPointer(S, Ptr, Off, BaseDecl, IsDerivedMember);
3178}
3179
3180/// BaseToDerivedMemberPointer
3182 const RecordDecl *BaseDecl) {
3183 const auto &Ptr = S.Stk.pop<MemberPointer>();
3184
3185 if (!Ptr.isDerivedMember()) {
3186 // Simply append.
3187 return appendToMemberPointer(S, Ptr, Off, BaseDecl,
3188 /*IsDerivedMember=*/false);
3189 }
3190
3191 return castBackMemberPointer(S, Ptr, Off, BaseDecl);
3192}
3193
3195 S.Stk.push<MemberPointer>(D);
3196 return true;
3197}
3198
3200 const auto &MP = S.Stk.pop<MemberPointer>();
3201
3202 if (!MP.isBaseCastPossible())
3203 return false;
3204
3205 S.Stk.push<Pointer>(MP.getBase());
3206 return true;
3207}
3208
3210 const auto &MP = S.Stk.pop<MemberPointer>();
3211
3212 const ValueDecl *D = MP.getDecl();
3213 const auto *FD = dyn_cast_if_present<FunctionDecl>(D);
3214 if (!FD)
3215 return false;
3216
3217 const auto *Method = dyn_cast<CXXMethodDecl>(FD);
3218 if (!Method)
3219 return false;
3220
3221 const Pointer &Base = MP.getBase();
3222 // The method must be accessible via the base of the MemberPointer.
3223 const CXXRecordDecl *MethodParent = Method->getParent();
3224 if (!Base.getRecord() || Base.getRecord()->getDecl() != MethodParent)
3225 return false;
3226
3227 const auto *Func = S.getContext().getOrCreateFunction(FD);
3228 if (!Func)
3229 return false;
3230 S.Stk.push<Pointer>(Func);
3231 return true;
3232}
3233
3234/// Just append the given Entry to the MemberPointer's path.
3235/// This is used to re-inject APValues into the bytecode interpreter.
3237 bool IsDerived) {
3238 const auto &MemberPtr = S.Stk.pop<MemberPointer>();
3239
3240 unsigned OldPathLength = MemberPtr.getPathLength();
3241 unsigned NewPathLength = OldPathLength + 1;
3242
3243 auto *NewPath = S.allocMemberPointerPath(NewPathLength);
3244 std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
3245 NewPath[OldPathLength] = cast<CXXRecordDecl>(Entry);
3246
3248 MemberPtr.withPath(NewPathLength, NewPath, IsDerived));
3249 return true;
3250}
3251
3252template <bool Signed>
3253static bool floatAPCast(InterpState &S, CodePtr OpPC, const Floating &F,
3254 uint32_t BitWidth, uint32_t FPOI) {
3255 APSInt Result(BitWidth, /*IsUnsigned=*/!Signed);
3256 auto Status = F.convertToInteger(Result);
3257
3258 // Float-to-Integral overflow check.
3259 if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite() &&
3260 !handleOverflow(S, OpPC, F.getAPFloat()))
3261 return false;
3262
3264
3265 auto ResultAP = S.allocAP<IntegralAP<Signed>>(BitWidth);
3266 ResultAP.copy(Result);
3267
3268 S.Stk.push<IntegralAP<Signed>>(ResultAP);
3269
3270 return CheckFloatResult(S, OpPC, F, Status, FPO);
3271}
3272
3273bool CastFloatingIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth,
3274 uint32_t FPOI) {
3275 Floating F = S.Stk.pop<Floating>();
3276 return floatAPCast<false>(S, OpPC, F, BitWidth, FPOI);
3277}
3278
3279bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth,
3280 uint32_t FPOI) {
3281 Floating F = S.Stk.pop<Floating>();
3282 return floatAPCast<true>(S, OpPC, F, BitWidth, FPOI);
3283}
3284
3285static bool validType(QualType T) {
3286 if (const RecordDecl *RD = T->getAsRecordDecl())
3287 return ASTContext::hasLayout(RD);
3288 return true;
3289}
3290
3292 APSInt &&Index, bool AllowReplace) {
3293 const OpaquePointer &OP = Ptr.asOpaquePointer();
3294 QualType ArrTy = OP.getSurroundingArray();
3295
3296 if (isa<VariableArrayType>(ArrTy) && OP.PathLength != 0)
3297 return false;
3298
3299 QualType ElemType;
3300 if (const ArrayType *AT = ArrTy->getAsArrayTypeUnsafe())
3301 ElemType = AT->getElementType();
3302 else
3303 ElemType = ArrTy;
3304
3305 if (ArrTy->isArrayType()) {
3306 unsigned NewPathLength;
3307 if (AllowReplace && OP.isArrayElement()) {
3308 // This is what happens after an array-to-pointer-decay. We don't enter
3309 // the array element but simply change the index in the array we're
3310 // already pointing into.
3311 NewPathLength = OP.PathLength;
3312 } else {
3313 NewPathLength = OP.PathLength + 1;
3314 }
3315
3316 PointerPathEntry NewEntry;
3317 if (Index.isNonNegative())
3318 NewEntry = PointerPathEntry::array(Index.getZExtValue());
3319 else
3320 NewEntry = PointerPathEntry::negativeArray((-Index).getZExtValue());
3321
3322 PointerPathEntry *NewPath =
3323 S.extendPointerPath(NewPathLength, OP.Path, NewEntry);
3324 S.Stk.push<Pointer>(
3325 OP.withPath(NewPath, NewPathLength, ElemType.getTypePtr()),
3326 Ptr.getByteOffset());
3327
3328 } else {
3329 if (!validType(ElemType))
3330 return false;
3331 unsigned ElemSize =
3333 size_t NewOffset = Ptr.getByteOffset() + (Index.getZExtValue() * ElemSize);
3334 bool PastEnd = Index != 0;
3335
3336 S.Stk.push<Pointer>(OP.withFieldType(ElemType.getTypePtr(), PastEnd),
3337 NewOffset);
3338 }
3339 return true;
3340}
3341
3342std::optional<Pointer> addSubOffsetOpaque(InterpState &S, CodePtr OpPC,
3343 const Pointer &Ptr, APSInt &&Offset,
3344 ArithOp Op) {
3345 assert(Ptr.isOpaquePointer());
3346 if (Offset.isZero())
3347 return Ptr;
3348
3349 const OpaquePointer &OP = Ptr.asOpaquePointer();
3350 QualType ArrTy = OP.getSurroundingArray();
3351 QualType ElemTy = ArrTy;
3352 unsigned NumElems = 1;
3353 if (const ArrayType *AT = ArrTy->getAsArrayTypeUnsafe()) {
3354 ElemTy = AT->getElementType();
3355 if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
3356 NumElems = CAT->getZExtSize();
3357 }
3358
3359 if (isa<IncompleteArrayType>(ArrTy)) {
3360 const SourceInfo &E = S.Current->getSource(OpPC);
3361 S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
3362 return std::nullopt;
3363 }
3364
3365 if (Offset > NumElems) {
3366 if (Op == ArithOp::Add)
3367 S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
3368 << Offset << /*non-array*/ !isa<ArrayType>(ArrTy) << NumElems;
3369 else
3370 S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
3371 << -Offset << /*non-array*/ !isa<ArrayType>(ArrTy) << NumElems;
3372 }
3373
3374 if (!validType(ElemTy) || !validType(ArrTy)) {
3375 Invalid(S, OpPC);
3376 return std::nullopt;
3377 }
3378
3379 if (Offset.getActiveBits() > 64)
3380 return std::nullopt;
3381
3382 // If the pointer is an array element, advance that index.
3383 if (OP.isArrayElement()) {
3384 unsigned NewPathLength = OP.PathLength;
3385 PointerPathEntry *NewPath = S.allocPointerPath(OP.PathLength, OP.Path);
3386
3387 if (Op == ArithOp::Add)
3388 NewPath[NewPathLength - 1].Index += Offset.getZExtValue();
3389 else
3390 NewPath[NewPathLength - 1].Index -= Offset.getZExtValue();
3391 return OP.withPath(NewPath, NewPathLength, OP.FieldType.getPointer());
3392 }
3393
3394 unsigned ElemSize =
3396 unsigned NewOffset;
3397 if (Op == ArithOp::Add)
3398 NewOffset = Ptr.getByteOffset() + (ElemSize * Offset.getZExtValue());
3399 else
3400 NewOffset = Ptr.getByteOffset() - (ElemSize * Offset.getZExtValue());
3401
3402 // We already checked offset != before, so this is a non-array type being
3403 // offset by > 0.
3404 return Pointer(OP.withPastEnd(true), NewOffset);
3405}
3406
3407// FIXME: Would be nice to generate this instead of hardcoding it here.
3408[[maybe_unused]] static constexpr bool OpReturns(Opcode Op) {
3409 return Op == OP_RetVoid || Op == OP_RetValue || Op == OP_NoRet ||
3410 Op == OP_RetSint8 || Op == OP_RetUint8 || Op == OP_RetSint16 ||
3411 Op == OP_RetUint16 || Op == OP_RetSint32 || Op == OP_RetUint32 ||
3412 Op == OP_RetSint64 || Op == OP_RetUint64 || Op == OP_RetIntAP ||
3413 Op == OP_RetIntAPS || Op == OP_RetBool || Op == OP_RetFixedPoint ||
3414 Op == OP_RetPtr || Op == OP_RetMemberPtr || Op == OP_RetFloat ||
3415 Op == OP_EndSpeculation;
3416}
3417
3418#if USE_TAILCALLS
3419PRESERVE_NONE static bool InterpNext(InterpState &S);
3420#endif
3421
3422// The dispatcher functions read the opcode arguments from the
3423// bytecode and call the implementation function.
3424#define GET_INTERPFN_DISPATCHERS
3425#include "Opcodes.inc"
3426#undef GET_INTERPFN_DISPATCHERS
3427
3429// Array of the dispatcher functions defined above.
3431#define GET_INTERPFN_LIST
3432#include "Opcodes.inc"
3433#undef GET_INTERPFN_LIST
3434};
3435
3436#if USE_TAILCALLS
3437// Read the next opcode and call the dispatcher function.
3438PRESERVE_NONE static bool InterpNext(InterpState &S) {
3439 auto Op = S.PC.read<Opcode>();
3440 auto Fn = InterpFunctions[Op];
3441 MUSTTAIL return Fn(S);
3442}
3443#endif
3444
3446 // The current stack frame when we started Interpret().
3447 // This is being used by the ops to determine wheter
3448 // to return from this function and thus terminate
3449 // interpretation.
3450 assert(!S.Current->isRoot());
3451
3452 S.PC = S.Current->getFunction()->getCodeBegin();
3453
3454#if USE_TAILCALLS
3455 return InterpNext(S);
3456#else
3457 while (true) {
3458 auto Op = S.PC.read<Opcode>();
3459 auto Fn = InterpFunctions[Op];
3460
3461 if (!Fn(S))
3462 return false;
3463 if (OpReturns(Op))
3464 break;
3465 }
3466 return true;
3467#endif
3468}
3469
3470/// This is used to implement speculative execution via __builtin_constant_p
3471/// when we generate bytecode.
3472///
3473/// The setup here is that we use the same tailcall mechanism for speculative
3474/// evaluation that we use for the regular one.
3475/// Since each speculative execution ends with an EndSpeculation opcode,
3476/// that one does NOT call InterpNext() but simply returns true.
3477/// This way, we return back to this function when we see an EndSpeculation,
3478/// OR (of course), when we encounter an error and one of the opcodes
3479/// returns false.
3480PRESERVE_NONE static bool BCP(InterpState &S, CodePtr OpPC, int32_t Offset,
3481 PrimType PT) {
3482 // PC after reading the BCP opcode and both Offset/PT arguments.
3483 [[maybe_unused]] CodePtr PCBefore = S.PC;
3484 size_t StackSizeBefore = S.Stk.size();
3485
3486 // Speculation depth must be at least 1 here, since we must have
3487 // passed a StartSpeculation op before.
3488#ifndef NDEBUG
3489 [[maybe_unused]] unsigned DepthBefore = S.SpeculationDepth;
3490 assert(DepthBefore >= 1);
3491#endif
3492
3493 auto SpeculativeInterp = [&S]() -> bool {
3494 // Ignore diagnostics during speculative execution.
3495 PushIgnoreDiags(S);
3496 auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S); });
3497
3498#if USE_TAILCALLS
3499 auto Op = S.PC.read<Opcode>();
3500 auto Fn = InterpFunctions[Op];
3501 return Fn(S);
3502#else
3503 while (true) {
3504 auto Op = S.PC.read<Opcode>();
3505 auto Fn = InterpFunctions[Op];
3506
3507 if (!Fn(S))
3508 return false;
3509 if (OpReturns(Op))
3510 break;
3511 }
3512 return true;
3513#endif
3514 };
3515
3516 if (SpeculativeInterp()) {
3517 // Speculation must've ended naturally via a EndSpeculation opcode.
3518 assert(S.SpeculationDepth == DepthBefore - 1);
3519 if (PT == PT_Ptr) {
3520 const auto &Ptr = S.Stk.pop<Pointer>();
3521 assert(S.Stk.size() == StackSizeBefore);
3524 } else {
3525 // Pop the result from the stack and return success.
3526 TYPE_SWITCH(PT, S.Stk.discard<T>(););
3527 assert(S.Stk.size() == StackSizeBefore);
3529 }
3530 } else {
3531 // Jump to the end of the speculation, just after the actual EndSpeculation
3532 // op.
3533 S.PC = PCBefore + Offset - align(sizeof(Opcode));
3534
3535 // End the speculation manually since we didn't call EndSpeculation
3536 // naturally.
3537 EndSpeculation(S);
3538
3539 if (!S.inConstantContext())
3540 return Invalid(S, OpPC);
3541
3542 S.Stk.clearTo(StackSizeBefore);
3544 }
3545
3546 // We have already evaluated this speculation's EndSpeculation opcode.
3547 assert(S.SpeculationDepth == DepthBefore - 1);
3548
3549 return true;
3550}
3551
3552} // namespace interp
3553} // 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)
static PRESERVE_NONE bool RetValue(InterpState &S)
Definition Interp.cpp:53
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK)
Definition Interp.cpp:195
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition Interp.cpp:222
static bool Jf(InterpState &S, CodePtr OpPC, int32_t Offset)
Definition Interp.cpp:74
static bool Jmp(InterpState &S, CodePtr OpPC, int32_t Offset)
Definition Interp.cpp:61
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, const ValueDecl *D, AccessKinds AK=AK_Read)
Definition Interp.cpp:103
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC, const ValueDecl *VD, AccessKinds AK=AK_Read)
Definition Interp.cpp:153
static bool isModification(AccessKinds AK)
Definition Interp.cpp:148
#define MUSTTAIL
Definition Interp.cpp:47
static void noteValueLocation(InterpState &S, const Block *B)
Definition Interp.cpp:89
static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
Definition Interp.cpp:82
static bool Jt(InterpState &S, CodePtr OpPC, int32_t Offset)
Definition Interp.cpp:66
#define PRESERVE_NONE
Definition Interp.h:49
static StringRef getIdentifier(const Token &Tok)
#define TYPE_SWITCH_ALLOC(Expr, B)
Definition PrimType.h:309
#define TYPE_SWITCH(Expr, B)
Definition PrimType.h:235
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:223
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.
static bool hasLayout(const RecordDecl *D)
Whether layout (offset and size) information can be queried for D.
const clang::PrintingPolicy & getPrintingPolicy() const
Definition ASTContext.h:881
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
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:947
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3836
QualType getElementType() const
Definition TypeBase.h:3848
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
AccessSpecifier Access
The access along this inheritance path.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
paths_iterator begin()
paths_iterator end()
Represents a C++ destructor within a class.
Definition DeclCXX.h:2906
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2149
bool isVirtual() const
Definition DeclCXX.h:2204
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition DeclCXX.h:522
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:2987
Expr * getCallee()
Definition Expr.h:3134
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3178
Expr ** getArgs()
Retrieve the call arguments.
Definition Expr.h:3181
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1631
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1290
ValueDecl * getDecl()
Definition Expr.h:1358
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
bool isInvalidDecl() const
Definition DeclBase.h:596
SourceLocation getLocation() const
Definition DeclBase.h:447
bool hasAttr() const
Definition DeclBase.h:585
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:435
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Represents an enum.
Definition Decl.h:4146
unsigned getNumNegativeBits() const
Returns the width in bits required to store all the negative enumerators of this enum.
Definition Decl.h:4356
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:5253
This represents one expression.
Definition Expr.h:113
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:145
LangOptions::FPExceptionModeKind getExceptionMode() const
static FPOptions getFromOpaqueInt(storage_type Value)
RoundingMode getRoundingMode() const
Represents a member of a struct/union/class.
Definition Decl.h:3295
Represents a function declaration or definition.
Definition Decl.h:2059
QualType getReturnType() const
Definition Decl.h:2976
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:3019
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition Decl.h:2597
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
Definition Decl.h:2480
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:3470
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3188
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:3235
@ FPE_Ignore
Assume that floating-point exceptions are masked.
This represents a decl that may have a name.
Definition Decl.h:275
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:296
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:302
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8585
void addConst()
Add the const type qualifier to this QualType.
Definition TypeBase.h:1172
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8501
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8574
Represents a struct/union/class.
Definition Decl.h:4460
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
TagDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:4963
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
Definition TargetInfo.h:495
The base class of the type hierarchy.
Definition TypeBase.h:1879
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 isArrayType() const
Definition TypeBase.h:8837
bool isPointerType() const
Definition TypeBase.h:8738
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9154
bool isReferenceType() const
Definition TypeBase.h:8762
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9232
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9390
bool isPointerOrReferenceType() const
Definition TypeBase.h:8742
bool isRecordType() const
Definition TypeBase.h:8865
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:713
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1594
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition Decl.h:1307
A memory block, either on the stack or in the heap.
Definition InterpBlock.h:43
const T & deref() const
bool isExtern() const
Checks if the block is extern.
Definition InterpBlock.h:81
const Descriptor * getDescriptor() const
Returns the block's descriptor.
Definition InterpBlock.h:77
bool isStatic() const
Checks if the block has static storage duration.
Definition InterpBlock.h:83
bool isTemporary() const
Checks if the block is temporary.
Definition InterpBlock.h:85
std::byte * rawData()
Returns a pointer to the raw data, including metadata.
bool isInitialized() const
Returns whether the data of this block has been initialized via invoking the Ctor func.
Definition InterpBlock.h:98
bool isDynamic() const
Definition InterpBlock.h:87
UnsignedOrNone getDeclID() const
Returns the declaration ID.
Definition InterpBlock.h:95
bool isDummy() const
Definition InterpBlock.h:88
unsigned getEvalID() const
The Evaluation ID this block was created in.
bool isWeak() const
Definition InterpBlock.h:86
bool isAccessible() const
Pointer into the code segment.
Definition Source.h:31
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
Definition Source.h:60
Compilation context for expressions.
Definition Compiler.h:119
unsigned collectBaseOffset(const RecordDecl *BaseDecl, const RecordDecl *DerivedDecl) const
Definition Context.cpp:786
const Record * getRecord(const RecordDecl *D) const
Definition Context.cpp:817
const Function * getOrCreateFunction(const FunctionDecl *FuncDecl)
Definition Context.cpp:651
ASTContext & getASTContext() const
Returns the AST context.
Definition Context.h:107
OptPrimType classify(QualType T) const
Classifies a type.
Definition Context.cpp:506
const CXXMethodDecl * getOverridingFunction(const CXXRecordDecl *DynamicDecl, const CXXRecordDecl *StaticDecl, const CXXMethodDecl *InitialFunction) const
Definition Context.cpp:615
Manages dynamic memory allocations done during bytecode interpretation.
std::optional< Form > getAllocationForm(const Expr *Source) const
Checks whether the allocation done at the given source is an array allocation.
bool deallocate(const Expr *Source, const Block *BlockToDelete)
Deallocate the given source+block combination.
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
bool isFinite() const
Definition Floating.h:151
APFloat::opStatus convertToInteger(APSInt &Result) const
Definition Floating.h:71
APFloat getAPFloat() const
Definition Floating.h:64
Base class for stack frames, shared between VM and walker.
Definition Frame.h:28
Bytecode function.
Definition Function.h:98
bool hasExplicitThisPointer() const
Definition Function.h:226
Scope & getScope(unsigned Idx)
Returns a specific scope.
Definition Function.h:173
CodePtr getCodeBegin() const
Returns a pointer to the start of the code.
Definition Function.h:128
bool isDestructor() const
Checks if the function is a destructor.
Definition Function.h:196
bool isVirtual() const
Checks if the function is virtual.
Definition Function.h:183
bool hasNonNullAttr() const
Definition Function.h:157
bool isFullyCompiled() const
Checks if the function is fully done compiling.
Definition Function.h:223
bool isConstructor() const
Checks if the function is a constructor.
Definition Function.h:188
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
Definition Function.h:133
bool hasBody() const
Checks if the function already has a body attached.
Definition Function.h:234
bool isConstexpr() const
Definition Function.h:185
unsigned getWrittenArgSize() const
Definition Function.h:252
unsigned getArgSize() const
Returns the size of the argument stack.
Definition Function.h:125
bool isLambdaStaticInvoker() const
Returns whether this function is a lambda static invoker, which we generate custom byte code for.
Definition Function.h:204
bool isValid() const
Checks if the function is valid to call.
Definition Function.h:180
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Definition IntegralAP.h:36
void copy(const APInt &V)
Definition IntegralAP.h:78
Wrapper around numeric types.
Definition Integral.h:69
static std::enable_if_t<!std::is_same_v< ValT, IntegralKind >, Integral > from(ValT V, unsigned NumBits=0)
Definition Integral.h:327
Frame storing local variables.
Definition InterpFrame.h:27
SourceLocation getLocation(CodePtr PC) const
static void free(InterpFrame *F)
Definition InterpFrame.h:59
InterpFrame * Caller
The frame of the previous function.
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
SourceRange getRange(CodePtr PC) const
Block * getLocalBlock(unsigned Offset) const
const Pointer & getThis() const
Returns the 'this' pointer.
const Function * getFunction() const
Returns the current function.
Definition InterpFrame.h:90
unsigned getArgSize() const
bool isRoot() const
Checks if the frame is a root frame - return should quit the interpreter.
Pointer getLocalPointer(unsigned Offset) const
Returns a pointer to a local variables.
const Expr * getExpr(CodePtr PC) const
unsigned getDepth() const
static size_t allocSize(const Function *F)
Returns the number of bytes needed to allocate an InterpFrame for the given function.
Definition InterpFrame.h:48
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:78
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:63
Interpreter context.
Definition InterpState.h:43
bool lifetimeStartedInEvaluation(const Block *B) const
Context & getContext() const
Definition InterpState.h:73
bool initializingBlock(const Block *B) const
DynamicAllocator & getAllocator()
Definition InterpState.h:77
Context & Ctx
Interpreter Context.
const unsigned EvalID
ID identifying this evaluation.
bool noteStep(CodePtr OpPC)
Note that a step has been executed.
InterpStack & Stk
Temporary stack.
bool checkingConstantDestruction() const
Return if we're checking if a global variable has a constant destructor.
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
InterpFrame * Current
The current frame.
PointerPathEntry * allocPointerPath(unsigned Length, const PointerPathEntry *OldPP)
const CXXRecordDecl ** allocMemberPointerPath(unsigned Length)
void deallocate(Block *B)
Deallocates a pointer.
PointerPathEntry * extendPointerPath(unsigned NewLength, const PointerPathEntry *OldPP, PointerPathEntry NewEntry)
Allocate a new pointer path of Length NewLength.
llvm::SmallVector< PtrView > InitializingPtrs
List of blocks we're currently running either constructors or destructors for.
T allocAP(unsigned BitWidth)
StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const
Program & P
Reference to the module containing all bytecode.
unsigned getPathLength() const
Return the length of the cast path.
PrimType value_or(PrimType PT) const
Definition PrimType.h:88
A pointer to a memory block, live or dead.
Definition Pointer.h:531
Pointer narrow() const
Restricts the scope of an array element pointer.
Definition Pointer.h:642
Pointer stripBaseCasts() const
Strip base casts from this Pointer.
Definition Pointer.h:1256
const Expr * getRootExpr() const
Definition Pointer.cpp:1217
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
Definition Pointer.h:613
bool isDummy() const
Checks if the pointer points to a dummy value.
Definition Pointer.h:942
int64_t getIndex() const
Returns the index into an array.
Definition Pointer.h:1017
bool isStringPointer() const
Definition Pointer.h:861
unsigned getNumElems() const
Returns the number of elements.
Definition Pointer.h:994
QualType getType() const
Returns the type of the innermost field.
Definition Pointer.h:724
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition Pointer.h:709
bool isZero() const
Checks if the pointer is null.
Definition Pointer.h:656
bool isRoot() const
Pointer points directly to a block.
Definition Pointer.h:815
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition Pointer.h:686
static bool pointToSameBlock(const Pointer &A, const Pointer &B)
Checks if both given pointers point to the same block.
Definition Pointer.cpp:894
bool isOnePastEnd() const
Checks if the index is one past end.
Definition Pointer.h:1027
const FieldDecl * getField() const
Returns the field information.
Definition Pointer.h:873
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
Definition Pointer.h:649
bool isBlockPointer() const
Definition Pointer.h:857
const Block * block() const
Definition Pointer.h:1002
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
Definition Pointer.h:714
PtrView view() const
Definition Pointer.h:603
UnsignedOrNone getCurrentDecl() const
Returns the current declaration ID.
Definition Program.h:155
Structure/Class descriptor.
Definition Record.h:25
const RecordDecl * getDecl() const
Returns the underlying declaration.
Definition Record.h:70
unsigned getNumVirtualBases() const
Definition Record.h:131
llvm::iterator_range< LocalVectorTy::const_reverse_iterator > locals_reverse() const
Definition Function.h:56
Describes the statement/declaration an opcode was generated from.
Definition Source.h:77
SourceLocation getLoc() const
Definition Source.cpp:15
bool checkingForUndefinedBehavior() const
Are we checking an expression for overflow?
Definition State.h:126
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
Definition State.cpp:86
bool emitRelaxedDiag(SourceLocation Loc, diag::kind DiagId)
If DiagId should be relaxed as per the current evaluation settings, emit it as a warning instead of a...
Definition State.cpp:20
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:37
ASTContext & getASTContext() const
Definition State.h:90
bool noteUndefinedBehavior() const
Note that we hit something that was technically undefined behavior, but that we can evaluate past it ...
Definition State.h:115
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:60
const LangOptions & getLangOpts() const
Definition State.h:91
bool checkingPotentialConstantExpression() const
Are we checking whether the expression is a potential constant expression?
Definition State.h:122
Defines the clang::TargetInfo interface.
bool arePotentiallyOverlappingStringLiterals(const Pointer &LHS, const Pointer &RHS)
Definition Interp.cpp:2898
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a field from which a pointer is going to be derived is valid.
Definition Interp.cpp:545
bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off)
Definition Interp.cpp:1658
bool GetMemberPtrBase(InterpState &S)
Definition Interp.cpp:3199
bool PseudoDtor(InterpState &S, CodePtr OpPC)
Ends the lifetime of the pop'd pointer.
Definition Interp.cpp:2567
static bool CheckCallDepth(InterpState &S, CodePtr OpPC)
Definition Interp.cpp:1145
static constexpr bool OpReturns(Opcode Op)
Definition Interp.cpp:3408
const InterpFn InterpFunctions[]
Definition Interp.cpp:3430
static bool diagnoseCallableDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *DiagDecl)
Definition Interp.cpp:1041
bool GetTypeid(InterpState &S, const Type *TypePtr, const Type *TypeInfoType)
Typeid support.
Definition Interp.cpp:2849
bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
Definition Interp.cpp:2800
static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition Interp.cpp:677
bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
Definition Interp.cpp:2787
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
Definition Interp.cpp:1033
bool arrayElemPtrOpaque(InterpState &S, CodePtr OpPC, const Pointer &Ptr, APSInt &&Index, bool AllowReplace)
Definition Interp.cpp:3291
bool CheckFunctionDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *FD)
Opcode. Check if the function decl can be called at compile time.
Definition Interp.cpp:1831
std::optional< Pointer > addSubOffsetOpaque(InterpState &S, CodePtr OpPC, const Pointer &Ptr, APSInt &&Offset, ArithOp Op)
Definition Interp.cpp:3342
bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue)
static bool appendToMemberPointer(InterpState &S, const MemberPointer &MemberPtr, int32_t BaseOffset, const RecordDecl *BaseDecl, bool IsDerivedMember)
Definition Interp.cpp:3151
static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
Definition Interp.cpp:1121
bool StartThisLifetime(InterpState &S)
Definition Interp.cpp:2511
void cleanupAfterFunctionCall(InterpState &S, const Function *Func)
Definition Interp.cpp:268
static bool runRecordDestructor(InterpState &S, CodePtr OpPC, const Pointer &BasePtr, const Descriptor *Desc)
Definition Interp.cpp:1340
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc, AccessKinds AK)
Checks if the Descriptor is of a constexpr or const global variable.
Definition Interp.cpp:464
bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType)
Definition Interp.cpp:2854
bool LT(InterpState &S, CodePtr OpPC)
Definition Interp.h:1524
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:566
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:1238
static void setLifeStateRecurse(PtrView Ptr, Lifetime L)
Definition Interp.cpp:2535
bool PushIgnoreDiags(InterpState &S)
Definition Interp.h:3713
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:817
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:1280
bool EndLifetime(InterpState &S, CodePtr OpPC)
Ends the lifetime of the peek'd pointer.
Definition Interp.cpp:2557
static bool getDynamicDecl(InterpState &S, CodePtr OpPC, PtrView TypePtr, const CXXRecordDecl *&DynamicDecl)
Definition Interp.cpp:2051
bool CastMemberPtrDerivedPop(InterpState &S, int32_t Off, const RecordDecl *BaseDecl)
BaseToDerivedMemberPointer.
Definition Interp.cpp:3181
static DynamicCastResult findRecordBase(const ASTContext &Ctx, const Record *R, QualType Needle)
Definition Interp.cpp:2135
static bool CheckWeak(InterpState &S, CodePtr OpPC, const Block *B)
Definition Interp.cpp:800
static void copyPrimitiveMemory(InterpState &S, PtrView Ptr, PrimType T)
Definition Interp.cpp:2949
bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, unsigned BitWidth)
Definition Interp.cpp:2756
static bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B)
Definition Interp.cpp:1367
bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off)
1) Peeks a Pointer 2) Pushes Pointer.atField(Off) on the stack
Definition Interp.cpp:1653
bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK, bool WillActivate)
Definition Interp.cpp:325
static bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *CE, unsigned ArgSize)
Definition Interp.cpp:1318
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if Ptr is a one-past-the-end pointer.
Definition Interp.cpp:555
bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC, const FixedPoint &FP)
Definition Interp.cpp:2735
bool PopIgnoreDiags(InterpState &S)
Definition Interp.h:3725
bool GetMemberPtrDecl(InterpState &S)
Definition Interp.cpp:3209
bool handleReference(InterpState &S, CodePtr OpPC, Block *B)
Definition Interp.cpp:2830
bool CheckBitCast(InterpState &S, CodePtr OpPC, const Type *TargetType, bool SrcIsVoidPtr)
Definition Interp.cpp:1846
bool CopyMemberPtrPath(InterpState &S, const RecordDecl *Entry, bool IsDerived)
Just append the given Entry to the MemberPointer's path.
Definition Interp.cpp:3236
static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t Off)
Definition Interp.cpp:1589
static void startLifetimeRecurse(PtrView Ptr)
Definition Interp.cpp:2486
static bool hasVirtualDestructor(QualType T)
Definition Interp.cpp:1398
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a value can be loaded from a block.
Definition Interp.cpp:879
static bool getBase(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t Off, bool NullOK)
Definition Interp.cpp:1663
static void finishGlobalRecurse(InterpState &S, PtrView Ptr)
Definition Interp.cpp:2995
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition PrimType.h:213
bool CheckBCPResult(InterpState &S, const Pointer &Ptr)
Definition Interp.cpp:305
PRESERVE_NONE bool EndSpeculation(InterpState &S)
Definition Interp.h:3757
bool diagnoseShiftFailure(InterpState &S, CodePtr OpPC, ShiftFailure Failure, const APSInt *Value, unsigned Bits)
Definition Interp.cpp:241
bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC)
Checks if dynamic memory allocation is available in the current language mode.
Definition Interp.cpp:1229
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
Definition Interp.cpp:434
bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK, const Type *TargetType)
Definition Interp.cpp:1724
bool DiagTypeid(InterpState &S, CodePtr OpPC)
Definition Interp.cpp:2890
bool diagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Definition Interp.cpp:724
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
This is not used by any of the opcodes directly.
Definition Interp.cpp:956
static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func, const Pointer &ThisPtr)
Definition Interp.cpp:1763
llvm::APInt APInt
Definition FixedPoint.h:19
void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED, const APSInt &Value)
Definition Interp.cpp:1506
bool isConstexprUnknown(const Block *B)
Definition Interp.cpp:293
bool StartThisLifetime1(InterpState &S)
Definition Interp.cpp:2522
bool RVOPtr(InterpState &S)
Definition Interp.h:3259
bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR, bool InitializerFailed)
Definition Interp.cpp:1285
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
Definition Interp.cpp:534
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:1256
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:1209
PrimType
Enumeration of the primitive types of the VM.
Definition PrimType.h:34
static bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr, bool IsCtor, bool IsDtor)
Definition Interp.cpp:1020
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:1902
constexpr bool needsAlloc()
Definition PrimType.h:133
bool(*)(InterpState &) PRESERVE_NONE InterpFn
Definition Interp.cpp:3428
bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index)
Definition Interp.cpp:2748
bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK)
Checks if a pointer is a dummy pointer.
Definition Interp.cpp:1300
static bool diagnoseOutOfLifetimeDestroy(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition Interp.cpp:1787
static bool floatAPCast(InterpState &S, CodePtr OpPC, const Floating &F, uint32_t BitWidth, uint32_t FPOI)
Definition Interp.cpp:3253
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:2584
bool checkDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition Interp.cpp:1803
bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T)
Definition Interp.cpp:1527
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
Definition Interp.cpp:426
bool CheckFloatStatus(InterpState &S, CodePtr OpPC, APFloat::opStatus Status, FPOptions FPO)
Check if the given floating-point evaluation status is allowed for compile-time constant folding duri...
Definition Interp.cpp:1173
bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off)
Definition Interp.cpp:1715
static void compileFunction(InterpState &S, const Function *Func)
Definition Interp.cpp:1891
bool CheckThis(InterpState &S, CodePtr OpPC)
Checks the 'this' pointer.
Definition Interp.cpp:1156
bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth, uint32_t FPOI)
Definition Interp.cpp:3279
bool CheckIntegralAddressCast(InterpState &S, CodePtr OpPC, unsigned BitWidth)
Definition Interp.cpp:2782
bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.cpp:3097
bool CheckMutable(InterpState &S, CodePtr OpPC, PtrView Ptr, AccessKinds AK)
Checks if a pointer points to a mutable field.
Definition Interp.cpp:650
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
Definition PrimType.cpp:24
bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm, bool IsGlobalDelete)
Definition Interp.cpp:1405
bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E)
Definition Interp.cpp:2688
bool CallBI(InterpState &S, CodePtr OpPC, const CallExpr *CE, uint32_t BuiltinID)
Definition Interp.cpp:2413
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B)
Definition Interp.cpp:848
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
Definition Interp.cpp:407
static bool CheckLifetime(InterpState &S, CodePtr OpPC, Lifetime LT, const Block *B, AccessKinds AK)
Definition Interp.cpp:783
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr, bool WillBeActivated)
Checks if a value can be stored in a block.
Definition Interp.cpp:989
static bool allowNullSubObj(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition Interp.cpp:1584
bool FinishInitGlobal(InterpState &S)
Definition Interp.cpp:3043
bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK)
Definition Interp.cpp:1719
llvm::BitVector collectNonNullArgs(const FunctionDecl *F, ArrayRef< const Expr * > Args)
static bool castBackMemberPointer(InterpState &S, const MemberPointer &MemberPtr, int32_t BaseOffset, const RecordDecl *BaseDecl)
Definition Interp.cpp:3119
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, const CallExpr *CE)
Definition Interp.cpp:2424
bool CastFloatingIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth, uint32_t FPOI)
Definition Interp.cpp:3273
bool MarkDestroyed(InterpState &S, CodePtr OpPC)
Definition Interp.cpp:2575
bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
Definition Interp.cpp:2318
static bool validType(QualType T)
Definition Interp.cpp:3285
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
Definition Interp.cpp:593
bool Interpret(InterpState &S)
Interpreter entry point.
Definition Interp.cpp:3445
bool GetMemberPtr(InterpState &S, const ValueDecl *D)
Definition Interp.cpp:3194
static PRESERVE_NONE bool BCP(InterpState &S, CodePtr OpPC, int32_t Offset, PrimType PT)
This is used to implement speculative execution via __builtin_constant_p when we generate bytecode.
Definition Interp.cpp:3480
bool CastMemberPtrBasePop(InterpState &S, int32_t Off, const RecordDecl *BaseDecl)
DerivedToBaseMemberPointer.
Definition Interp.cpp:3169
llvm::APSInt APSInt
Definition FixedPoint.h:20
bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, bool Fatal)
Definition Interp.cpp:3055
bool DynamicCast(InterpState &S, CodePtr OpPC, const Type *DestTypePtr, bool IsReferenceCast)
Definition Interp.cpp:2152
static bool diagnoseTypeIdField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, unsigned Offset)
Definition Interp.cpp:1559
RangeSelector merge(RangeSelector First, RangeSelector Second)
Selects the merge of the two ranges, i.e.
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ Ambiguous
Name lookup results in an ambiguity; use getAmbiguityKind to figure out what kind of ambiguity we hav...
Definition Lookup.h:64
@ Success
Annotation was successful.
Definition Parser.h:65
@ AS_private
Definition Specifiers.h:127
@ SC_Extern
Definition Specifiers.h:252
CheckSubobjectKind
The order of this enum is important for diagnostics.
Definition State.h:42
@ CSK_Derived
Definition State.h:44
@ CSK_Base
Definition State.h:43
@ CSK_Field
Definition State.h:45
@ Result
The result type of a method or function.
Definition TypeBase.h:906
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
Definition State.h:26
@ AK_TypeId
Definition State.h:34
@ AK_Construct
Definition State.h:35
@ AK_Increment
Definition State.h:30
@ AK_DynamicCast
Definition State.h:33
@ 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
OptionalUnsigned< unsigned > UnsignedOrNone
const FunctionProtoType * T
@ Off
Never emit colors regardless of the output stream.
U cast(CodeGen::Address addr)
Definition Address.h:327
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
A quantity in bits.
Describes a memory block created by an allocation site.
Definition Descriptor.h:122
const bool IsConst
Flag indicating if the block is mutable.
Definition Descriptor.h:154
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition Descriptor.h:246
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition Descriptor.h:260
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:253
const ValueDecl * asValueDecl() const
Definition Descriptor.h:205
QualType getType() const
const Decl * asDecl() const
Definition Descriptor.h:201
const Descriptor *const ElemDesc
Descriptor of the array element.
Definition Descriptor.h:148
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:251
const VarDecl * asVarDecl() const
Definition Descriptor.h:209
PrimType getPrimType() const
Definition Descriptor.h:231
bool isRecord() const
Checks if the descriptor is of a record.
Definition Descriptor.h:265
const bool IsTemporary
Flag indicating if the block is a temporary.
Definition Descriptor.h:158
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition Descriptor.h:146
const Expr * asExpr() const
Definition Descriptor.h:202
Descriptor used for global variables.
Definition Descriptor.h:49
Inline descriptor embedded in structures and arrays.
Definition Descriptor.h:67
OpaquePointer withFieldType(const Type *FieldTy, std::optional< bool > PastEnd=std::nullopt) const
Definition Pointer.h:442
llvm::PointerIntPair< const Type *, 2, unsigned > FieldType
Definition Pointer.h:435
OpaquePointer withPastEnd(bool PastEnd) const
Definition Pointer.h:461
QualType getSurroundingArray() const
If this is pointing to an array element, return the array.
Definition Pointer.cpp:1341
const PointerPathEntry * Path
Definition Pointer.h:436
bool isArrayElement() const
Definition Pointer.h:482
QualType getFieldType() const
Definition Pointer.h:476
OpaquePointer withPath(const PointerPathEntry *Path, unsigned PathLength, const Type *FieldTy, std::optional< bool > PastEnd=std::nullopt) const
Definition Pointer.h:451
static PointerPathEntry array(int64_t Index)
Definition Pointer.h:410
static PointerPathEntry field(const FieldDecl *FD)
Definition Pointer.h:424
static PointerPathEntry negativeArray(int64_t Index)
Definition Pointer.h:417
static PointerPathEntry base(const CXXRecordDecl *RD, bool Virtual=false)
Definition Pointer.h:403
const Record * getRecord() const
Definition Pointer.h:153
const FieldDecl * getField() const
Definition Pointer.h:158
const Block * block() const
Definition Pointer.h:56
bool isMutable() const
Definition Pointer.h:50
QualType getType() const
Definition Pointer.h:278
bool isConst() const
Definition Pointer.h:62
bool isRoot() const
Definition Pointer.h:60
Lifetime getLifetime() const
Definition Pointer.cpp:691
PtrView getBase() const
Definition Pointer.h:268
bool isActive() const
Definition Pointer.h:46
T & deref() const
Definition Pointer.h:244
PtrView stripBaseCasts() const
Definition Pointer.h:141