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