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