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