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