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