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