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