xref: /llvm-project/clang/lib/AST/ByteCode/Interp.cpp (revision 51c7338cc671c90ba9345b53c7ca01dc461341ed)
1a07aba5dSTimm Baeder //===------- Interp.cpp - Interpreter for the constexpr VM ------*- C++ -*-===//
2a07aba5dSTimm Baeder //
3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information.
5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a07aba5dSTimm Baeder //
7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===//
8a07aba5dSTimm Baeder 
9a07aba5dSTimm Baeder #include "Interp.h"
10a07aba5dSTimm Baeder #include "Function.h"
11a07aba5dSTimm Baeder #include "InterpFrame.h"
12a07aba5dSTimm Baeder #include "InterpShared.h"
13a07aba5dSTimm Baeder #include "InterpStack.h"
14a07aba5dSTimm Baeder #include "Opcode.h"
15a07aba5dSTimm Baeder #include "PrimType.h"
16a07aba5dSTimm Baeder #include "Program.h"
17a07aba5dSTimm Baeder #include "State.h"
18a07aba5dSTimm Baeder #include "clang/AST/ASTContext.h"
19a07aba5dSTimm Baeder #include "clang/AST/CXXInheritance.h"
20a07aba5dSTimm Baeder #include "clang/AST/DeclObjC.h"
21a07aba5dSTimm Baeder #include "clang/AST/Expr.h"
22a07aba5dSTimm Baeder #include "clang/AST/ExprCXX.h"
23fed8695bSTimm Baeder #include "clang/Basic/DiagnosticSema.h"
24e637a5c9STimm Baeder #include "clang/Basic/TargetInfo.h"
25a07aba5dSTimm Baeder #include "llvm/ADT/StringExtras.h"
26a07aba5dSTimm Baeder 
27a07aba5dSTimm Baeder using namespace clang;
28a07aba5dSTimm Baeder using namespace clang::interp;
29a07aba5dSTimm Baeder 
3082ed9c03STimm Baeder static bool RetValue(InterpState &S, CodePtr &Pt) {
31a07aba5dSTimm Baeder   llvm::report_fatal_error("Interpreter cannot return values");
32a07aba5dSTimm Baeder }
33a07aba5dSTimm Baeder 
34a07aba5dSTimm Baeder //===----------------------------------------------------------------------===//
35a07aba5dSTimm Baeder // Jmp, Jt, Jf
36a07aba5dSTimm Baeder //===----------------------------------------------------------------------===//
37a07aba5dSTimm Baeder 
38a07aba5dSTimm Baeder static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
39a07aba5dSTimm Baeder   PC += Offset;
40a07aba5dSTimm Baeder   return true;
41a07aba5dSTimm Baeder }
42a07aba5dSTimm Baeder 
43a07aba5dSTimm Baeder static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
44a07aba5dSTimm Baeder   if (S.Stk.pop<bool>()) {
45a07aba5dSTimm Baeder     PC += Offset;
46a07aba5dSTimm Baeder   }
47a07aba5dSTimm Baeder   return true;
48a07aba5dSTimm Baeder }
49a07aba5dSTimm Baeder 
50a07aba5dSTimm Baeder static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
51a07aba5dSTimm Baeder   if (!S.Stk.pop<bool>()) {
52a07aba5dSTimm Baeder     PC += Offset;
53a07aba5dSTimm Baeder   }
54a07aba5dSTimm Baeder   return true;
55a07aba5dSTimm Baeder }
56a07aba5dSTimm Baeder 
57a07aba5dSTimm Baeder static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC,
58a07aba5dSTimm Baeder                                        const ValueDecl *VD) {
59a07aba5dSTimm Baeder   const SourceInfo &E = S.Current->getSource(OpPC);
60a07aba5dSTimm Baeder   S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
61a07aba5dSTimm Baeder   S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
62a07aba5dSTimm Baeder }
63a07aba5dSTimm Baeder 
64a07aba5dSTimm Baeder static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
65a07aba5dSTimm Baeder                                      const ValueDecl *VD);
66a07aba5dSTimm Baeder static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC,
67a07aba5dSTimm Baeder                                 const ValueDecl *D) {
68a07aba5dSTimm Baeder   const SourceInfo &E = S.Current->getSource(OpPC);
69a07aba5dSTimm Baeder 
70a07aba5dSTimm Baeder   if (isa<ParmVarDecl>(D)) {
71*51c7338cSTimm Baeder     if (D->getType()->isReferenceType())
72*51c7338cSTimm Baeder       return false;
73*51c7338cSTimm Baeder 
74a07aba5dSTimm Baeder     if (S.getLangOpts().CPlusPlus11) {
75a07aba5dSTimm Baeder       S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
76a07aba5dSTimm Baeder       S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
77a07aba5dSTimm Baeder     } else {
78a07aba5dSTimm Baeder       S.FFDiag(E);
79a07aba5dSTimm Baeder     }
80a07aba5dSTimm Baeder     return false;
81a07aba5dSTimm Baeder   }
82a07aba5dSTimm Baeder 
8346ad7ff4STimm Baeder   if (!D->getType().isConstQualified()) {
84a07aba5dSTimm Baeder     diagnoseNonConstVariable(S, OpPC, D);
8546ad7ff4STimm Baeder   } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
8646ad7ff4STimm Baeder     if (!VD->getAnyInitializer()) {
87a07aba5dSTimm Baeder       diagnoseMissingInitializer(S, OpPC, VD);
8846ad7ff4STimm Baeder     } else {
8946ad7ff4STimm Baeder       const SourceInfo &Loc = S.Current->getSource(OpPC);
9046ad7ff4STimm Baeder       S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
9146ad7ff4STimm Baeder       S.Note(VD->getLocation(), diag::note_declared_at);
9246ad7ff4STimm Baeder     }
9346ad7ff4STimm Baeder   }
94a07aba5dSTimm Baeder 
95a07aba5dSTimm Baeder   return false;
96a07aba5dSTimm Baeder }
97a07aba5dSTimm Baeder 
98a07aba5dSTimm Baeder static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
99a07aba5dSTimm Baeder                                      const ValueDecl *VD) {
100a07aba5dSTimm Baeder   const SourceInfo &Loc = S.Current->getSource(OpPC);
101c57b9f5aSTimm Baeder   if (!S.getLangOpts().CPlusPlus) {
102c57b9f5aSTimm Baeder     S.FFDiag(Loc);
103c57b9f5aSTimm Baeder     return;
104c57b9f5aSTimm Baeder   }
105c57b9f5aSTimm Baeder 
106a07aba5dSTimm Baeder   if (const auto *VarD = dyn_cast<VarDecl>(VD);
107a07aba5dSTimm Baeder       VarD && VarD->getType().isConstQualified() &&
108a07aba5dSTimm Baeder       !VarD->getAnyInitializer()) {
109a07aba5dSTimm Baeder     diagnoseMissingInitializer(S, OpPC, VD);
110a07aba5dSTimm Baeder     return;
111a07aba5dSTimm Baeder   }
112a07aba5dSTimm Baeder 
113a07aba5dSTimm Baeder   // Rather random, but this is to match the diagnostic output of the current
114a07aba5dSTimm Baeder   // interpreter.
115a07aba5dSTimm Baeder   if (isa<ObjCIvarDecl>(VD))
116a07aba5dSTimm Baeder     return;
117a07aba5dSTimm Baeder 
118a07aba5dSTimm Baeder   if (VD->getType()->isIntegralOrEnumerationType()) {
119a07aba5dSTimm Baeder     S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
120a07aba5dSTimm Baeder     S.Note(VD->getLocation(), diag::note_declared_at);
121a07aba5dSTimm Baeder     return;
122a07aba5dSTimm Baeder   }
123a07aba5dSTimm Baeder 
124a07aba5dSTimm Baeder   S.FFDiag(Loc,
125a07aba5dSTimm Baeder            S.getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
126a07aba5dSTimm Baeder                                        : diag::note_constexpr_ltor_non_integral,
127a07aba5dSTimm Baeder            1)
128a07aba5dSTimm Baeder       << VD << VD->getType();
129a07aba5dSTimm Baeder   S.Note(VD->getLocation(), diag::note_declared_at);
130a07aba5dSTimm Baeder }
131a07aba5dSTimm Baeder 
132a07aba5dSTimm Baeder static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
133a07aba5dSTimm Baeder                         AccessKinds AK) {
134a07aba5dSTimm Baeder   if (Ptr.isActive())
135a07aba5dSTimm Baeder     return true;
136a07aba5dSTimm Baeder 
137a07aba5dSTimm Baeder   assert(Ptr.inUnion());
138a07aba5dSTimm Baeder   assert(Ptr.isField() && Ptr.getField());
139a07aba5dSTimm Baeder 
140a07aba5dSTimm Baeder   Pointer U = Ptr.getBase();
141a07aba5dSTimm Baeder   Pointer C = Ptr;
142a07aba5dSTimm Baeder   while (!U.isRoot() && U.inUnion() && !U.isActive()) {
143a07aba5dSTimm Baeder     if (U.getField())
144a07aba5dSTimm Baeder       C = U;
145a07aba5dSTimm Baeder     U = U.getBase();
146a07aba5dSTimm Baeder   }
147a07aba5dSTimm Baeder   assert(C.isField());
148a07aba5dSTimm Baeder 
149a07aba5dSTimm Baeder   // Get the inactive field descriptor.
150a07aba5dSTimm Baeder   const FieldDecl *InactiveField = C.getField();
151a07aba5dSTimm Baeder   assert(InactiveField);
152a07aba5dSTimm Baeder 
153a07aba5dSTimm Baeder   // Consider:
154a07aba5dSTimm Baeder   // union U {
155a07aba5dSTimm Baeder   //   struct {
156a07aba5dSTimm Baeder   //     int x;
157a07aba5dSTimm Baeder   //     int y;
158a07aba5dSTimm Baeder   //   } a;
159a07aba5dSTimm Baeder   // }
160a07aba5dSTimm Baeder   //
161a07aba5dSTimm Baeder   // When activating x, we will also activate a. If we now try to read
162a07aba5dSTimm Baeder   // from y, we will get to CheckActive, because y is not active. In that
163a07aba5dSTimm Baeder   // case, our U will be a (not a union). We return here and let later code
164a07aba5dSTimm Baeder   // handle this.
165a07aba5dSTimm Baeder   if (!U.getFieldDesc()->isUnion())
166a07aba5dSTimm Baeder     return true;
167a07aba5dSTimm Baeder 
168a07aba5dSTimm Baeder   // Find the active field of the union.
169a07aba5dSTimm Baeder   const Record *R = U.getRecord();
170a07aba5dSTimm Baeder   assert(R && R->isUnion() && "Not a union");
171a07aba5dSTimm Baeder 
172a07aba5dSTimm Baeder   const FieldDecl *ActiveField = nullptr;
173a07aba5dSTimm Baeder   for (const Record::Field &F : R->fields()) {
174a07aba5dSTimm Baeder     const Pointer &Field = U.atField(F.Offset);
175a07aba5dSTimm Baeder     if (Field.isActive()) {
176a07aba5dSTimm Baeder       ActiveField = Field.getField();
177a07aba5dSTimm Baeder       break;
178a07aba5dSTimm Baeder     }
179a07aba5dSTimm Baeder   }
180a07aba5dSTimm Baeder 
181a07aba5dSTimm Baeder   const SourceInfo &Loc = S.Current->getSource(OpPC);
182a07aba5dSTimm Baeder   S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
183a07aba5dSTimm Baeder       << AK << InactiveField << !ActiveField << ActiveField;
184a07aba5dSTimm Baeder   return false;
185a07aba5dSTimm Baeder }
186a07aba5dSTimm Baeder 
187a07aba5dSTimm Baeder static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
188a07aba5dSTimm Baeder                            AccessKinds AK) {
189a07aba5dSTimm Baeder   if (auto ID = Ptr.getDeclID()) {
190a07aba5dSTimm Baeder     if (!Ptr.isStaticTemporary())
191a07aba5dSTimm Baeder       return true;
192a07aba5dSTimm Baeder 
193e4f3b56dSTimm Baeder     const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
194e4f3b56dSTimm Baeder         Ptr.getDeclDesc()->asExpr());
195e4f3b56dSTimm Baeder     if (!MTE)
196a07aba5dSTimm Baeder       return true;
197a07aba5dSTimm Baeder 
198e4f3b56dSTimm Baeder     // FIXME(perf): Since we do this check on every Load from a static
199e4f3b56dSTimm Baeder     // temporary, it might make sense to cache the value of the
200e4f3b56dSTimm Baeder     // isUsableInConstantExpressions call.
201e4f3b56dSTimm Baeder     if (!MTE->isUsableInConstantExpressions(S.getASTContext()) &&
202e4f3b56dSTimm Baeder         Ptr.block()->getEvalID() != S.Ctx.getEvalID()) {
203a07aba5dSTimm Baeder       const SourceInfo &E = S.Current->getSource(OpPC);
204a07aba5dSTimm Baeder       S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
205a07aba5dSTimm Baeder       S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
206a07aba5dSTimm Baeder       return false;
207a07aba5dSTimm Baeder     }
208e4f3b56dSTimm Baeder   }
209a07aba5dSTimm Baeder   return true;
210a07aba5dSTimm Baeder }
211a07aba5dSTimm Baeder 
212a07aba5dSTimm Baeder static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
213a07aba5dSTimm Baeder   if (auto ID = Ptr.getDeclID()) {
214a07aba5dSTimm Baeder     if (!Ptr.isStatic())
215a07aba5dSTimm Baeder       return true;
216a07aba5dSTimm Baeder 
217a07aba5dSTimm Baeder     if (S.P.getCurrentDecl() == ID)
218a07aba5dSTimm Baeder       return true;
219a07aba5dSTimm Baeder 
220a07aba5dSTimm Baeder     S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
221a07aba5dSTimm Baeder     return false;
222a07aba5dSTimm Baeder   }
223a07aba5dSTimm Baeder   return true;
224a07aba5dSTimm Baeder }
225a07aba5dSTimm Baeder 
226a07aba5dSTimm Baeder namespace clang {
227a07aba5dSTimm Baeder namespace interp {
228a07aba5dSTimm Baeder static void popArg(InterpState &S, const Expr *Arg) {
229a07aba5dSTimm Baeder   PrimType Ty = S.getContext().classify(Arg).value_or(PT_Ptr);
230a07aba5dSTimm Baeder   TYPE_SWITCH(Ty, S.Stk.discard<T>());
231a07aba5dSTimm Baeder }
232a07aba5dSTimm Baeder 
23383fea8b8STimm Baeder void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
23483fea8b8STimm Baeder                               const Function *Func) {
235a07aba5dSTimm Baeder   assert(S.Current);
23683fea8b8STimm Baeder   assert(Func);
237a07aba5dSTimm Baeder 
23883fea8b8STimm Baeder   if (Func->isUnevaluatedBuiltin())
239a07aba5dSTimm Baeder     return;
240a07aba5dSTimm Baeder 
241a07aba5dSTimm Baeder   // Some builtin functions require us to only look at the call site, since
242a07aba5dSTimm Baeder   // the classified parameter types do not match.
24383fea8b8STimm Baeder   if (unsigned BID = Func->getBuiltinID();
244e4cf0a04STimm Baeder       BID && S.getASTContext().BuiltinInfo.hasCustomTypechecking(BID)) {
245a07aba5dSTimm Baeder     const auto *CE =
246a07aba5dSTimm Baeder         cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
247a07aba5dSTimm Baeder     for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
248a07aba5dSTimm Baeder       const Expr *A = CE->getArg(I);
249a07aba5dSTimm Baeder       popArg(S, A);
250a07aba5dSTimm Baeder     }
251a07aba5dSTimm Baeder     return;
252a07aba5dSTimm Baeder   }
253a07aba5dSTimm Baeder 
25483fea8b8STimm Baeder   if (S.Current->Caller && Func->isVariadic()) {
255a07aba5dSTimm Baeder     // CallExpr we're look for is at the return PC of the current function, i.e.
256a07aba5dSTimm Baeder     // in the caller.
257a07aba5dSTimm Baeder     // This code path should be executed very rarely.
258a07aba5dSTimm Baeder     unsigned NumVarArgs;
259a07aba5dSTimm Baeder     const Expr *const *Args = nullptr;
260a07aba5dSTimm Baeder     unsigned NumArgs = 0;
261a07aba5dSTimm Baeder     const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
262a07aba5dSTimm Baeder     if (const auto *CE = dyn_cast<CallExpr>(CallSite)) {
263a07aba5dSTimm Baeder       Args = CE->getArgs();
264a07aba5dSTimm Baeder       NumArgs = CE->getNumArgs();
265a07aba5dSTimm Baeder     } else if (const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
266a07aba5dSTimm Baeder       Args = CE->getArgs();
267a07aba5dSTimm Baeder       NumArgs = CE->getNumArgs();
268a07aba5dSTimm Baeder     } else
269a07aba5dSTimm Baeder       assert(false && "Can't get arguments from that expression type");
270a07aba5dSTimm Baeder 
27183fea8b8STimm Baeder     assert(NumArgs >= Func->getNumWrittenParams());
27283fea8b8STimm Baeder     NumVarArgs = NumArgs - (Func->getNumWrittenParams() +
273a07aba5dSTimm Baeder                             isa<CXXOperatorCallExpr>(CallSite));
274a07aba5dSTimm Baeder     for (unsigned I = 0; I != NumVarArgs; ++I) {
275a07aba5dSTimm Baeder       const Expr *A = Args[NumArgs - 1 - I];
276a07aba5dSTimm Baeder       popArg(S, A);
277a07aba5dSTimm Baeder     }
278a07aba5dSTimm Baeder   }
279a07aba5dSTimm Baeder 
280a07aba5dSTimm Baeder   // And in any case, remove the fixed parameters (the non-variadic ones)
281a07aba5dSTimm Baeder   // at the end.
28283fea8b8STimm Baeder   for (PrimType Ty : Func->args_reverse())
28383fea8b8STimm Baeder     TYPE_SWITCH(Ty, S.Stk.discard<T>());
284a07aba5dSTimm Baeder }
285a07aba5dSTimm Baeder 
286a07aba5dSTimm Baeder bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
287a07aba5dSTimm Baeder   if (!Ptr.isExtern())
288a07aba5dSTimm Baeder     return true;
289a07aba5dSTimm Baeder 
290a07aba5dSTimm Baeder   if (Ptr.isInitialized() ||
291a07aba5dSTimm Baeder       (Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl))
292a07aba5dSTimm Baeder     return true;
293a07aba5dSTimm Baeder 
294a07aba5dSTimm Baeder   if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
295a07aba5dSTimm Baeder     const auto *VD = Ptr.getDeclDesc()->asValueDecl();
296a07aba5dSTimm Baeder     diagnoseNonConstVariable(S, OpPC, VD);
297a07aba5dSTimm Baeder   }
298a07aba5dSTimm Baeder   return false;
299a07aba5dSTimm Baeder }
300a07aba5dSTimm Baeder 
301a07aba5dSTimm Baeder bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
302a07aba5dSTimm Baeder   if (!Ptr.isUnknownSizeArray())
303a07aba5dSTimm Baeder     return true;
304a07aba5dSTimm Baeder   const SourceInfo &E = S.Current->getSource(OpPC);
305a07aba5dSTimm Baeder   S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
306a07aba5dSTimm Baeder   return false;
307a07aba5dSTimm Baeder }
308a07aba5dSTimm Baeder 
309a07aba5dSTimm Baeder bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
310a07aba5dSTimm Baeder                AccessKinds AK) {
311a07aba5dSTimm Baeder   if (Ptr.isZero()) {
312a07aba5dSTimm Baeder     const auto &Src = S.Current->getSource(OpPC);
313a07aba5dSTimm Baeder 
314a07aba5dSTimm Baeder     if (Ptr.isField())
315a07aba5dSTimm Baeder       S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
316a07aba5dSTimm Baeder     else
317a07aba5dSTimm Baeder       S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
318a07aba5dSTimm Baeder 
319a07aba5dSTimm Baeder     return false;
320a07aba5dSTimm Baeder   }
321a07aba5dSTimm Baeder 
322a07aba5dSTimm Baeder   if (!Ptr.isLive()) {
323a07aba5dSTimm Baeder     const auto &Src = S.Current->getSource(OpPC);
324a07aba5dSTimm Baeder 
325df11ee21STimm Baeder     if (Ptr.isDynamic()) {
326df11ee21STimm Baeder       S.FFDiag(Src, diag::note_constexpr_access_deleted_object) << AK;
3271be64c27STimm Baeder     } else if (!S.checkingPotentialConstantExpression()) {
328df11ee21STimm Baeder       bool IsTemp = Ptr.isTemporary();
329a07aba5dSTimm Baeder       S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
330a07aba5dSTimm Baeder 
331a07aba5dSTimm Baeder       if (IsTemp)
332a07aba5dSTimm Baeder         S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
333a07aba5dSTimm Baeder       else
334a07aba5dSTimm Baeder         S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
335df11ee21STimm Baeder     }
336a07aba5dSTimm Baeder 
337a07aba5dSTimm Baeder     return false;
338a07aba5dSTimm Baeder   }
339a07aba5dSTimm Baeder 
340a07aba5dSTimm Baeder   return true;
341a07aba5dSTimm Baeder }
342a07aba5dSTimm Baeder 
343a07aba5dSTimm Baeder bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
344a07aba5dSTimm Baeder   assert(Desc);
345a07aba5dSTimm Baeder 
346cb608cc5STimm Baeder   const auto *D = Desc->asVarDecl();
347cb608cc5STimm Baeder   if (!D || !D->hasGlobalStorage())
348a07aba5dSTimm Baeder     return true;
349a07aba5dSTimm Baeder 
350cb608cc5STimm Baeder   if (D == S.EvaluatingDecl)
351a07aba5dSTimm Baeder     return true;
352a07aba5dSTimm Baeder 
353cb608cc5STimm Baeder   if (D->isConstexpr())
354cb608cc5STimm Baeder     return true;
355a07aba5dSTimm Baeder 
3568079a2c5Syronglin   // If we're evaluating the initializer for a constexpr variable in C23, we may
3578079a2c5Syronglin   // only read other contexpr variables. Abort here since this one isn't
3588079a2c5Syronglin   // constexpr.
3598079a2c5Syronglin   if (const auto *VD = dyn_cast_if_present<VarDecl>(S.EvaluatingDecl);
3608079a2c5Syronglin       VD && VD->isConstexpr() && S.getLangOpts().C23)
3618079a2c5Syronglin     return Invalid(S, OpPC);
3628079a2c5Syronglin 
363cb608cc5STimm Baeder   QualType T = D->getType();
364cb608cc5STimm Baeder   bool IsConstant = T.isConstant(S.getASTContext());
365cb608cc5STimm Baeder   if (T->isIntegralOrEnumerationType()) {
366cb608cc5STimm Baeder     if (!IsConstant) {
367a07aba5dSTimm Baeder       diagnoseNonConstVariable(S, OpPC, D);
368a07aba5dSTimm Baeder       return false;
369a07aba5dSTimm Baeder     }
370a07aba5dSTimm Baeder     return true;
371a07aba5dSTimm Baeder   }
372a07aba5dSTimm Baeder 
373cb608cc5STimm Baeder   if (IsConstant) {
374cb608cc5STimm Baeder     if (S.getLangOpts().CPlusPlus) {
375cb608cc5STimm Baeder       S.CCEDiag(S.Current->getLocation(OpPC),
376cb608cc5STimm Baeder                 S.getLangOpts().CPlusPlus11
377cb608cc5STimm Baeder                     ? diag::note_constexpr_ltor_non_constexpr
378cb608cc5STimm Baeder                     : diag::note_constexpr_ltor_non_integral,
379cb608cc5STimm Baeder                 1)
380cb608cc5STimm Baeder           << D << T;
381cb608cc5STimm Baeder       S.Note(D->getLocation(), diag::note_declared_at);
382cb608cc5STimm Baeder     } else {
383cb608cc5STimm Baeder       S.CCEDiag(S.Current->getLocation(OpPC));
384cb608cc5STimm Baeder     }
385cb608cc5STimm Baeder     return true;
386cb608cc5STimm Baeder   }
387cb608cc5STimm Baeder 
388cb608cc5STimm Baeder   if (T->isPointerOrReferenceType()) {
389cb608cc5STimm Baeder     if (!T->getPointeeType().isConstant(S.getASTContext()) ||
390cb608cc5STimm Baeder         !S.getLangOpts().CPlusPlus11) {
391cb608cc5STimm Baeder       diagnoseNonConstVariable(S, OpPC, D);
392cb608cc5STimm Baeder       return false;
393cb608cc5STimm Baeder     }
394cb608cc5STimm Baeder     return true;
395cb608cc5STimm Baeder   }
396cb608cc5STimm Baeder 
397cb608cc5STimm Baeder   diagnoseNonConstVariable(S, OpPC, D);
398cb608cc5STimm Baeder   return false;
399cb608cc5STimm Baeder }
400cb608cc5STimm Baeder 
401a07aba5dSTimm Baeder static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
402d5b42db0STimm Baeder   if (!Ptr.isStatic() || !Ptr.isBlockPointer())
403a07aba5dSTimm Baeder     return true;
404a07aba5dSTimm Baeder   return CheckConstant(S, OpPC, Ptr.getDeclDesc());
405a07aba5dSTimm Baeder }
406a07aba5dSTimm Baeder 
407a07aba5dSTimm Baeder bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
408a07aba5dSTimm Baeder                CheckSubobjectKind CSK) {
409a07aba5dSTimm Baeder   if (!Ptr.isZero())
410a07aba5dSTimm Baeder     return true;
411a07aba5dSTimm Baeder   const SourceInfo &Loc = S.Current->getSource(OpPC);
412a07aba5dSTimm Baeder   S.FFDiag(Loc, diag::note_constexpr_null_subobject)
413a07aba5dSTimm Baeder       << CSK << S.Current->getRange(OpPC);
414a07aba5dSTimm Baeder 
415a07aba5dSTimm Baeder   return false;
416a07aba5dSTimm Baeder }
417a07aba5dSTimm Baeder 
418a07aba5dSTimm Baeder bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
419a07aba5dSTimm Baeder                 AccessKinds AK) {
420a07aba5dSTimm Baeder   if (!Ptr.isOnePastEnd())
421a07aba5dSTimm Baeder     return true;
422d70f54f2STimm Baeder   if (S.getLangOpts().CPlusPlus) {
423a07aba5dSTimm Baeder     const SourceInfo &Loc = S.Current->getSource(OpPC);
424a07aba5dSTimm Baeder     S.FFDiag(Loc, diag::note_constexpr_access_past_end)
425a07aba5dSTimm Baeder         << AK << S.Current->getRange(OpPC);
426d70f54f2STimm Baeder   }
427a07aba5dSTimm Baeder   return false;
428a07aba5dSTimm Baeder }
429a07aba5dSTimm Baeder 
430a07aba5dSTimm Baeder bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
431a07aba5dSTimm Baeder                 CheckSubobjectKind CSK) {
432a07aba5dSTimm Baeder   if (!Ptr.isElementPastEnd())
433a07aba5dSTimm Baeder     return true;
434a07aba5dSTimm Baeder   const SourceInfo &Loc = S.Current->getSource(OpPC);
435a07aba5dSTimm Baeder   S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
436a07aba5dSTimm Baeder       << CSK << S.Current->getRange(OpPC);
437a07aba5dSTimm Baeder   return false;
438a07aba5dSTimm Baeder }
439a07aba5dSTimm Baeder 
440a07aba5dSTimm Baeder bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
441a07aba5dSTimm Baeder                     CheckSubobjectKind CSK) {
442a07aba5dSTimm Baeder   if (!Ptr.isOnePastEnd())
443a07aba5dSTimm Baeder     return true;
444a07aba5dSTimm Baeder 
445a07aba5dSTimm Baeder   const SourceInfo &Loc = S.Current->getSource(OpPC);
446a07aba5dSTimm Baeder   S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
447a07aba5dSTimm Baeder       << CSK << S.Current->getRange(OpPC);
448a07aba5dSTimm Baeder   return false;
449a07aba5dSTimm Baeder }
450a07aba5dSTimm Baeder 
451a07aba5dSTimm Baeder bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
452a07aba5dSTimm Baeder                    uint32_t Offset) {
453a07aba5dSTimm Baeder   uint32_t MinOffset = Ptr.getDeclDesc()->getMetadataSize();
454a07aba5dSTimm Baeder   uint32_t PtrOffset = Ptr.getByteOffset();
455a07aba5dSTimm Baeder 
456a07aba5dSTimm Baeder   // We subtract Offset from PtrOffset. The result must be at least
457a07aba5dSTimm Baeder   // MinOffset.
458a07aba5dSTimm Baeder   if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
459a07aba5dSTimm Baeder     return true;
460a07aba5dSTimm Baeder 
461a07aba5dSTimm Baeder   const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
462a07aba5dSTimm Baeder   QualType TargetQT = E->getType()->getPointeeType();
463a07aba5dSTimm Baeder   QualType MostDerivedQT = Ptr.getDeclPtr().getType();
464a07aba5dSTimm Baeder 
465a07aba5dSTimm Baeder   S.CCEDiag(E, diag::note_constexpr_invalid_downcast)
466a07aba5dSTimm Baeder       << MostDerivedQT << TargetQT;
467a07aba5dSTimm Baeder 
468a07aba5dSTimm Baeder   return false;
469a07aba5dSTimm Baeder }
470a07aba5dSTimm Baeder 
471a07aba5dSTimm Baeder bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
472a07aba5dSTimm Baeder   assert(Ptr.isLive() && "Pointer is not live");
473a07aba5dSTimm Baeder   if (!Ptr.isConst() || Ptr.isMutable())
474a07aba5dSTimm Baeder     return true;
475a07aba5dSTimm Baeder 
476a07aba5dSTimm Baeder   // The This pointer is writable in constructors and destructors,
477a07aba5dSTimm Baeder   // even if isConst() returns true.
478a07aba5dSTimm Baeder   // TODO(perf): We could be hitting this code path quite a lot in complex
479a07aba5dSTimm Baeder   // constructors. Is there a better way to do this?
480a07aba5dSTimm Baeder   if (S.Current->getFunction()) {
481a07aba5dSTimm Baeder     for (const InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) {
482a07aba5dSTimm Baeder       if (const Function *Func = Frame->getFunction();
483a07aba5dSTimm Baeder           Func && (Func->isConstructor() || Func->isDestructor()) &&
484a07aba5dSTimm Baeder           Ptr.block() == Frame->getThis().block()) {
485a07aba5dSTimm Baeder         return true;
486a07aba5dSTimm Baeder       }
487a07aba5dSTimm Baeder     }
488a07aba5dSTimm Baeder   }
489a07aba5dSTimm Baeder 
490a07aba5dSTimm Baeder   if (!Ptr.isBlockPointer())
491a07aba5dSTimm Baeder     return false;
492a07aba5dSTimm Baeder 
493a07aba5dSTimm Baeder   const QualType Ty = Ptr.getType();
494a07aba5dSTimm Baeder   const SourceInfo &Loc = S.Current->getSource(OpPC);
495a07aba5dSTimm Baeder   S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
496a07aba5dSTimm Baeder   return false;
497a07aba5dSTimm Baeder }
498a07aba5dSTimm Baeder 
499a07aba5dSTimm Baeder bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
500a07aba5dSTimm Baeder   assert(Ptr.isLive() && "Pointer is not live");
501a07aba5dSTimm Baeder   if (!Ptr.isMutable())
502a07aba5dSTimm Baeder     return true;
503a07aba5dSTimm Baeder 
504a07aba5dSTimm Baeder   // In C++14 onwards, it is permitted to read a mutable member whose
505a07aba5dSTimm Baeder   // lifetime began within the evaluation.
506a07aba5dSTimm Baeder   if (S.getLangOpts().CPlusPlus14 &&
507a07aba5dSTimm Baeder       Ptr.block()->getEvalID() == S.Ctx.getEvalID())
508a07aba5dSTimm Baeder     return true;
509a07aba5dSTimm Baeder 
510a07aba5dSTimm Baeder   const SourceInfo &Loc = S.Current->getSource(OpPC);
511a07aba5dSTimm Baeder   const FieldDecl *Field = Ptr.getField();
512a07aba5dSTimm Baeder   S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
513a07aba5dSTimm Baeder   S.Note(Field->getLocation(), diag::note_declared_at);
514a07aba5dSTimm Baeder   return false;
515a07aba5dSTimm Baeder }
516a07aba5dSTimm Baeder 
5177b88e753STimm Baeder static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
518a07aba5dSTimm Baeder                           AccessKinds AK) {
519a07aba5dSTimm Baeder   assert(Ptr.isLive());
520a07aba5dSTimm Baeder 
521a07aba5dSTimm Baeder   // FIXME: This check here might be kinda expensive. Maybe it would be better
522a07aba5dSTimm Baeder   // to have another field in InlineDescriptor for this?
523a07aba5dSTimm Baeder   if (!Ptr.isBlockPointer())
524a07aba5dSTimm Baeder     return true;
525a07aba5dSTimm Baeder 
526a07aba5dSTimm Baeder   QualType PtrType = Ptr.getType();
527a07aba5dSTimm Baeder   if (!PtrType.isVolatileQualified())
528a07aba5dSTimm Baeder     return true;
529a07aba5dSTimm Baeder 
530a07aba5dSTimm Baeder   const SourceInfo &Loc = S.Current->getSource(OpPC);
531a07aba5dSTimm Baeder   if (S.getLangOpts().CPlusPlus)
532a07aba5dSTimm Baeder     S.FFDiag(Loc, diag::note_constexpr_access_volatile_type) << AK << PtrType;
533a07aba5dSTimm Baeder   else
534a07aba5dSTimm Baeder     S.FFDiag(Loc);
535a07aba5dSTimm Baeder   return false;
536a07aba5dSTimm Baeder }
537a07aba5dSTimm Baeder 
538a07aba5dSTimm Baeder bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
539a07aba5dSTimm Baeder                       AccessKinds AK) {
540a07aba5dSTimm Baeder   assert(Ptr.isLive());
541a07aba5dSTimm Baeder 
542a07aba5dSTimm Baeder   if (Ptr.isInitialized())
543a07aba5dSTimm Baeder     return true;
544a07aba5dSTimm Baeder 
545a07aba5dSTimm Baeder   if (const auto *VD = Ptr.getDeclDesc()->asVarDecl();
546d70f54f2STimm Baeder       VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
547a07aba5dSTimm Baeder     const SourceInfo &Loc = S.Current->getSource(OpPC);
548a07aba5dSTimm Baeder     if (VD->getAnyInitializer()) {
549a07aba5dSTimm Baeder       S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
550a07aba5dSTimm Baeder       S.Note(VD->getLocation(), diag::note_declared_at);
551a07aba5dSTimm Baeder     } else {
552a07aba5dSTimm Baeder       diagnoseMissingInitializer(S, OpPC, VD);
553a07aba5dSTimm Baeder     }
554a07aba5dSTimm Baeder     return false;
555a07aba5dSTimm Baeder   }
556a07aba5dSTimm Baeder 
557a07aba5dSTimm Baeder   if (!S.checkingPotentialConstantExpression()) {
558a07aba5dSTimm Baeder     S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
559a07aba5dSTimm Baeder         << AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
560a07aba5dSTimm Baeder   }
561a07aba5dSTimm Baeder   return false;
562a07aba5dSTimm Baeder }
563a07aba5dSTimm Baeder 
564a07aba5dSTimm Baeder bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
565a07aba5dSTimm Baeder   if (Ptr.isInitialized())
566a07aba5dSTimm Baeder     return true;
567a07aba5dSTimm Baeder 
568a07aba5dSTimm Baeder   assert(S.getLangOpts().CPlusPlus);
569a07aba5dSTimm Baeder   const auto *VD = cast<VarDecl>(Ptr.getDeclDesc()->asValueDecl());
570a07aba5dSTimm Baeder   if ((!VD->hasConstantInitialization() &&
571d9e72860Syronglin        VD->mightBeUsableInConstantExpressions(S.getASTContext())) ||
572a07aba5dSTimm Baeder       (S.getLangOpts().OpenCL && !S.getLangOpts().CPlusPlus11 &&
573d9e72860Syronglin        !VD->hasICEInitializer(S.getASTContext()))) {
574a07aba5dSTimm Baeder     const SourceInfo &Loc = S.Current->getSource(OpPC);
575a07aba5dSTimm Baeder     S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
576a07aba5dSTimm Baeder     S.Note(VD->getLocation(), diag::note_declared_at);
577a07aba5dSTimm Baeder   }
578a07aba5dSTimm Baeder   return false;
579a07aba5dSTimm Baeder }
580a07aba5dSTimm Baeder 
581d267daa9STimm Baeder static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
582d267daa9STimm Baeder   if (!Ptr.isWeak())
583d267daa9STimm Baeder     return true;
584d267daa9STimm Baeder 
585d267daa9STimm Baeder   const auto *VD = Ptr.getDeclDesc()->asVarDecl();
586d267daa9STimm Baeder   assert(VD);
587d267daa9STimm Baeder   S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_var_init_weak)
588d267daa9STimm Baeder       << VD;
589d267daa9STimm Baeder   S.Note(VD->getLocation(), diag::note_declared_at);
590d267daa9STimm Baeder 
591d267daa9STimm Baeder   return false;
592d267daa9STimm Baeder }
593d267daa9STimm Baeder 
594a07aba5dSTimm Baeder bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
595a07aba5dSTimm Baeder                AccessKinds AK) {
596a07aba5dSTimm Baeder   if (!CheckLive(S, OpPC, Ptr, AK))
597a07aba5dSTimm Baeder     return false;
598a07aba5dSTimm Baeder   if (!CheckConstant(S, OpPC, Ptr))
599a07aba5dSTimm Baeder     return false;
600a07aba5dSTimm Baeder   if (!CheckDummy(S, OpPC, Ptr, AK))
601a07aba5dSTimm Baeder     return false;
602a07aba5dSTimm Baeder   if (!CheckExtern(S, OpPC, Ptr))
603a07aba5dSTimm Baeder     return false;
604a07aba5dSTimm Baeder   if (!CheckRange(S, OpPC, Ptr, AK))
605a07aba5dSTimm Baeder     return false;
606a07aba5dSTimm Baeder   if (!CheckActive(S, OpPC, Ptr, AK))
607a07aba5dSTimm Baeder     return false;
608a07aba5dSTimm Baeder   if (!CheckInitialized(S, OpPC, Ptr, AK))
609a07aba5dSTimm Baeder     return false;
610a07aba5dSTimm Baeder   if (!CheckTemporary(S, OpPC, Ptr, AK))
611a07aba5dSTimm Baeder     return false;
612d267daa9STimm Baeder   if (!CheckWeak(S, OpPC, Ptr))
613d267daa9STimm Baeder     return false;
614a07aba5dSTimm Baeder   if (!CheckMutable(S, OpPC, Ptr))
615a07aba5dSTimm Baeder     return false;
616a07aba5dSTimm Baeder   if (!CheckVolatile(S, OpPC, Ptr, AK))
617a07aba5dSTimm Baeder     return false;
618a07aba5dSTimm Baeder   return true;
619a07aba5dSTimm Baeder }
620a07aba5dSTimm Baeder 
621a14c7309STimm Baeder /// This is not used by any of the opcodes directly. It's used by
622a14c7309STimm Baeder /// EvalEmitter to do the final lvalue-to-rvalue conversion.
623a14c7309STimm Baeder bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
624a14c7309STimm Baeder   if (!CheckLive(S, OpPC, Ptr, AK_Read))
625a14c7309STimm Baeder     return false;
626a14c7309STimm Baeder   if (!CheckConstant(S, OpPC, Ptr))
627a14c7309STimm Baeder     return false;
628a14c7309STimm Baeder 
629a14c7309STimm Baeder   if (!CheckDummy(S, OpPC, Ptr, AK_Read))
630a14c7309STimm Baeder     return false;
631a14c7309STimm Baeder   if (!CheckExtern(S, OpPC, Ptr))
632a14c7309STimm Baeder     return false;
633a14c7309STimm Baeder   if (!CheckRange(S, OpPC, Ptr, AK_Read))
634a14c7309STimm Baeder     return false;
635a14c7309STimm Baeder   if (!CheckActive(S, OpPC, Ptr, AK_Read))
636a14c7309STimm Baeder     return false;
637a14c7309STimm Baeder   if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
638a14c7309STimm Baeder     return false;
639a14c7309STimm Baeder   if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
640a14c7309STimm Baeder     return false;
64197aa8cc9STimm Baeder   if (!CheckWeak(S, OpPC, Ptr))
64297aa8cc9STimm Baeder     return false;
643a14c7309STimm Baeder   if (!CheckMutable(S, OpPC, Ptr))
644a14c7309STimm Baeder     return false;
645a14c7309STimm Baeder   return true;
646a14c7309STimm Baeder }
647a14c7309STimm Baeder 
648a07aba5dSTimm Baeder bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
649a07aba5dSTimm Baeder   if (!CheckLive(S, OpPC, Ptr, AK_Assign))
650a07aba5dSTimm Baeder     return false;
651a07aba5dSTimm Baeder   if (!CheckDummy(S, OpPC, Ptr, AK_Assign))
652a07aba5dSTimm Baeder     return false;
653a07aba5dSTimm Baeder   if (!CheckExtern(S, OpPC, Ptr))
654a07aba5dSTimm Baeder     return false;
655a07aba5dSTimm Baeder   if (!CheckRange(S, OpPC, Ptr, AK_Assign))
656a07aba5dSTimm Baeder     return false;
657a07aba5dSTimm Baeder   if (!CheckGlobal(S, OpPC, Ptr))
658a07aba5dSTimm Baeder     return false;
659a07aba5dSTimm Baeder   if (!CheckConst(S, OpPC, Ptr))
660a07aba5dSTimm Baeder     return false;
661a07aba5dSTimm Baeder   return true;
662a07aba5dSTimm Baeder }
663a07aba5dSTimm Baeder 
664a07aba5dSTimm Baeder bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
665a07aba5dSTimm Baeder   if (!CheckLive(S, OpPC, Ptr, AK_MemberCall))
666a07aba5dSTimm Baeder     return false;
667a07aba5dSTimm Baeder   if (!Ptr.isDummy()) {
668a07aba5dSTimm Baeder     if (!CheckExtern(S, OpPC, Ptr))
669a07aba5dSTimm Baeder       return false;
670a07aba5dSTimm Baeder     if (!CheckRange(S, OpPC, Ptr, AK_MemberCall))
671a07aba5dSTimm Baeder       return false;
672a07aba5dSTimm Baeder   }
673a07aba5dSTimm Baeder   return true;
674a07aba5dSTimm Baeder }
675a07aba5dSTimm Baeder 
676a07aba5dSTimm Baeder bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
677a07aba5dSTimm Baeder   if (!CheckLive(S, OpPC, Ptr, AK_Assign))
678a07aba5dSTimm Baeder     return false;
679a07aba5dSTimm Baeder   if (!CheckRange(S, OpPC, Ptr, AK_Assign))
680a07aba5dSTimm Baeder     return false;
681a07aba5dSTimm Baeder   return true;
682a07aba5dSTimm Baeder }
683a07aba5dSTimm Baeder 
684a07aba5dSTimm Baeder bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
685a07aba5dSTimm Baeder 
686a07aba5dSTimm Baeder   if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
687a07aba5dSTimm Baeder     const SourceLocation &Loc = S.Current->getLocation(OpPC);
688a07aba5dSTimm Baeder     S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
689a07aba5dSTimm Baeder     return false;
690a07aba5dSTimm Baeder   }
691a07aba5dSTimm Baeder 
692a07aba5dSTimm Baeder   if (F->isConstexpr() && F->hasBody() &&
693a07aba5dSTimm Baeder       (F->getDecl()->isConstexpr() || F->getDecl()->hasAttr<MSConstexprAttr>()))
694a07aba5dSTimm Baeder     return true;
695a07aba5dSTimm Baeder 
696a07aba5dSTimm Baeder   // Implicitly constexpr.
697a07aba5dSTimm Baeder   if (F->isLambdaStaticInvoker())
698a07aba5dSTimm Baeder     return true;
699a07aba5dSTimm Baeder 
700a07aba5dSTimm Baeder   const SourceLocation &Loc = S.Current->getLocation(OpPC);
701a07aba5dSTimm Baeder   if (S.getLangOpts().CPlusPlus11) {
702a07aba5dSTimm Baeder     const FunctionDecl *DiagDecl = F->getDecl();
703a07aba5dSTimm Baeder 
704a07aba5dSTimm Baeder     // Invalid decls have been diagnosed before.
705a07aba5dSTimm Baeder     if (DiagDecl->isInvalidDecl())
706a07aba5dSTimm Baeder       return false;
707a07aba5dSTimm Baeder 
708a07aba5dSTimm Baeder     // If this function is not constexpr because it is an inherited
709a07aba5dSTimm Baeder     // non-constexpr constructor, diagnose that directly.
710a07aba5dSTimm Baeder     const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
711a07aba5dSTimm Baeder     if (CD && CD->isInheritingConstructor()) {
712a07aba5dSTimm Baeder       const auto *Inherited = CD->getInheritedConstructor().getConstructor();
713a07aba5dSTimm Baeder       if (!Inherited->isConstexpr())
714a07aba5dSTimm Baeder         DiagDecl = CD = Inherited;
715a07aba5dSTimm Baeder     }
716a07aba5dSTimm Baeder 
717a07aba5dSTimm Baeder     // FIXME: If DiagDecl is an implicitly-declared special member function
718a07aba5dSTimm Baeder     // or an inheriting constructor, we should be much more explicit about why
719a07aba5dSTimm Baeder     // it's not constexpr.
720a07aba5dSTimm Baeder     if (CD && CD->isInheritingConstructor()) {
721a07aba5dSTimm Baeder       S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
722a07aba5dSTimm Baeder           << CD->getInheritedConstructor().getConstructor()->getParent();
723a07aba5dSTimm Baeder       S.Note(DiagDecl->getLocation(), diag::note_declared_at);
724a07aba5dSTimm Baeder     } else {
725a07aba5dSTimm Baeder       // Don't emit anything if the function isn't defined and we're checking
726a07aba5dSTimm Baeder       // for a constant expression. It might be defined at the point we're
727a07aba5dSTimm Baeder       // actually calling it.
728a07aba5dSTimm Baeder       bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
729a07aba5dSTimm Baeder       if (!DiagDecl->isDefined() && !IsExtern && DiagDecl->isConstexpr() &&
730a07aba5dSTimm Baeder           S.checkingPotentialConstantExpression())
731a07aba5dSTimm Baeder         return false;
732a07aba5dSTimm Baeder 
733a07aba5dSTimm Baeder       // If the declaration is defined, declared 'constexpr' _and_ has a body,
734a07aba5dSTimm Baeder       // the below diagnostic doesn't add anything useful.
735a07aba5dSTimm Baeder       if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
736a07aba5dSTimm Baeder           DiagDecl->hasBody())
737a07aba5dSTimm Baeder         return false;
738a07aba5dSTimm Baeder 
739a07aba5dSTimm Baeder       S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
740a07aba5dSTimm Baeder           << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
741a07aba5dSTimm Baeder 
742a07aba5dSTimm Baeder       if (DiagDecl->getDefinition())
743a07aba5dSTimm Baeder         S.Note(DiagDecl->getDefinition()->getLocation(),
744a07aba5dSTimm Baeder                diag::note_declared_at);
745a07aba5dSTimm Baeder       else
746a07aba5dSTimm Baeder         S.Note(DiagDecl->getLocation(), diag::note_declared_at);
747a07aba5dSTimm Baeder     }
748a07aba5dSTimm Baeder   } else {
749a07aba5dSTimm Baeder     S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
750a07aba5dSTimm Baeder   }
751a07aba5dSTimm Baeder 
752a07aba5dSTimm Baeder   return false;
753a07aba5dSTimm Baeder }
754a07aba5dSTimm Baeder 
755a07aba5dSTimm Baeder bool CheckCallDepth(InterpState &S, CodePtr OpPC) {
756a07aba5dSTimm Baeder   if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
757a07aba5dSTimm Baeder     S.FFDiag(S.Current->getSource(OpPC),
758a07aba5dSTimm Baeder              diag::note_constexpr_depth_limit_exceeded)
759a07aba5dSTimm Baeder         << S.getLangOpts().ConstexprCallDepth;
760a07aba5dSTimm Baeder     return false;
761a07aba5dSTimm Baeder   }
762a07aba5dSTimm Baeder 
763a07aba5dSTimm Baeder   return true;
764a07aba5dSTimm Baeder }
765a07aba5dSTimm Baeder 
766a07aba5dSTimm Baeder bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
767a07aba5dSTimm Baeder   if (!This.isZero())
768a07aba5dSTimm Baeder     return true;
769a07aba5dSTimm Baeder 
770a07aba5dSTimm Baeder   const SourceInfo &Loc = S.Current->getSource(OpPC);
771a07aba5dSTimm Baeder 
772a07aba5dSTimm Baeder   bool IsImplicit = false;
773a07aba5dSTimm Baeder   if (const auto *E = dyn_cast_if_present<CXXThisExpr>(Loc.asExpr()))
774a07aba5dSTimm Baeder     IsImplicit = E->isImplicit();
775a07aba5dSTimm Baeder 
776a07aba5dSTimm Baeder   if (S.getLangOpts().CPlusPlus11)
777a07aba5dSTimm Baeder     S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
778a07aba5dSTimm Baeder   else
779a07aba5dSTimm Baeder     S.FFDiag(Loc);
780a07aba5dSTimm Baeder 
781a07aba5dSTimm Baeder   return false;
782a07aba5dSTimm Baeder }
783a07aba5dSTimm Baeder 
784a07aba5dSTimm Baeder bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
785a07aba5dSTimm Baeder   if (!MD->isPureVirtual())
786a07aba5dSTimm Baeder     return true;
787a07aba5dSTimm Baeder   const SourceInfo &E = S.Current->getSource(OpPC);
788a07aba5dSTimm Baeder   S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
789a07aba5dSTimm Baeder   S.Note(MD->getLocation(), diag::note_declared_at);
790a07aba5dSTimm Baeder   return false;
791a07aba5dSTimm Baeder }
792a07aba5dSTimm Baeder 
793a07aba5dSTimm Baeder bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
7940f5f440fSTimm Baeder                       APFloat::opStatus Status, FPOptions FPO) {
795a07aba5dSTimm Baeder   // [expr.pre]p4:
796a07aba5dSTimm Baeder   //   If during the evaluation of an expression, the result is not
797a07aba5dSTimm Baeder   //   mathematically defined [...], the behavior is undefined.
798a07aba5dSTimm Baeder   // FIXME: C++ rules require us to not conform to IEEE 754 here.
799a07aba5dSTimm Baeder   if (Result.isNan()) {
8000f5f440fSTimm Baeder     const SourceInfo &E = S.Current->getSource(OpPC);
801a07aba5dSTimm Baeder     S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
802a07aba5dSTimm Baeder         << /*NaN=*/true << S.Current->getRange(OpPC);
803a07aba5dSTimm Baeder     return S.noteUndefinedBehavior();
804a07aba5dSTimm Baeder   }
805a07aba5dSTimm Baeder 
806a07aba5dSTimm Baeder   // In a constant context, assume that any dynamic rounding mode or FP
807a07aba5dSTimm Baeder   // exception state matches the default floating-point environment.
808a07aba5dSTimm Baeder   if (S.inConstantContext())
809a07aba5dSTimm Baeder     return true;
810a07aba5dSTimm Baeder 
811a07aba5dSTimm Baeder   if ((Status & APFloat::opInexact) &&
812a07aba5dSTimm Baeder       FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) {
813a07aba5dSTimm Baeder     // Inexact result means that it depends on rounding mode. If the requested
814a07aba5dSTimm Baeder     // mode is dynamic, the evaluation cannot be made in compile time.
8150f5f440fSTimm Baeder     const SourceInfo &E = S.Current->getSource(OpPC);
816a07aba5dSTimm Baeder     S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
817a07aba5dSTimm Baeder     return false;
818a07aba5dSTimm Baeder   }
819a07aba5dSTimm Baeder 
820a07aba5dSTimm Baeder   if ((Status != APFloat::opOK) &&
821a07aba5dSTimm Baeder       (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic ||
822a07aba5dSTimm Baeder        FPO.getExceptionMode() != LangOptions::FPE_Ignore ||
823a07aba5dSTimm Baeder        FPO.getAllowFEnvAccess())) {
8240f5f440fSTimm Baeder     const SourceInfo &E = S.Current->getSource(OpPC);
825a07aba5dSTimm Baeder     S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
826a07aba5dSTimm Baeder     return false;
827a07aba5dSTimm Baeder   }
828a07aba5dSTimm Baeder 
829a07aba5dSTimm Baeder   if ((Status & APFloat::opStatus::opInvalidOp) &&
830a07aba5dSTimm Baeder       FPO.getExceptionMode() != LangOptions::FPE_Ignore) {
8310f5f440fSTimm Baeder     const SourceInfo &E = S.Current->getSource(OpPC);
832a07aba5dSTimm Baeder     // There is no usefully definable result.
833a07aba5dSTimm Baeder     S.FFDiag(E);
834a07aba5dSTimm Baeder     return false;
835a07aba5dSTimm Baeder   }
836a07aba5dSTimm Baeder 
837a07aba5dSTimm Baeder   return true;
838a07aba5dSTimm Baeder }
839a07aba5dSTimm Baeder 
840a07aba5dSTimm Baeder bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC) {
841a07aba5dSTimm Baeder   if (S.getLangOpts().CPlusPlus20)
842a07aba5dSTimm Baeder     return true;
843a07aba5dSTimm Baeder 
844a07aba5dSTimm Baeder   const SourceInfo &E = S.Current->getSource(OpPC);
845a07aba5dSTimm Baeder   S.CCEDiag(E, diag::note_constexpr_new);
846a07aba5dSTimm Baeder   return true;
847a07aba5dSTimm Baeder }
848a07aba5dSTimm Baeder 
849610b8539STimm Baeder bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC,
850610b8539STimm Baeder                          DynamicAllocator::Form AllocForm,
851610b8539STimm Baeder                          DynamicAllocator::Form DeleteForm, const Descriptor *D,
852a07aba5dSTimm Baeder                          const Expr *NewExpr) {
853610b8539STimm Baeder   if (AllocForm == DeleteForm)
854a07aba5dSTimm Baeder     return true;
855a07aba5dSTimm Baeder 
856a07aba5dSTimm Baeder   QualType TypeToDiagnose;
857a07aba5dSTimm Baeder   // We need to shuffle things around a bit here to get a better diagnostic,
858a07aba5dSTimm Baeder   // because the expression we allocated the block for was of type int*,
859a07aba5dSTimm Baeder   // but we want to get the array size right.
860a07aba5dSTimm Baeder   if (D->isArray()) {
861a07aba5dSTimm Baeder     QualType ElemQT = D->getType()->getPointeeType();
862d9e72860Syronglin     TypeToDiagnose = S.getASTContext().getConstantArrayType(
863a07aba5dSTimm Baeder         ElemQT, APInt(64, static_cast<uint64_t>(D->getNumElems()), false),
864a07aba5dSTimm Baeder         nullptr, ArraySizeModifier::Normal, 0);
865a07aba5dSTimm Baeder   } else
866a07aba5dSTimm Baeder     TypeToDiagnose = D->getType()->getPointeeType();
867a07aba5dSTimm Baeder 
868a07aba5dSTimm Baeder   const SourceInfo &E = S.Current->getSource(OpPC);
869a07aba5dSTimm Baeder   S.FFDiag(E, diag::note_constexpr_new_delete_mismatch)
870610b8539STimm Baeder       << static_cast<int>(DeleteForm) << static_cast<int>(AllocForm)
871610b8539STimm Baeder       << TypeToDiagnose;
872a07aba5dSTimm Baeder   S.Note(NewExpr->getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
873a07aba5dSTimm Baeder       << NewExpr->getSourceRange();
874a07aba5dSTimm Baeder   return false;
875a07aba5dSTimm Baeder }
876a07aba5dSTimm Baeder 
877a07aba5dSTimm Baeder bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source,
878a07aba5dSTimm Baeder                        const Pointer &Ptr) {
879e6030d38STimm Baeder   // Regular new type(...) call.
880610b8539STimm Baeder   if (isa_and_nonnull<CXXNewExpr>(Source))
881610b8539STimm Baeder     return true;
882e6030d38STimm Baeder   // operator new.
883e6030d38STimm Baeder   if (const auto *CE = dyn_cast_if_present<CallExpr>(Source);
884610b8539STimm Baeder       CE && CE->getBuiltinCallee() == Builtin::BI__builtin_operator_new)
885a07aba5dSTimm Baeder     return true;
886e6030d38STimm Baeder   // std::allocator.allocate() call
887e6030d38STimm Baeder   if (const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(Source);
888e6030d38STimm Baeder       MCE && MCE->getMethodDecl()->getIdentifier()->isStr("allocate"))
889e6030d38STimm Baeder     return true;
890a07aba5dSTimm Baeder 
891a07aba5dSTimm Baeder   // Whatever this is, we didn't heap allocate it.
892a07aba5dSTimm Baeder   const SourceInfo &Loc = S.Current->getSource(OpPC);
893a07aba5dSTimm Baeder   S.FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
894d9e72860Syronglin       << Ptr.toDiagnosticString(S.getASTContext());
895a07aba5dSTimm Baeder 
896a07aba5dSTimm Baeder   if (Ptr.isTemporary())
897a07aba5dSTimm Baeder     S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
898a07aba5dSTimm Baeder   else
899a07aba5dSTimm Baeder     S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
900a07aba5dSTimm Baeder   return false;
901a07aba5dSTimm Baeder }
902a07aba5dSTimm Baeder 
903a07aba5dSTimm Baeder /// We aleady know the given DeclRefExpr is invalid for some reason,
904a07aba5dSTimm Baeder /// now figure out why and print appropriate diagnostics.
905a07aba5dSTimm Baeder bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
906a07aba5dSTimm Baeder   const ValueDecl *D = DR->getDecl();
907a07aba5dSTimm Baeder   return diagnoseUnknownDecl(S, OpPC, D);
908a07aba5dSTimm Baeder }
909a07aba5dSTimm Baeder 
910a07aba5dSTimm Baeder bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
911a07aba5dSTimm Baeder                 AccessKinds AK) {
912a07aba5dSTimm Baeder   if (!Ptr.isDummy())
913a07aba5dSTimm Baeder     return true;
914a07aba5dSTimm Baeder 
915a07aba5dSTimm Baeder   const Descriptor *Desc = Ptr.getDeclDesc();
916a07aba5dSTimm Baeder   const ValueDecl *D = Desc->asValueDecl();
917a07aba5dSTimm Baeder   if (!D)
918a07aba5dSTimm Baeder     return false;
919a07aba5dSTimm Baeder 
920a07aba5dSTimm Baeder   if (AK == AK_Read || AK == AK_Increment || AK == AK_Decrement)
921a07aba5dSTimm Baeder     return diagnoseUnknownDecl(S, OpPC, D);
922a07aba5dSTimm Baeder 
923a07aba5dSTimm Baeder   assert(AK == AK_Assign);
924f22a8d18STimm Baeder   if (S.getLangOpts().CPlusPlus14) {
925a07aba5dSTimm Baeder     const SourceInfo &E = S.Current->getSource(OpPC);
926a07aba5dSTimm Baeder     S.FFDiag(E, diag::note_constexpr_modify_global);
927a07aba5dSTimm Baeder   }
928a07aba5dSTimm Baeder   return false;
929a07aba5dSTimm Baeder }
930a07aba5dSTimm Baeder 
931a07aba5dSTimm Baeder bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F,
932a07aba5dSTimm Baeder                       const CallExpr *CE, unsigned ArgSize) {
933a07aba5dSTimm Baeder   auto Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
934a07aba5dSTimm Baeder   auto NonNullArgs = collectNonNullArgs(F->getDecl(), Args);
935a07aba5dSTimm Baeder   unsigned Offset = 0;
936a07aba5dSTimm Baeder   unsigned Index = 0;
937a07aba5dSTimm Baeder   for (const Expr *Arg : Args) {
938a07aba5dSTimm Baeder     if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
939a07aba5dSTimm Baeder       const Pointer &ArgPtr = S.Stk.peek<Pointer>(ArgSize - Offset);
940a07aba5dSTimm Baeder       if (ArgPtr.isZero()) {
941a07aba5dSTimm Baeder         const SourceLocation &Loc = S.Current->getLocation(OpPC);
942a07aba5dSTimm Baeder         S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
943a07aba5dSTimm Baeder         return false;
944a07aba5dSTimm Baeder       }
945a07aba5dSTimm Baeder     }
946a07aba5dSTimm Baeder 
947a07aba5dSTimm Baeder     Offset += align(primSize(S.Ctx.classify(Arg).value_or(PT_Ptr)));
948a07aba5dSTimm Baeder     ++Index;
949a07aba5dSTimm Baeder   }
950a07aba5dSTimm Baeder   return true;
951a07aba5dSTimm Baeder }
952a07aba5dSTimm Baeder 
953a07aba5dSTimm Baeder // FIXME: This is similar to code we already have in Compiler.cpp.
954a07aba5dSTimm Baeder // I think it makes sense to instead add the field and base destruction stuff
955a07aba5dSTimm Baeder // to the destructor Function itself. Then destroying a record would really
956a07aba5dSTimm Baeder // _just_ be calling its destructor. That would also help with the diagnostic
957a07aba5dSTimm Baeder // difference when the destructor or a field/base fails.
958a07aba5dSTimm Baeder static bool runRecordDestructor(InterpState &S, CodePtr OpPC,
959a07aba5dSTimm Baeder                                 const Pointer &BasePtr,
960a07aba5dSTimm Baeder                                 const Descriptor *Desc) {
961a07aba5dSTimm Baeder   assert(Desc->isRecord());
962a07aba5dSTimm Baeder   const Record *R = Desc->ElemRecord;
963a07aba5dSTimm Baeder   assert(R);
964a07aba5dSTimm Baeder 
965a07aba5dSTimm Baeder   if (Pointer::pointToSameBlock(BasePtr, S.Current->getThis())) {
966a07aba5dSTimm Baeder     const SourceInfo &Loc = S.Current->getSource(OpPC);
967a07aba5dSTimm Baeder     S.FFDiag(Loc, diag::note_constexpr_double_destroy);
968a07aba5dSTimm Baeder     return false;
969a07aba5dSTimm Baeder   }
970a07aba5dSTimm Baeder 
971a07aba5dSTimm Baeder   // Destructor of this record.
972a07aba5dSTimm Baeder   if (const CXXDestructorDecl *Dtor = R->getDestructor();
973a07aba5dSTimm Baeder       Dtor && !Dtor->isTrivial()) {
974a07aba5dSTimm Baeder     const Function *DtorFunc = S.getContext().getOrCreateFunction(Dtor);
975a07aba5dSTimm Baeder     if (!DtorFunc)
976a07aba5dSTimm Baeder       return false;
977a07aba5dSTimm Baeder 
978a07aba5dSTimm Baeder     S.Stk.push<Pointer>(BasePtr);
979a07aba5dSTimm Baeder     if (!Call(S, OpPC, DtorFunc, 0))
980a07aba5dSTimm Baeder       return false;
981a07aba5dSTimm Baeder   }
982a07aba5dSTimm Baeder   return true;
983a07aba5dSTimm Baeder }
984a07aba5dSTimm Baeder 
985f93258e4STimm Baeder static bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B) {
986a07aba5dSTimm Baeder   assert(B);
987a07aba5dSTimm Baeder   const Descriptor *Desc = B->getDescriptor();
988a07aba5dSTimm Baeder 
989a07aba5dSTimm Baeder   if (Desc->isPrimitive() || Desc->isPrimitiveArray())
990a07aba5dSTimm Baeder     return true;
991a07aba5dSTimm Baeder 
992a07aba5dSTimm Baeder   assert(Desc->isRecord() || Desc->isCompositeArray());
993a07aba5dSTimm Baeder 
994a07aba5dSTimm Baeder   if (Desc->isCompositeArray()) {
995a07aba5dSTimm Baeder     const Descriptor *ElemDesc = Desc->ElemDesc;
996a07aba5dSTimm Baeder     assert(ElemDesc->isRecord());
997a07aba5dSTimm Baeder 
998a07aba5dSTimm Baeder     Pointer RP(const_cast<Block *>(B));
999a07aba5dSTimm Baeder     for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
1000a07aba5dSTimm Baeder       if (!runRecordDestructor(S, OpPC, RP.atIndex(I).narrow(), ElemDesc))
1001a07aba5dSTimm Baeder         return false;
1002a07aba5dSTimm Baeder     }
1003a07aba5dSTimm Baeder     return true;
1004a07aba5dSTimm Baeder   }
1005a07aba5dSTimm Baeder 
1006a07aba5dSTimm Baeder   assert(Desc->isRecord());
1007a07aba5dSTimm Baeder   return runRecordDestructor(S, OpPC, Pointer(const_cast<Block *>(B)), Desc);
1008a07aba5dSTimm Baeder }
1009a07aba5dSTimm Baeder 
1010f0b9a0baSTimm Baeder static bool hasVirtualDestructor(QualType T) {
1011f0b9a0baSTimm Baeder   if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
1012f0b9a0baSTimm Baeder     if (const CXXDestructorDecl *DD = RD->getDestructor())
1013f0b9a0baSTimm Baeder       return DD->isVirtual();
1014f0b9a0baSTimm Baeder   return false;
1015f0b9a0baSTimm Baeder }
1016f0b9a0baSTimm Baeder 
1017f93258e4STimm Baeder bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
1018f93258e4STimm Baeder           bool IsGlobalDelete) {
1019f93258e4STimm Baeder   if (!CheckDynamicMemoryAllocation(S, OpPC))
1020f93258e4STimm Baeder     return false;
1021f93258e4STimm Baeder 
1022f93258e4STimm Baeder   const Expr *Source = nullptr;
1023f93258e4STimm Baeder   const Block *BlockToDelete = nullptr;
1024f93258e4STimm Baeder   {
1025f93258e4STimm Baeder     // Extra scope for this so the block doesn't have this pointer
1026f93258e4STimm Baeder     // pointing to it when we destroy it.
1027f93258e4STimm Baeder     Pointer Ptr = S.Stk.pop<Pointer>();
1028f93258e4STimm Baeder 
1029f93258e4STimm Baeder     // Deleteing nullptr is always fine.
1030f93258e4STimm Baeder     if (Ptr.isZero())
1031f93258e4STimm Baeder       return true;
1032f93258e4STimm Baeder 
1033f93258e4STimm Baeder     // Remove base casts.
1034f0b9a0baSTimm Baeder     QualType InitialType = Ptr.getType();
1035f93258e4STimm Baeder     while (Ptr.isBaseClass())
1036f93258e4STimm Baeder       Ptr = Ptr.getBase();
1037f93258e4STimm Baeder 
1038f0b9a0baSTimm Baeder     // For the non-array case, the types must match if the static type
1039f0b9a0baSTimm Baeder     // does not have a virtual destructor.
1040f0b9a0baSTimm Baeder     if (!DeleteIsArrayForm && Ptr.getType() != InitialType &&
1041f0b9a0baSTimm Baeder         !hasVirtualDestructor(InitialType)) {
1042f0b9a0baSTimm Baeder       S.FFDiag(S.Current->getSource(OpPC),
1043f0b9a0baSTimm Baeder                diag::note_constexpr_delete_base_nonvirt_dtor)
1044f0b9a0baSTimm Baeder           << InitialType << Ptr.getType();
1045f0b9a0baSTimm Baeder       return false;
1046f0b9a0baSTimm Baeder     }
1047f0b9a0baSTimm Baeder 
1048f93258e4STimm Baeder     if (!Ptr.isRoot() || Ptr.isOnePastEnd() || Ptr.isArrayElement()) {
1049f93258e4STimm Baeder       const SourceInfo &Loc = S.Current->getSource(OpPC);
1050f93258e4STimm Baeder       S.FFDiag(Loc, diag::note_constexpr_delete_subobject)
1051f93258e4STimm Baeder           << Ptr.toDiagnosticString(S.getASTContext()) << Ptr.isOnePastEnd();
1052f93258e4STimm Baeder       return false;
1053f93258e4STimm Baeder     }
1054f93258e4STimm Baeder 
1055f93258e4STimm Baeder     Source = Ptr.getDeclDesc()->asExpr();
1056f93258e4STimm Baeder     BlockToDelete = Ptr.block();
1057f93258e4STimm Baeder 
1058f93258e4STimm Baeder     if (!CheckDeleteSource(S, OpPC, Source, Ptr))
1059f93258e4STimm Baeder       return false;
1060f93258e4STimm Baeder 
1061f93258e4STimm Baeder     // For a class type with a virtual destructor, the selected operator delete
1062f93258e4STimm Baeder     // is the one looked up when building the destructor.
1063f93258e4STimm Baeder     QualType AllocType = Ptr.getType();
1064f93258e4STimm Baeder     if (!DeleteIsArrayForm && !IsGlobalDelete) {
1065f93258e4STimm Baeder       auto getVirtualOperatorDelete = [](QualType T) -> const FunctionDecl * {
1066f93258e4STimm Baeder         if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
1067f93258e4STimm Baeder           if (const CXXDestructorDecl *DD = RD->getDestructor())
1068f93258e4STimm Baeder             return DD->isVirtual() ? DD->getOperatorDelete() : nullptr;
1069f93258e4STimm Baeder         return nullptr;
1070f93258e4STimm Baeder       };
1071f93258e4STimm Baeder 
1072f93258e4STimm Baeder       if (const FunctionDecl *VirtualDelete =
1073f93258e4STimm Baeder               getVirtualOperatorDelete(AllocType);
1074f93258e4STimm Baeder           VirtualDelete &&
1075f93258e4STimm Baeder           !VirtualDelete->isReplaceableGlobalAllocationFunction()) {
1076f93258e4STimm Baeder         S.FFDiag(S.Current->getSource(OpPC),
1077f93258e4STimm Baeder                  diag::note_constexpr_new_non_replaceable)
1078f93258e4STimm Baeder             << isa<CXXMethodDecl>(VirtualDelete) << VirtualDelete;
1079f93258e4STimm Baeder         return false;
1080f93258e4STimm Baeder       }
1081f93258e4STimm Baeder     }
1082f93258e4STimm Baeder   }
1083f93258e4STimm Baeder   assert(Source);
1084f93258e4STimm Baeder   assert(BlockToDelete);
1085f93258e4STimm Baeder 
1086f93258e4STimm Baeder   // Invoke destructors before deallocating the memory.
1087f93258e4STimm Baeder   if (!RunDestructors(S, OpPC, BlockToDelete))
1088f93258e4STimm Baeder     return false;
1089f93258e4STimm Baeder 
1090f93258e4STimm Baeder   DynamicAllocator &Allocator = S.getAllocator();
1091f93258e4STimm Baeder   const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
1092f93258e4STimm Baeder   std::optional<DynamicAllocator::Form> AllocForm =
1093f93258e4STimm Baeder       Allocator.getAllocationForm(Source);
1094f93258e4STimm Baeder 
1095f93258e4STimm Baeder   if (!Allocator.deallocate(Source, BlockToDelete, S)) {
1096f93258e4STimm Baeder     // Nothing has been deallocated, this must be a double-delete.
1097f93258e4STimm Baeder     const SourceInfo &Loc = S.Current->getSource(OpPC);
1098f93258e4STimm Baeder     S.FFDiag(Loc, diag::note_constexpr_double_delete);
1099f93258e4STimm Baeder     return false;
1100f93258e4STimm Baeder   }
1101f93258e4STimm Baeder 
1102f93258e4STimm Baeder   assert(AllocForm);
1103f93258e4STimm Baeder   DynamicAllocator::Form DeleteForm = DeleteIsArrayForm
1104f93258e4STimm Baeder                                           ? DynamicAllocator::Form::Array
1105f93258e4STimm Baeder                                           : DynamicAllocator::Form::NonArray;
1106f93258e4STimm Baeder   return CheckNewDeleteForms(S, OpPC, *AllocForm, DeleteForm, BlockDesc,
1107f93258e4STimm Baeder                              Source);
1108f93258e4STimm Baeder }
1109f93258e4STimm Baeder 
1110a07aba5dSTimm Baeder void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED,
1111a07aba5dSTimm Baeder                        const APSInt &Value) {
1112a07aba5dSTimm Baeder   llvm::APInt Min;
1113a07aba5dSTimm Baeder   llvm::APInt Max;
1114a07aba5dSTimm Baeder 
1115a07aba5dSTimm Baeder   if (S.EvaluatingDecl && !S.EvaluatingDecl->isConstexpr())
1116a07aba5dSTimm Baeder     return;
1117a07aba5dSTimm Baeder 
1118a07aba5dSTimm Baeder   ED->getValueRange(Max, Min);
1119a07aba5dSTimm Baeder   --Max;
1120a07aba5dSTimm Baeder 
1121a07aba5dSTimm Baeder   if (ED->getNumNegativeBits() &&
1122a07aba5dSTimm Baeder       (Max.slt(Value.getSExtValue()) || Min.sgt(Value.getSExtValue()))) {
1123a07aba5dSTimm Baeder     const SourceLocation &Loc = S.Current->getLocation(OpPC);
1124a07aba5dSTimm Baeder     S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1125a07aba5dSTimm Baeder         << llvm::toString(Value, 10) << Min.getSExtValue() << Max.getSExtValue()
1126a07aba5dSTimm Baeder         << ED;
1127a07aba5dSTimm Baeder   } else if (!ED->getNumNegativeBits() && Max.ult(Value.getZExtValue())) {
1128a07aba5dSTimm Baeder     const SourceLocation &Loc = S.Current->getLocation(OpPC);
1129a07aba5dSTimm Baeder     S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1130a07aba5dSTimm Baeder         << llvm::toString(Value, 10) << Min.getZExtValue() << Max.getZExtValue()
1131a07aba5dSTimm Baeder         << ED;
1132a07aba5dSTimm Baeder   }
1133a07aba5dSTimm Baeder }
1134a07aba5dSTimm Baeder 
1135f86050deSTimm Baeder bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T) {
1136f86050deSTimm Baeder   assert(T);
1137f86050deSTimm Baeder   assert(!S.getLangOpts().CPlusPlus23);
1138f86050deSTimm Baeder 
1139f86050deSTimm Baeder   // C++1y: A constant initializer for an object o [...] may also invoke
1140f86050deSTimm Baeder   // constexpr constructors for o and its subobjects even if those objects
1141f86050deSTimm Baeder   // are of non-literal class types.
1142f86050deSTimm Baeder   //
1143f86050deSTimm Baeder   // C++11 missed this detail for aggregates, so classes like this:
1144f86050deSTimm Baeder   //   struct foo_t { union { int i; volatile int j; } u; };
1145f86050deSTimm Baeder   // are not (obviously) initializable like so:
1146f86050deSTimm Baeder   //   __attribute__((__require_constant_initialization__))
1147f86050deSTimm Baeder   //   static const foo_t x = {{0}};
1148f86050deSTimm Baeder   // because "i" is a subobject with non-literal initialization (due to the
1149f86050deSTimm Baeder   // volatile member of the union). See:
1150f86050deSTimm Baeder   //   http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677
1151f86050deSTimm Baeder   // Therefore, we use the C++1y behavior.
1152f86050deSTimm Baeder 
1153f86050deSTimm Baeder   if (S.Current->getFunction() && S.Current->getFunction()->isConstructor() &&
1154f86050deSTimm Baeder       S.Current->getThis().getDeclDesc()->asDecl() == S.EvaluatingDecl) {
1155f86050deSTimm Baeder     return true;
1156f86050deSTimm Baeder   }
1157f86050deSTimm Baeder 
1158f86050deSTimm Baeder   const Expr *E = S.Current->getExpr(OpPC);
1159f86050deSTimm Baeder   if (S.getLangOpts().CPlusPlus11)
1160f86050deSTimm Baeder     S.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType();
1161f86050deSTimm Baeder   else
1162f86050deSTimm Baeder     S.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
1163f86050deSTimm Baeder   return false;
1164f86050deSTimm Baeder }
1165f86050deSTimm Baeder 
1166e86b68ffSTimm Baeder static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
1167e86b68ffSTimm Baeder                      uint32_t Off) {
1168e86b68ffSTimm Baeder   if (S.getLangOpts().CPlusPlus && S.inConstantContext() &&
1169e86b68ffSTimm Baeder       !CheckNull(S, OpPC, Ptr, CSK_Field))
1170e86b68ffSTimm Baeder     return false;
1171e86b68ffSTimm Baeder 
1172e86b68ffSTimm Baeder   if (!CheckExtern(S, OpPC, Ptr))
1173e86b68ffSTimm Baeder     return false;
1174e86b68ffSTimm Baeder   if (!CheckRange(S, OpPC, Ptr, CSK_Field))
1175e86b68ffSTimm Baeder     return false;
1176e86b68ffSTimm Baeder   if (!CheckArray(S, OpPC, Ptr))
1177e86b68ffSTimm Baeder     return false;
1178e86b68ffSTimm Baeder   if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
1179e86b68ffSTimm Baeder     return false;
1180e86b68ffSTimm Baeder 
1181e86b68ffSTimm Baeder   if (Ptr.isIntegralPointer()) {
1182e86b68ffSTimm Baeder     S.Stk.push<Pointer>(Ptr.asIntPointer().atOffset(S.getASTContext(), Off));
1183e86b68ffSTimm Baeder     return true;
1184e86b68ffSTimm Baeder   }
1185e86b68ffSTimm Baeder 
1186e86b68ffSTimm Baeder   if (!Ptr.isBlockPointer()) {
1187e86b68ffSTimm Baeder     // FIXME: The only time we (seem to) get here is when trying to access a
1188e86b68ffSTimm Baeder     // field of a typeid pointer. In that case, we're supposed to diagnose e.g.
1189e86b68ffSTimm Baeder     // `typeid(int).name`, but we currently diagnose `&typeid(int)`.
1190e86b68ffSTimm Baeder     S.FFDiag(S.Current->getSource(OpPC),
1191e86b68ffSTimm Baeder              diag::note_constexpr_access_unreadable_object)
1192e86b68ffSTimm Baeder         << AK_Read << Ptr.toDiagnosticString(S.getASTContext());
1193e86b68ffSTimm Baeder     return false;
1194e86b68ffSTimm Baeder   }
1195e86b68ffSTimm Baeder 
1196e86b68ffSTimm Baeder   if (Off > Ptr.block()->getSize())
1197e86b68ffSTimm Baeder     return false;
1198e86b68ffSTimm Baeder 
1199e86b68ffSTimm Baeder   S.Stk.push<Pointer>(Ptr.atField(Off));
1200e86b68ffSTimm Baeder   return true;
1201e86b68ffSTimm Baeder }
1202e86b68ffSTimm Baeder 
1203e86b68ffSTimm Baeder bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
1204e86b68ffSTimm Baeder   const auto &Ptr = S.Stk.peek<Pointer>();
1205e86b68ffSTimm Baeder   return getField(S, OpPC, Ptr, Off);
1206e86b68ffSTimm Baeder }
1207e86b68ffSTimm Baeder 
1208e86b68ffSTimm Baeder bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
1209e86b68ffSTimm Baeder   const auto &Ptr = S.Stk.pop<Pointer>();
1210e86b68ffSTimm Baeder   return getField(S, OpPC, Ptr, Off);
1211e86b68ffSTimm Baeder }
1212e86b68ffSTimm Baeder 
121309cd5a86STimm Baeder static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
121409cd5a86STimm Baeder                              const Pointer &ThisPtr) {
121509cd5a86STimm Baeder   assert(Func->isConstructor());
121609cd5a86STimm Baeder 
121709cd5a86STimm Baeder   const Descriptor *D = ThisPtr.getFieldDesc();
121809cd5a86STimm Baeder 
121909cd5a86STimm Baeder   // FIXME: I think this case is not 100% correct. E.g. a pointer into a
122009cd5a86STimm Baeder   // subobject of a composite array.
122109cd5a86STimm Baeder   if (!D->ElemRecord)
122209cd5a86STimm Baeder     return true;
122309cd5a86STimm Baeder 
122409cd5a86STimm Baeder   if (D->ElemRecord->getNumVirtualBases() == 0)
122509cd5a86STimm Baeder     return true;
122609cd5a86STimm Baeder 
122709cd5a86STimm Baeder   S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_virtual_base)
122809cd5a86STimm Baeder       << Func->getParentDecl();
122909cd5a86STimm Baeder   return false;
123009cd5a86STimm Baeder }
123109cd5a86STimm Baeder 
1232f70ccdaeSTimm Baeder bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
1233f70ccdaeSTimm Baeder              uint32_t VarArgSize) {
1234f70ccdaeSTimm Baeder   if (Func->hasThisPointer()) {
1235f70ccdaeSTimm Baeder     size_t ArgSize = Func->getArgSize() + VarArgSize;
1236f70ccdaeSTimm Baeder     size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1237f70ccdaeSTimm Baeder     const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1238f70ccdaeSTimm Baeder 
1239f70ccdaeSTimm Baeder     // If the current function is a lambda static invoker and
1240f70ccdaeSTimm Baeder     // the function we're about to call is a lambda call operator,
1241f70ccdaeSTimm Baeder     // skip the CheckInvoke, since the ThisPtr is a null pointer
1242f70ccdaeSTimm Baeder     // anyway.
1243f70ccdaeSTimm Baeder     if (!(S.Current->getFunction() &&
1244f70ccdaeSTimm Baeder           S.Current->getFunction()->isLambdaStaticInvoker() &&
1245f70ccdaeSTimm Baeder           Func->isLambdaCallOperator())) {
1246f70ccdaeSTimm Baeder       if (!CheckInvoke(S, OpPC, ThisPtr))
1247f70ccdaeSTimm Baeder         return false;
1248f70ccdaeSTimm Baeder     }
1249f70ccdaeSTimm Baeder 
1250f70ccdaeSTimm Baeder     if (S.checkingPotentialConstantExpression())
1251f70ccdaeSTimm Baeder       return false;
1252f70ccdaeSTimm Baeder   }
1253f70ccdaeSTimm Baeder 
1254f70ccdaeSTimm Baeder   if (!CheckCallable(S, OpPC, Func))
1255f70ccdaeSTimm Baeder     return false;
1256f70ccdaeSTimm Baeder 
1257f70ccdaeSTimm Baeder   if (!CheckCallDepth(S, OpPC))
1258f70ccdaeSTimm Baeder     return false;
1259f70ccdaeSTimm Baeder 
1260f70ccdaeSTimm Baeder   auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize);
1261f70ccdaeSTimm Baeder   InterpFrame *FrameBefore = S.Current;
1262f70ccdaeSTimm Baeder   S.Current = NewFrame.get();
1263f70ccdaeSTimm Baeder 
1264f70ccdaeSTimm Baeder   // Note that we cannot assert(CallResult.hasValue()) here since
1265f70ccdaeSTimm Baeder   // Ret() above only sets the APValue if the curent frame doesn't
1266f70ccdaeSTimm Baeder   // have a caller set.
126782ed9c03STimm Baeder   if (Interpret(S)) {
1268f70ccdaeSTimm Baeder     NewFrame.release(); // Frame was delete'd already.
1269f70ccdaeSTimm Baeder     assert(S.Current == FrameBefore);
1270f70ccdaeSTimm Baeder     return true;
1271f70ccdaeSTimm Baeder   }
1272f70ccdaeSTimm Baeder 
1273f70ccdaeSTimm Baeder   // Interpreting the function failed somehow. Reset to
1274f70ccdaeSTimm Baeder   // previous state.
1275f70ccdaeSTimm Baeder   S.Current = FrameBefore;
1276f70ccdaeSTimm Baeder   return false;
1277f70ccdaeSTimm Baeder }
1278f70ccdaeSTimm Baeder 
1279f70ccdaeSTimm Baeder bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
1280f70ccdaeSTimm Baeder           uint32_t VarArgSize) {
128183fea8b8STimm Baeder   assert(Func);
128283fea8b8STimm Baeder   auto cleanup = [&]() -> bool {
128383fea8b8STimm Baeder     cleanupAfterFunctionCall(S, OpPC, Func);
128483fea8b8STimm Baeder     return false;
128583fea8b8STimm Baeder   };
128683fea8b8STimm Baeder 
1287f70ccdaeSTimm Baeder   if (Func->hasThisPointer()) {
1288f70ccdaeSTimm Baeder     size_t ArgSize = Func->getArgSize() + VarArgSize;
1289f70ccdaeSTimm Baeder     size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1290f70ccdaeSTimm Baeder 
1291f70ccdaeSTimm Baeder     const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1292f70ccdaeSTimm Baeder 
1293*51c7338cSTimm Baeder     // C++23 [expr.const]p5.6
1294*51c7338cSTimm Baeder     // an invocation of a virtual function ([class.virtual]) for an object whose
1295*51c7338cSTimm Baeder     // dynamic type is constexpr-unknown;
1296*51c7338cSTimm Baeder     if (ThisPtr.isDummy() && Func->isVirtual())
1297*51c7338cSTimm Baeder       return false;
1298*51c7338cSTimm Baeder 
1299f70ccdaeSTimm Baeder     // If the current function is a lambda static invoker and
1300f70ccdaeSTimm Baeder     // the function we're about to call is a lambda call operator,
1301f70ccdaeSTimm Baeder     // skip the CheckInvoke, since the ThisPtr is a null pointer
1302f70ccdaeSTimm Baeder     // anyway.
1303f70ccdaeSTimm Baeder     if (S.Current->getFunction() &&
1304f70ccdaeSTimm Baeder         S.Current->getFunction()->isLambdaStaticInvoker() &&
1305f70ccdaeSTimm Baeder         Func->isLambdaCallOperator()) {
1306f70ccdaeSTimm Baeder       assert(ThisPtr.isZero());
1307f70ccdaeSTimm Baeder     } else {
1308f70ccdaeSTimm Baeder       if (!CheckInvoke(S, OpPC, ThisPtr))
130983fea8b8STimm Baeder         return cleanup();
1310f70ccdaeSTimm Baeder     }
131109cd5a86STimm Baeder 
131209cd5a86STimm Baeder     if (Func->isConstructor() && !checkConstructor(S, OpPC, Func, ThisPtr))
131309cd5a86STimm Baeder       return false;
1314f70ccdaeSTimm Baeder   }
1315f70ccdaeSTimm Baeder 
1316f70ccdaeSTimm Baeder   if (!CheckCallable(S, OpPC, Func))
131783fea8b8STimm Baeder     return cleanup();
1318f70ccdaeSTimm Baeder 
1319f70ccdaeSTimm Baeder   // FIXME: The isConstructor() check here is not always right. The current
1320f70ccdaeSTimm Baeder   // constant evaluator is somewhat inconsistent in when it allows a function
1321f70ccdaeSTimm Baeder   // call when checking for a constant expression.
1322f70ccdaeSTimm Baeder   if (Func->hasThisPointer() && S.checkingPotentialConstantExpression() &&
1323f70ccdaeSTimm Baeder       !Func->isConstructor())
132483fea8b8STimm Baeder     return cleanup();
1325f70ccdaeSTimm Baeder 
1326f70ccdaeSTimm Baeder   if (!CheckCallDepth(S, OpPC))
132783fea8b8STimm Baeder     return cleanup();
1328f70ccdaeSTimm Baeder 
1329f70ccdaeSTimm Baeder   auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC, VarArgSize);
1330f70ccdaeSTimm Baeder   InterpFrame *FrameBefore = S.Current;
1331f70ccdaeSTimm Baeder   S.Current = NewFrame.get();
1332f70ccdaeSTimm Baeder 
1333a024a0ceSTimm Baeder   InterpStateCCOverride CCOverride(S, Func->getDecl()->isImmediateFunction());
1334f70ccdaeSTimm Baeder   // Note that we cannot assert(CallResult.hasValue()) here since
1335f70ccdaeSTimm Baeder   // Ret() above only sets the APValue if the curent frame doesn't
1336f70ccdaeSTimm Baeder   // have a caller set.
133782ed9c03STimm Baeder   if (Interpret(S)) {
1338f70ccdaeSTimm Baeder     NewFrame.release(); // Frame was delete'd already.
1339f70ccdaeSTimm Baeder     assert(S.Current == FrameBefore);
1340f70ccdaeSTimm Baeder     return true;
1341f70ccdaeSTimm Baeder   }
1342f70ccdaeSTimm Baeder 
1343f70ccdaeSTimm Baeder   // Interpreting the function failed somehow. Reset to
1344f70ccdaeSTimm Baeder   // previous state.
1345f70ccdaeSTimm Baeder   S.Current = FrameBefore;
1346f70ccdaeSTimm Baeder   return false;
1347f70ccdaeSTimm Baeder }
1348f70ccdaeSTimm Baeder 
1349f70ccdaeSTimm Baeder bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
1350f70ccdaeSTimm Baeder               uint32_t VarArgSize) {
1351f70ccdaeSTimm Baeder   assert(Func->hasThisPointer());
1352f70ccdaeSTimm Baeder   assert(Func->isVirtual());
1353f70ccdaeSTimm Baeder   size_t ArgSize = Func->getArgSize() + VarArgSize;
1354f70ccdaeSTimm Baeder   size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1355f70ccdaeSTimm Baeder   Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1356f70ccdaeSTimm Baeder 
1357f70ccdaeSTimm Baeder   const CXXRecordDecl *DynamicDecl = nullptr;
1358f70ccdaeSTimm Baeder   {
1359f70ccdaeSTimm Baeder     Pointer TypePtr = ThisPtr;
1360f70ccdaeSTimm Baeder     while (TypePtr.isBaseClass())
1361f70ccdaeSTimm Baeder       TypePtr = TypePtr.getBase();
1362f70ccdaeSTimm Baeder 
1363f70ccdaeSTimm Baeder     QualType DynamicType = TypePtr.getType();
1364f70ccdaeSTimm Baeder     if (DynamicType->isPointerType() || DynamicType->isReferenceType())
1365f70ccdaeSTimm Baeder       DynamicDecl = DynamicType->getPointeeCXXRecordDecl();
1366f70ccdaeSTimm Baeder     else
1367f70ccdaeSTimm Baeder       DynamicDecl = DynamicType->getAsCXXRecordDecl();
1368f70ccdaeSTimm Baeder   }
1369f70ccdaeSTimm Baeder   assert(DynamicDecl);
1370f70ccdaeSTimm Baeder 
1371f70ccdaeSTimm Baeder   const auto *StaticDecl = cast<CXXRecordDecl>(Func->getParentDecl());
1372f70ccdaeSTimm Baeder   const auto *InitialFunction = cast<CXXMethodDecl>(Func->getDecl());
1373f70ccdaeSTimm Baeder   const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
1374f70ccdaeSTimm Baeder       DynamicDecl, StaticDecl, InitialFunction);
1375f70ccdaeSTimm Baeder 
1376f70ccdaeSTimm Baeder   if (Overrider != InitialFunction) {
1377f70ccdaeSTimm Baeder     // DR1872: An instantiated virtual constexpr function can't be called in a
1378f70ccdaeSTimm Baeder     // constant expression (prior to C++20). We can still constant-fold such a
1379f70ccdaeSTimm Baeder     // call.
1380f70ccdaeSTimm Baeder     if (!S.getLangOpts().CPlusPlus20 && Overrider->isVirtual()) {
1381f70ccdaeSTimm Baeder       const Expr *E = S.Current->getExpr(OpPC);
1382f70ccdaeSTimm Baeder       S.CCEDiag(E, diag::note_constexpr_virtual_call) << E->getSourceRange();
1383f70ccdaeSTimm Baeder     }
1384f70ccdaeSTimm Baeder 
1385f70ccdaeSTimm Baeder     Func = S.getContext().getOrCreateFunction(Overrider);
1386f70ccdaeSTimm Baeder 
1387f70ccdaeSTimm Baeder     const CXXRecordDecl *ThisFieldDecl =
1388f70ccdaeSTimm Baeder         ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
1389f70ccdaeSTimm Baeder     if (Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
1390f70ccdaeSTimm Baeder       // If the function we call is further DOWN the hierarchy than the
1391f70ccdaeSTimm Baeder       // FieldDesc of our pointer, just go up the hierarchy of this field
1392f70ccdaeSTimm Baeder       // the furthest we can go.
1393f70ccdaeSTimm Baeder       while (ThisPtr.isBaseClass())
1394f70ccdaeSTimm Baeder         ThisPtr = ThisPtr.getBase();
1395f70ccdaeSTimm Baeder     }
1396f70ccdaeSTimm Baeder   }
1397f70ccdaeSTimm Baeder 
1398f70ccdaeSTimm Baeder   if (!Call(S, OpPC, Func, VarArgSize))
1399f70ccdaeSTimm Baeder     return false;
1400f70ccdaeSTimm Baeder 
1401f70ccdaeSTimm Baeder   // Covariant return types. The return type of Overrider is a pointer
1402f70ccdaeSTimm Baeder   // or reference to a class type.
1403f70ccdaeSTimm Baeder   if (Overrider != InitialFunction &&
1404f70ccdaeSTimm Baeder       Overrider->getReturnType()->isPointerOrReferenceType() &&
1405f70ccdaeSTimm Baeder       InitialFunction->getReturnType()->isPointerOrReferenceType()) {
1406f70ccdaeSTimm Baeder     QualType OverriderPointeeType =
1407f70ccdaeSTimm Baeder         Overrider->getReturnType()->getPointeeType();
1408f70ccdaeSTimm Baeder     QualType InitialPointeeType =
1409f70ccdaeSTimm Baeder         InitialFunction->getReturnType()->getPointeeType();
1410f70ccdaeSTimm Baeder     // We've called Overrider above, but calling code expects us to return what
1411f70ccdaeSTimm Baeder     // InitialFunction returned. According to the rules for covariant return
1412f70ccdaeSTimm Baeder     // types, what InitialFunction returns needs to be a base class of what
1413f70ccdaeSTimm Baeder     // Overrider returns. So, we need to do an upcast here.
1414f70ccdaeSTimm Baeder     unsigned Offset = S.getContext().collectBaseOffset(
1415f70ccdaeSTimm Baeder         InitialPointeeType->getAsRecordDecl(),
1416f70ccdaeSTimm Baeder         OverriderPointeeType->getAsRecordDecl());
1417f70ccdaeSTimm Baeder     return GetPtrBasePop(S, OpPC, Offset);
1418f70ccdaeSTimm Baeder   }
1419f70ccdaeSTimm Baeder 
1420f70ccdaeSTimm Baeder   return true;
1421f70ccdaeSTimm Baeder }
1422f70ccdaeSTimm Baeder 
142346870175STimm Bäder bool CallBI(InterpState &S, CodePtr OpPC, const Function *Func,
142478cf9b83STimm Baeder             const CallExpr *CE, uint32_t BuiltinID) {
1425ce158734STimm Baeder   // A little arbitrary, but the current interpreter allows evaluation
1426ce158734STimm Baeder   // of builtin functions in this mode, with some exceptions.
1427ce158734STimm Baeder   if (BuiltinID == Builtin::BI__builtin_operator_new &&
1428ce158734STimm Baeder       S.checkingPotentialConstantExpression())
1429610b8539STimm Baeder     return false;
143046870175STimm Bäder   auto NewFrame = std::make_unique<InterpFrame>(S, Func, OpPC);
1431f70ccdaeSTimm Baeder 
1432f70ccdaeSTimm Baeder   InterpFrame *FrameBefore = S.Current;
1433f70ccdaeSTimm Baeder   S.Current = NewFrame.get();
1434f70ccdaeSTimm Baeder 
143546870175STimm Bäder   if (InterpretBuiltin(S, OpPC, Func, CE, BuiltinID)) {
143695f4aa44Ssmanna12     // Release ownership of NewFrame to prevent it from being deleted.
143795f4aa44Ssmanna12     NewFrame.release(); // Frame was deleted already.
143895f4aa44Ssmanna12     // Ensure that S.Current is correctly reset to the previous frame.
143995f4aa44Ssmanna12     assert(S.Current == FrameBefore);
1440f70ccdaeSTimm Baeder     return true;
1441f70ccdaeSTimm Baeder   }
144295f4aa44Ssmanna12 
144395f4aa44Ssmanna12   // Interpreting the function failed somehow. Reset to
144495f4aa44Ssmanna12   // previous state.
1445f70ccdaeSTimm Baeder   S.Current = FrameBefore;
1446f70ccdaeSTimm Baeder   return false;
1447f70ccdaeSTimm Baeder }
1448f70ccdaeSTimm Baeder 
1449f70ccdaeSTimm Baeder bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
1450f70ccdaeSTimm Baeder              const CallExpr *CE) {
1451f70ccdaeSTimm Baeder   const FunctionPointer &FuncPtr = S.Stk.pop<FunctionPointer>();
1452f70ccdaeSTimm Baeder 
1453f70ccdaeSTimm Baeder   const Function *F = FuncPtr.getFunction();
1454f70ccdaeSTimm Baeder   if (!F) {
1455f70ccdaeSTimm Baeder     const auto *E = cast<CallExpr>(S.Current->getExpr(OpPC));
1456f70ccdaeSTimm Baeder     S.FFDiag(E, diag::note_constexpr_null_callee)
1457f70ccdaeSTimm Baeder         << const_cast<Expr *>(E->getCallee()) << E->getSourceRange();
1458f70ccdaeSTimm Baeder     return false;
1459f70ccdaeSTimm Baeder   }
1460f70ccdaeSTimm Baeder 
1461f70ccdaeSTimm Baeder   if (!FuncPtr.isValid() || !F->getDecl())
1462f70ccdaeSTimm Baeder     return Invalid(S, OpPC);
1463f70ccdaeSTimm Baeder 
1464f70ccdaeSTimm Baeder   assert(F);
1465f70ccdaeSTimm Baeder 
1466f70ccdaeSTimm Baeder   // This happens when the call expression has been cast to
1467f70ccdaeSTimm Baeder   // something else, but we don't support that.
1468f70ccdaeSTimm Baeder   if (S.Ctx.classify(F->getDecl()->getReturnType()) !=
1469f70ccdaeSTimm Baeder       S.Ctx.classify(CE->getType()))
1470f70ccdaeSTimm Baeder     return false;
1471f70ccdaeSTimm Baeder 
1472f70ccdaeSTimm Baeder   // Check argument nullability state.
1473f70ccdaeSTimm Baeder   if (F->hasNonNullAttr()) {
1474f70ccdaeSTimm Baeder     if (!CheckNonNullArgs(S, OpPC, F, CE, ArgSize))
1475f70ccdaeSTimm Baeder       return false;
1476f70ccdaeSTimm Baeder   }
1477f70ccdaeSTimm Baeder 
1478f70ccdaeSTimm Baeder   assert(ArgSize >= F->getWrittenArgSize());
1479f70ccdaeSTimm Baeder   uint32_t VarArgSize = ArgSize - F->getWrittenArgSize();
1480f70ccdaeSTimm Baeder 
1481f70ccdaeSTimm Baeder   // We need to do this explicitly here since we don't have the necessary
1482f70ccdaeSTimm Baeder   // information to do it automatically.
1483f70ccdaeSTimm Baeder   if (F->isThisPointerExplicit())
1484f70ccdaeSTimm Baeder     VarArgSize -= align(primSize(PT_Ptr));
1485f70ccdaeSTimm Baeder 
1486f70ccdaeSTimm Baeder   if (F->isVirtual())
1487f70ccdaeSTimm Baeder     return CallVirt(S, OpPC, F, VarArgSize);
1488f70ccdaeSTimm Baeder 
1489f70ccdaeSTimm Baeder   return Call(S, OpPC, F, VarArgSize);
1490f70ccdaeSTimm Baeder }
1491f70ccdaeSTimm Baeder 
1492c712ab82STimm Baeder bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
1493c712ab82STimm Baeder                           std::optional<uint64_t> ArraySize) {
1494c712ab82STimm Baeder   const Pointer &Ptr = S.Stk.peek<Pointer>();
1495c712ab82STimm Baeder 
1496c712ab82STimm Baeder   if (!CheckStore(S, OpPC, Ptr))
1497c712ab82STimm Baeder     return false;
1498c712ab82STimm Baeder 
14994b964002STimm Baeder   if (!InvalidNewDeleteExpr(S, OpPC, E))
15004b964002STimm Baeder     return false;
15014b964002STimm Baeder 
1502c712ab82STimm Baeder   const auto *NewExpr = cast<CXXNewExpr>(E);
1503c712ab82STimm Baeder   QualType StorageType = Ptr.getType();
1504c712ab82STimm Baeder 
1505e6030d38STimm Baeder   if ((isa_and_nonnull<CXXNewExpr>(Ptr.getFieldDesc()->asExpr()) ||
1506e6030d38STimm Baeder        isa_and_nonnull<CXXMemberCallExpr>(Ptr.getFieldDesc()->asExpr())) &&
1507d9b377d8STimm Baeder       StorageType->isPointerType()) {
1508c712ab82STimm Baeder     // FIXME: Are there other cases where this is a problem?
1509c712ab82STimm Baeder     StorageType = StorageType->getPointeeType();
1510c712ab82STimm Baeder   }
1511c712ab82STimm Baeder 
1512c712ab82STimm Baeder   const ASTContext &ASTCtx = S.getASTContext();
1513c712ab82STimm Baeder   QualType AllocType;
1514c712ab82STimm Baeder   if (ArraySize) {
1515c712ab82STimm Baeder     AllocType = ASTCtx.getConstantArrayType(
1516c712ab82STimm Baeder         NewExpr->getAllocatedType(),
1517c712ab82STimm Baeder         APInt(64, static_cast<uint64_t>(*ArraySize), false), nullptr,
1518c712ab82STimm Baeder         ArraySizeModifier::Normal, 0);
1519c712ab82STimm Baeder   } else {
1520c712ab82STimm Baeder     AllocType = NewExpr->getAllocatedType();
1521c712ab82STimm Baeder   }
1522c712ab82STimm Baeder 
1523c712ab82STimm Baeder   unsigned StorageSize = 1;
1524c712ab82STimm Baeder   unsigned AllocSize = 1;
1525c712ab82STimm Baeder   if (const auto *CAT = dyn_cast<ConstantArrayType>(AllocType))
1526c712ab82STimm Baeder     AllocSize = CAT->getZExtSize();
1527c712ab82STimm Baeder   if (const auto *CAT = dyn_cast<ConstantArrayType>(StorageType))
1528c712ab82STimm Baeder     StorageSize = CAT->getZExtSize();
1529c712ab82STimm Baeder 
1530c712ab82STimm Baeder   if (AllocSize > StorageSize ||
1531c712ab82STimm Baeder       !ASTCtx.hasSimilarType(ASTCtx.getBaseElementType(AllocType),
1532c712ab82STimm Baeder                              ASTCtx.getBaseElementType(StorageType))) {
1533c712ab82STimm Baeder     S.FFDiag(S.Current->getLocation(OpPC),
1534c712ab82STimm Baeder              diag::note_constexpr_placement_new_wrong_type)
1535c712ab82STimm Baeder         << StorageType << AllocType;
1536c712ab82STimm Baeder     return false;
1537c712ab82STimm Baeder   }
153887b6ec3bSTimm Baeder 
153987b6ec3bSTimm Baeder   // Can't activate fields in a union, unless the direct base is the union.
154087b6ec3bSTimm Baeder   if (Ptr.inUnion() && !Ptr.isActive() && !Ptr.getBase().getRecord()->isUnion())
154187b6ec3bSTimm Baeder     return CheckActive(S, OpPC, Ptr, AK_Construct);
154287b6ec3bSTimm Baeder 
1543c712ab82STimm Baeder   return true;
1544c712ab82STimm Baeder }
1545c712ab82STimm Baeder 
1546c712ab82STimm Baeder bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E) {
1547c712ab82STimm Baeder   assert(E);
1548c712ab82STimm Baeder 
15494b964002STimm Baeder   if (S.getLangOpts().CPlusPlus26)
15504b964002STimm Baeder     return true;
15514b964002STimm Baeder 
1552a9731dffSTimm Baeder   const auto &Loc = S.Current->getSource(OpPC);
1553a9731dffSTimm Baeder 
1554c712ab82STimm Baeder   if (const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
1555c712ab82STimm Baeder     const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
1556c712ab82STimm Baeder 
1557c712ab82STimm Baeder     if (!S.getLangOpts().CPlusPlus26 && NewExpr->getNumPlacementArgs() > 0) {
15584b964002STimm Baeder       // This is allowed pre-C++26, but only an std function.
15594b964002STimm Baeder       if (S.Current->isStdFunction())
15604b964002STimm Baeder         return true;
1561c712ab82STimm Baeder       S.FFDiag(Loc, diag::note_constexpr_new_placement)
1562c712ab82STimm Baeder           << /*C++26 feature*/ 1 << E->getSourceRange();
1563c712ab82STimm Baeder     } else if (NewExpr->getNumPlacementArgs() == 1 &&
1564c712ab82STimm Baeder                !OperatorNew->isReservedGlobalPlacementOperator()) {
1565c712ab82STimm Baeder       S.FFDiag(Loc, diag::note_constexpr_new_placement)
1566c712ab82STimm Baeder           << /*Unsupported*/ 0 << E->getSourceRange();
1567c712ab82STimm Baeder     } else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) {
1568c712ab82STimm Baeder       S.FFDiag(Loc, diag::note_constexpr_new_non_replaceable)
1569c712ab82STimm Baeder           << isa<CXXMethodDecl>(OperatorNew) << OperatorNew;
1570c712ab82STimm Baeder     }
1571c712ab82STimm Baeder   } else {
1572c712ab82STimm Baeder     const auto *DeleteExpr = cast<CXXDeleteExpr>(E);
1573c712ab82STimm Baeder     const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
1574c712ab82STimm Baeder     if (!OperatorDelete->isReplaceableGlobalAllocationFunction()) {
1575c712ab82STimm Baeder       S.FFDiag(Loc, diag::note_constexpr_new_non_replaceable)
1576c712ab82STimm Baeder           << isa<CXXMethodDecl>(OperatorDelete) << OperatorDelete;
1577c712ab82STimm Baeder     }
1578c712ab82STimm Baeder   }
1579c712ab82STimm Baeder 
1580c712ab82STimm Baeder   return false;
1581c712ab82STimm Baeder }
1582c712ab82STimm Baeder 
158395ce78b7STimm Baeder bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC,
158495ce78b7STimm Baeder                               const FixedPoint &FP) {
158595ce78b7STimm Baeder   const Expr *E = S.Current->getExpr(OpPC);
158695ce78b7STimm Baeder   if (S.checkingForUndefinedBehavior()) {
158795ce78b7STimm Baeder     S.getASTContext().getDiagnostics().Report(
158895ce78b7STimm Baeder         E->getExprLoc(), diag::warn_fixedpoint_constant_overflow)
158995ce78b7STimm Baeder         << FP.toDiagnosticString(S.getASTContext()) << E->getType();
159095ce78b7STimm Baeder   }
159195ce78b7STimm Baeder   S.CCEDiag(E, diag::note_constexpr_overflow)
159295ce78b7STimm Baeder       << FP.toDiagnosticString(S.getASTContext()) << E->getType();
159395ce78b7STimm Baeder   return S.noteUndefinedBehavior();
159495ce78b7STimm Baeder }
159595ce78b7STimm Baeder 
1596fed8695bSTimm Baeder bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index) {
1597fed8695bSTimm Baeder   const SourceInfo &Loc = S.Current->getSource(OpPC);
1598fed8695bSTimm Baeder   S.FFDiag(Loc,
1599fed8695bSTimm Baeder            diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
1600fed8695bSTimm Baeder       << Index;
1601fed8695bSTimm Baeder   return false;
1602fed8695bSTimm Baeder }
1603fed8695bSTimm Baeder 
1604e637a5c9STimm Baeder bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC,
1605e637a5c9STimm Baeder                                 const Pointer &Ptr, unsigned BitWidth) {
1606e637a5c9STimm Baeder   if (Ptr.isDummy())
1607e637a5c9STimm Baeder     return false;
1608e637a5c9STimm Baeder 
1609e637a5c9STimm Baeder   const SourceInfo &E = S.Current->getSource(OpPC);
1610e637a5c9STimm Baeder   S.CCEDiag(E, diag::note_constexpr_invalid_cast)
1611e637a5c9STimm Baeder       << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
1612e637a5c9STimm Baeder 
1613e637a5c9STimm Baeder   if (Ptr.isBlockPointer() && !Ptr.isZero()) {
1614e637a5c9STimm Baeder     // Only allow based lvalue casts if they are lossless.
1615e637a5c9STimm Baeder     if (S.getASTContext().getTargetInfo().getPointerWidth(LangAS::Default) !=
1616e637a5c9STimm Baeder         BitWidth)
1617e637a5c9STimm Baeder       return Invalid(S, OpPC);
1618e637a5c9STimm Baeder   }
1619e637a5c9STimm Baeder   return true;
1620e637a5c9STimm Baeder }
1621e637a5c9STimm Baeder 
1622e637a5c9STimm Baeder bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
1623e637a5c9STimm Baeder   const Pointer &Ptr = S.Stk.pop<Pointer>();
1624e637a5c9STimm Baeder 
1625e637a5c9STimm Baeder   if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
1626e637a5c9STimm Baeder     return false;
1627e637a5c9STimm Baeder 
1628e637a5c9STimm Baeder   S.Stk.push<IntegralAP<false>>(
1629e637a5c9STimm Baeder       IntegralAP<false>::from(Ptr.getIntegerRepresentation(), BitWidth));
1630e637a5c9STimm Baeder   return true;
1631e637a5c9STimm Baeder }
1632e637a5c9STimm Baeder 
1633e637a5c9STimm Baeder bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
1634e637a5c9STimm Baeder   const Pointer &Ptr = S.Stk.pop<Pointer>();
1635e637a5c9STimm Baeder 
1636e637a5c9STimm Baeder   if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
1637e637a5c9STimm Baeder     return false;
1638e637a5c9STimm Baeder 
1639e637a5c9STimm Baeder   S.Stk.push<IntegralAP<true>>(
1640e637a5c9STimm Baeder       IntegralAP<true>::from(Ptr.getIntegerRepresentation(), BitWidth));
1641e637a5c9STimm Baeder   return true;
1642e637a5c9STimm Baeder }
1643e637a5c9STimm Baeder 
1644ef2a104cSTimm Baeder bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits,
1645ef2a104cSTimm Baeder                   bool TargetIsUCharOrByte) {
1646ef2a104cSTimm Baeder   // This is always fine.
1647ef2a104cSTimm Baeder   if (!HasIndeterminateBits)
1648ef2a104cSTimm Baeder     return true;
1649ef2a104cSTimm Baeder 
1650ef2a104cSTimm Baeder   // Indeterminate bits can only be bitcast to unsigned char or std::byte.
1651ef2a104cSTimm Baeder   if (TargetIsUCharOrByte)
1652ef2a104cSTimm Baeder     return true;
1653ef2a104cSTimm Baeder 
1654ef2a104cSTimm Baeder   const Expr *E = S.Current->getExpr(OpPC);
1655ef2a104cSTimm Baeder   QualType ExprType = E->getType();
1656ef2a104cSTimm Baeder   S.FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
1657ef2a104cSTimm Baeder       << ExprType << S.getLangOpts().CharIsSigned << E->getSourceRange();
1658ef2a104cSTimm Baeder   return false;
1659ef2a104cSTimm Baeder }
1660ef2a104cSTimm Baeder 
1661e86b68ffSTimm Baeder bool GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr,
1662e86b68ffSTimm Baeder                const Type *TypeInfoType) {
1663e86b68ffSTimm Baeder   S.Stk.push<Pointer>(TypePtr, TypeInfoType);
1664e86b68ffSTimm Baeder   return true;
1665e86b68ffSTimm Baeder }
1666e86b68ffSTimm Baeder 
1667e86b68ffSTimm Baeder bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType) {
1668e86b68ffSTimm Baeder   const auto &P = S.Stk.pop<Pointer>();
1669e86b68ffSTimm Baeder 
1670e86b68ffSTimm Baeder   if (!P.isBlockPointer())
1671e86b68ffSTimm Baeder     return false;
1672e86b68ffSTimm Baeder 
1673e86b68ffSTimm Baeder   S.Stk.push<Pointer>(P.getType().getTypePtr(), TypeInfoType);
1674e86b68ffSTimm Baeder   return true;
1675e86b68ffSTimm Baeder }
1676e86b68ffSTimm Baeder 
1677e86b68ffSTimm Baeder bool DiagTypeid(InterpState &S, CodePtr OpPC) {
1678e86b68ffSTimm Baeder   const auto *E = cast<CXXTypeidExpr>(S.Current->getExpr(OpPC));
1679e86b68ffSTimm Baeder   S.CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
1680e86b68ffSTimm Baeder       << E->getExprOperand()->getType()
1681e86b68ffSTimm Baeder       << E->getExprOperand()->getSourceRange();
1682e86b68ffSTimm Baeder   return false;
1683e86b68ffSTimm Baeder }
1684e86b68ffSTimm Baeder 
1685d2051919Sbd1976bris // https://github.com/llvm/llvm-project/issues/102513
1686d800ea7cSSimon Pilgrim #if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
1687d2051919Sbd1976bris #pragma optimize("", off)
1688d2051919Sbd1976bris #endif
168982ed9c03STimm Baeder bool Interpret(InterpState &S) {
1690a07aba5dSTimm Baeder   // The current stack frame when we started Interpret().
1691a07aba5dSTimm Baeder   // This is being used by the ops to determine wheter
1692a07aba5dSTimm Baeder   // to return from this function and thus terminate
1693a07aba5dSTimm Baeder   // interpretation.
1694a07aba5dSTimm Baeder   const InterpFrame *StartFrame = S.Current;
1695a07aba5dSTimm Baeder   assert(!S.Current->isRoot());
1696a07aba5dSTimm Baeder   CodePtr PC = S.Current->getPC();
1697a07aba5dSTimm Baeder 
1698a07aba5dSTimm Baeder   // Empty program.
1699a07aba5dSTimm Baeder   if (!PC)
1700a07aba5dSTimm Baeder     return true;
1701a07aba5dSTimm Baeder 
1702a07aba5dSTimm Baeder   for (;;) {
1703a07aba5dSTimm Baeder     auto Op = PC.read<Opcode>();
1704a07aba5dSTimm Baeder     CodePtr OpPC = PC;
1705a07aba5dSTimm Baeder 
1706a07aba5dSTimm Baeder     switch (Op) {
1707a07aba5dSTimm Baeder #define GET_INTERP
1708a07aba5dSTimm Baeder #include "Opcodes.inc"
1709a07aba5dSTimm Baeder #undef GET_INTERP
1710a07aba5dSTimm Baeder     }
1711a07aba5dSTimm Baeder   }
1712a07aba5dSTimm Baeder }
1713d2051919Sbd1976bris // https://github.com/llvm/llvm-project/issues/102513
1714d800ea7cSSimon Pilgrim #if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
1715d2051919Sbd1976bris #pragma optimize("", on)
1716d2051919Sbd1976bris #endif
1717a07aba5dSTimm Baeder 
1718a07aba5dSTimm Baeder } // namespace interp
1719a07aba5dSTimm Baeder } // namespace clang
1720