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