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