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