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