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