brintos

brintos / llvm-project-archived public Read only

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