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