//===--- CheckExprLifetime.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "CheckExprLifetime.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/PointerIntPair.h"

namespace clang::sema {
using lifetimes::isGslOwnerType;
using lifetimes::isGslPointerType;

namespace {
enum LifetimeKind {
  /// The lifetime of a temporary bound to this entity ends at the end of the
  /// full-expression, and that's (probably) fine.
  LK_FullExpression,

  /// The lifetime of a temporary bound to this entity is extended to the
  /// lifeitme of the entity itself.
  LK_Extended,

  /// The lifetime of a temporary bound to this entity probably ends too soon,
  /// because the entity is allocated in a new-expression.
  LK_New,

  /// The lifetime of a temporary bound to this entity ends too soon, because
  /// the entity is a return object.
  LK_Return,

  /// The lifetime of a temporary bound to this entity ends too soon, because
  /// the entity passed to a musttail function call.
  LK_MustTail,

  /// The lifetime of a temporary bound to this entity ends too soon, because
  /// the entity is the result of a statement expression.
  LK_StmtExprResult,

  /// This is a mem-initializer: if it would extend a temporary (other than via
  /// a default member initializer), the program is ill-formed.
  LK_MemInitializer,

  /// The lifetime of a temporary bound to this entity may end too soon,
  /// because the entity is a pointer and we assign the address of a temporary
  /// object to it.
  LK_Assignment,

  /// The lifetime of a temporary bound to this entity may end too soon,
  /// because the entity may capture the reference to a temporary object.
  LK_LifetimeCapture,
};
using LifetimeResult =
    llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
} // namespace

/// Determine the declaration which an initialized entity ultimately refers to,
/// for the purpose of lifetime-extending a temporary bound to a reference in
/// the initialization of \p Entity.
static LifetimeResult
getEntityLifetime(const InitializedEntity *Entity,
                  const InitializedEntity *InitField = nullptr) {
  // C++11 [class.temporary]p5:
  switch (Entity->getKind()) {
  case InitializedEntity::EK_Variable:
    //   The temporary [...] persists for the lifetime of the reference
    return {Entity, LK_Extended};

  case InitializedEntity::EK_Member:
    // For subobjects, we look at the complete object.
    if (Entity->getParent())
      return getEntityLifetime(Entity->getParent(), Entity);

    //   except:
    // C++17 [class.base.init]p8:
    //   A temporary expression bound to a reference member in a
    //   mem-initializer is ill-formed.
    // C++17 [class.base.init]p11:
    //   A temporary expression bound to a reference member from a
    //   default member initializer is ill-formed.
    //
    // The context of p11 and its example suggest that it's only the use of a
    // default member initializer from a constructor that makes the program
    // ill-formed, not its mere existence, and that it can even be used by
    // aggregate initialization.
    return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
                                                         : LK_MemInitializer};

  case InitializedEntity::EK_Binding:
    // Per [dcl.decomp]p3, the binding is treated as a variable of reference
    // type.
    return {Entity, LK_Extended};

  case InitializedEntity::EK_Parameter:
  case InitializedEntity::EK_Parameter_CF_Audited:
    //   -- A temporary bound to a reference parameter in a function call
    //      persists until the completion of the full-expression containing
    //      the call.
    return {nullptr, LK_FullExpression};

  case InitializedEntity::EK_TemplateParameter:
    // FIXME: This will always be ill-formed; should we eagerly diagnose it
    // here?
    return {nullptr, LK_FullExpression};

  case InitializedEntity::EK_Result:
    //   -- The lifetime of a temporary bound to the returned value in a
    //      function return statement is not extended; the temporary is
    //      destroyed at the end of the full-expression in the return statement.
    return {nullptr, LK_Return};

  case InitializedEntity::EK_StmtExprResult:
    // FIXME: Should we lifetime-extend through the result of a statement
    // expression?
    return {nullptr, LK_StmtExprResult};

  case InitializedEntity::EK_New:
    //   -- A temporary bound to a reference in a new-initializer persists
    //      until the completion of the full-expression containing the
    //      new-initializer.
    return {nullptr, LK_New};

  case InitializedEntity::EK_Temporary:
  case InitializedEntity::EK_CompoundLiteralInit:
  case InitializedEntity::EK_RelatedResult:
    // We don't yet know the storage duration of the surrounding temporary.
    // Assume it's got full-expression duration for now, it will patch up our
    // storage duration if that's not correct.
    return {nullptr, LK_FullExpression};

  case InitializedEntity::EK_ArrayElement:
    // For subobjects, we look at the complete object.
    return getEntityLifetime(Entity->getParent(), InitField);

  case InitializedEntity::EK_Base:
    // For subobjects, we look at the complete object.
    if (Entity->getParent())
      return getEntityLifetime(Entity->getParent(), InitField);
    return {InitField, LK_MemInitializer};

  case InitializedEntity::EK_Delegating:
    // We can reach this case for aggregate initialization in a constructor:
    //   struct A { int &&r; };
    //   struct B : A { B() : A{0} {} };
    // In this case, use the outermost field decl as the context.
    return {InitField, LK_MemInitializer};

  case InitializedEntity::EK_BlockElement:
  case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
  case InitializedEntity::EK_LambdaCapture:
  case InitializedEntity::EK_VectorElement:
  case InitializedEntity::EK_MatrixElement:
  case InitializedEntity::EK_ComplexElement:
    return {nullptr, LK_FullExpression};

  case InitializedEntity::EK_Exception:
    // FIXME: Can we diagnose lifetime problems with exceptions?
    return {nullptr, LK_FullExpression};

  case InitializedEntity::EK_ParenAggInitMember:
    //   -- A temporary object bound to a reference element of an aggregate of
    //      class type initialized from a parenthesized expression-list
    //      [dcl.init, 9.3] persists until the completion of the full-expression
    //      containing the expression-list.
    return {nullptr, LK_FullExpression};
  }

  llvm_unreachable("unknown entity kind");
}

namespace {
enum ReferenceKind {
  /// Lifetime would be extended by a reference binding to a temporary.
  RK_ReferenceBinding,
  /// Lifetime would be extended by a std::initializer_list object binding to
  /// its backing array.
  RK_StdInitializerList,
};

/// A temporary or local variable. This will be one of:
///  * A MaterializeTemporaryExpr.
///  * A DeclRefExpr whose declaration is a local.
///  * An AddrLabelExpr.
///  * A BlockExpr for a block with captures.
using Local = Expr *;

/// Expressions we stepped over when looking for the local state. Any steps
/// that would inhibit lifetime extension or take us out of subexpressions of
/// the initializer are included.
struct IndirectLocalPathEntry {
  enum EntryKind {
    DefaultInit,
    AddressOf,
    VarInit,
    LValToRVal,
    LifetimeBoundCall,
    TemporaryCopy,
    LambdaCaptureInit,
    MemberExpr,
    GslReferenceInit,
    GslPointerInit,
    GslPointerAssignment,
    DefaultArg,
    ParenAggInit,
  } Kind;
  Expr *E;
  union {
    const Decl *D = nullptr;
    const LambdaCapture *Capture;
  };
  IndirectLocalPathEntry() {}
  IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
  IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D)
      : Kind(K), E(E), D(D) {}
  IndirectLocalPathEntry(EntryKind K, Expr *E, const LambdaCapture *Capture)
      : Kind(K), E(E), Capture(Capture) {}
};

using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;

struct RevertToOldSizeRAII {
  IndirectLocalPath &Path;
  unsigned OldSize = Path.size();
  RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
  ~RevertToOldSizeRAII() { Path.resize(OldSize); }
};

using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
                                             ReferenceKind RK)>;
} // namespace

static bool isVarOnPath(const IndirectLocalPath &Path, VarDecl *VD) {
  for (auto E : Path)
    if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
      return true;
  return false;
}

static bool pathContainsInit(const IndirectLocalPath &Path) {
  return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
    return E.Kind == IndirectLocalPathEntry::DefaultInit ||
           E.Kind == IndirectLocalPathEntry::VarInit;
  });
}

static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
                                             Expr *Init, LocalVisitor Visit,
                                             bool RevisitSubinits);

static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
                                                  Expr *Init, ReferenceKind RK,
                                                  LocalVisitor Visit);

// Returns true if the given Record decl is a form of `GSLOwner<Pointer>`
// type, e.g. std::vector<string_view>, std::optional<string_view>.
static bool isContainerOfPointer(const RecordDecl *Container) {
  if (const auto *CTSD =
          dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container)) {
    if (!CTSD->hasAttr<OwnerAttr>()) // Container must be a GSL owner type.
      return false;
    const auto &TAs = CTSD->getTemplateArgs();
    return TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type &&
           lifetimes::isPointerLikeType(TAs[0].getAsType());
  }
  return false;
}
static bool isContainerOfOwner(const RecordDecl *Container) {
  const auto *CTSD =
      dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container);
  if (!CTSD)
    return false;
  if (!CTSD->hasAttr<OwnerAttr>()) // Container must be a GSL owner type.
    return false;
  const auto &TAs = CTSD->getTemplateArgs();
  return TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type &&
         isGslOwnerType(TAs[0].getAsType());
}

// Returns true if the given Record is `std::initializer_list<pointer>`.
static bool isStdInitializerListOfPointer(const RecordDecl *RD) {
  if (const auto *CTSD =
          dyn_cast_if_present<ClassTemplateSpecializationDecl>(RD)) {
    const auto &TAs = CTSD->getTemplateArgs();
    return lifetimes::isInStlNamespace(RD) && RD->getIdentifier() &&
           RD->getName() == "initializer_list" && TAs.size() > 0 &&
           TAs[0].getKind() == TemplateArgument::Type &&
           lifetimes::isPointerLikeType(TAs[0].getAsType());
  }
  return false;
}

// Returns true if the given constructor is a copy-like constructor, such as
// `Ctor(Owner<U>&&)` or `Ctor(const Owner<U>&)`.
static bool isCopyLikeConstructor(const CXXConstructorDecl *Ctor) {
  if (!Ctor || Ctor->param_size() != 1)
    return false;
  const auto *ParamRefType =
      Ctor->getParamDecl(0)->getType()->getAs<ReferenceType>();
  if (!ParamRefType)
    return false;

  // Check if the first parameter type is "Owner<U>".
  if (const auto *TST =
          ParamRefType->getPointeeType()->getAs<TemplateSpecializationType>())
    return TST->getTemplateName()
        .getAsTemplateDecl()
        ->getTemplatedDecl()
        ->hasAttr<OwnerAttr>();
  return false;
}

// Returns true if we should perform the GSL analysis on the first argument for
// the given constructor.
static bool
shouldTrackFirstArgumentForConstructor(const CXXConstructExpr *Ctor) {
  const auto *LHSRecordDecl = Ctor->getConstructor()->getParent();

  // Case 1, construct a GSL pointer, e.g. std::string_view
  // Always inspect when LHS is a pointer.
  if (LHSRecordDecl->hasAttr<PointerAttr>())
    return true;

  if (Ctor->getConstructor()->param_empty() ||
      !isContainerOfPointer(LHSRecordDecl))
    return false;

  // Now, the LHS is an Owner<Pointer> type, e.g., std::vector<string_view>.
  //
  // At a high level, we cannot precisely determine what the nested pointer
  // owns. However, by analyzing the RHS owner type, we can use heuristics to
  // infer ownership information. These heuristics are designed to be
  // conservative, minimizing false positives while still providing meaningful
  // diagnostics.
  //
  // While this inference isn't perfect, it helps catch common use-after-free
  // patterns.
  auto RHSArgType = Ctor->getArg(0)->getType();
  const auto *RHSRD = RHSArgType->getAsRecordDecl();
  // LHS is constructed from an initializer_list.
  //
  // std::initializer_list is a proxy object that provides access to the backing
  // array. We perform analysis on it to determine if there are any dangling
  // temporaries in the backing array.
  // E.g. std::vector<string_view> abc = {string()};
  if (isStdInitializerListOfPointer(RHSRD))
    return true;

  // RHS must be an owner.
  if (!isGslOwnerType(RHSArgType))
    return false;

  // Bail out if the RHS is Owner<Pointer>.
  //
  // We cannot reliably determine what the LHS nested pointer owns -- it could
  // be the entire RHS or the nested pointer in RHS. To avoid false positives,
  // we skip this case, such as:
  //   std::stack<std::string_view> s(std::deque<std::string_view>{});
  //
  // TODO: this also has a false negative, it doesn't catch the case like:
  //   std::optional<span<int*>> os = std::vector<int*>{}
  if (isContainerOfPointer(RHSRD))
    return false;

  // Assume that the nested Pointer is constructed from the nested Owner.
  // E.g. std::optional<string_view> sv = std::optional<string>(s);
  if (isContainerOfOwner(RHSRD))
    return true;

  // Now, the LHS is an Owner<Pointer> and the RHS is an Owner<X>,  where X is
  // neither an `Owner` nor a `Pointer`.
  //
  // Use the constructor's signature as a hint. If it is a copy-like constructor
  // `Owner1<Pointer>(Owner2<X>&&)`, we assume that the nested pointer is
  // constructed from X. In such cases, we do not diagnose, as `X` is not an
  // owner, e.g.
  //   std::optional<string_view> sv = std::optional<Foo>();
  if (const auto *PrimaryCtorTemplate =
          Ctor->getConstructor()->getPrimaryTemplate();
      PrimaryCtorTemplate &&
      isCopyLikeConstructor(dyn_cast_if_present<CXXConstructorDecl>(
          PrimaryCtorTemplate->getTemplatedDecl()))) {
    return false;
  }
  // Assume that the nested pointer is constructed from the whole RHS.
  // E.g. optional<string_view> s = std::string();
  return true;
}

// Visit lifetimebound or gsl-pointer arguments.
static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
                                       LocalVisitor Visit) {
  const FunctionDecl *Callee;
  ArrayRef<Expr *> Args;

  if (auto *CE = dyn_cast<CallExpr>(Call)) {
    Callee = CE->getDirectCallee();
    Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
  } else {
    auto *CCE = cast<CXXConstructExpr>(Call);
    Callee = CCE->getConstructor();
    Args = llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs());
  }
  if (!Callee)
    return;

  bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
      diag::warn_dangling_lifetime_pointer, SourceLocation());
  Expr *ObjectArg = nullptr;
  if (isa<CXXOperatorCallExpr>(Call) && Callee->isCXXInstanceMember()) {
    ObjectArg = Args[0];
    Args = Args.slice(1);
  } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
    ObjectArg = MCE->getImplicitObjectArgument();
  }

  auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) {
    Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
    if (Arg->isGLValue())
      visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
                                            Visit);
    else
      visitLocalsRetainedByInitializer(Path, Arg, Visit, true);
    Path.pop_back();
  };
  auto VisitGSLPointerArg = [&](const FunctionDecl *Callee, Expr *Arg) {
    auto ReturnType = Callee->getReturnType();

    // Once we initialized a value with a non gsl-owner reference, it can no
    // longer dangle.
    if (ReturnType->isReferenceType() &&
        !isGslOwnerType(ReturnType->getPointeeType())) {
      for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
        if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
            PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
          continue;
        if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
            PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
          return;
        break;
      }
    }
    Path.push_back({ReturnType->isReferenceType()
                        ? IndirectLocalPathEntry::GslReferenceInit
                        : IndirectLocalPathEntry::GslPointerInit,
                    Arg, Callee});
    if (Arg->isGLValue())
      visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
                                            Visit);
    else
      visitLocalsRetainedByInitializer(Path, Arg, Visit, true);
    Path.pop_back();
  };

  bool CheckCoroCall = false;
  if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
    CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
                    RD->hasAttr<CoroReturnTypeAttr>() &&
                    !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
  }

  if (ObjectArg) {
    bool CheckCoroObjArg = CheckCoroCall;
    // Coroutine lambda objects with empty capture list are not lifetimebound.
    if (auto *LE = dyn_cast<LambdaExpr>(ObjectArg->IgnoreImplicit());
        LE && LE->captures().empty())
      CheckCoroObjArg = false;
    // Allow `get_return_object()` as the object param (__promise) is not
    // lifetimebound.
    if (Sema::CanBeGetReturnObject(Callee))
      CheckCoroObjArg = false;
    if (lifetimes::implicitObjectParamIsLifetimeBound(Callee) ||
        CheckCoroObjArg)
      VisitLifetimeBoundArg(Callee, ObjectArg);
    else if (EnableGSLAnalysis) {
      if (auto *CME = dyn_cast<CXXMethodDecl>(Callee);
          CME && lifetimes::shouldTrackImplicitObjectArg(
                     *ObjectArg, CME, /*RunningUnderLifetimeSafety=*/false))
        VisitGSLPointerArg(Callee, ObjectArg);
    }
  }

  const FunctionDecl *CanonCallee =
      lifetimes::getDeclWithMergedLifetimeBoundAttrs(Callee);
  unsigned NP = std::min(Callee->getNumParams(), CanonCallee->getNumParams());
  for (unsigned I = 0, N = std::min<unsigned>(NP, Args.size()); I != N; ++I) {
    Expr *Arg = Args[I];
    RevertToOldSizeRAII RAII(Path);
    if (auto *DAE = dyn_cast<CXXDefaultArgExpr>(Arg)) {
      Path.push_back(
          {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
      Arg = DAE->getExpr();
    }
    if (CheckCoroCall ||
        CanonCallee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
      VisitLifetimeBoundArg(CanonCallee->getParamDecl(I), Arg);
    else if (isa<CXXConstructorDecl>(CanonCallee) &&
             llvm::any_of(CanonCallee->getParamDecl(I)
                              ->specific_attrs<LifetimeCaptureByAttr>(),
                          [](const LifetimeCaptureByAttr *CaptureAttr) {
                            return llvm::is_contained(
                                CaptureAttr->params(),
                                LifetimeCaptureByAttr::This);
                          }))
      // `lifetime_capture_by(this)` in a class constructor has the same
      // semantics as `lifetimebound`:
      //
      // struct Foo {
      //   const int& a;
      //   // Equivalent to Foo(const int& t [[clang::lifetimebound]])
      //   Foo(const int& t [[clang::lifetime_capture_by(this)]]) : a(t) {}
      // };
      //
      // In the implementation, `lifetime_capture_by` is treated as an alias for
      // `lifetimebound` and shares the same code path. This implies the emitted
      // diagnostics will be emitted under `-Wdangling`, not
      // `-Wdangling-capture`.
      VisitLifetimeBoundArg(CanonCallee->getParamDecl(I), Arg);
    else if (EnableGSLAnalysis && I == 0) {
      // Perform GSL analysis for the first argument
      if (lifetimes::shouldTrackFirstArgument(CanonCallee)) {
        VisitGSLPointerArg(CanonCallee, Arg);
      } else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Call);
                 Ctor && shouldTrackFirstArgumentForConstructor(Ctor)) {
        VisitGSLPointerArg(Ctor->getConstructor(), Arg);
      }
    }
  }
}

/// Visit the locals that would be reachable through a reference bound to the
/// glvalue expression \c Init.
static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
                                                  Expr *Init, ReferenceKind RK,
                                                  LocalVisitor Visit) {
  RevertToOldSizeRAII RAII(Path);

  // Walk past any constructs which we can lifetime-extend across.
  Expr *Old;
  do {
    Old = Init;

    if (auto *FE = dyn_cast<FullExpr>(Init))
      Init = FE->getSubExpr();

    if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
      // If this is just redundant braces around an initializer, step over it.
      if (ILE->isTransparent())
        Init = ILE->getInit(0);
    }

    if (MemberExpr *ME = dyn_cast<MemberExpr>(Init->IgnoreImpCasts()))
      Path.push_back(
          {IndirectLocalPathEntry::MemberExpr, ME, ME->getMemberDecl()});
    // Step over any subobject adjustments; we may have a materialized
    // temporary inside them.
    Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());

    // Per current approach for DR1376, look through casts to reference type
    // when performing lifetime extension.
    if (CastExpr *CE = dyn_cast<CastExpr>(Init))
      if (CE->getSubExpr()->isGLValue())
        Init = CE->getSubExpr();

    // Per the current approach for DR1299, look through array element access
    // on array glvalues when performing lifetime extension.
    if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init)) {
      Init = ASE->getBase();
      auto *ICE = dyn_cast<ImplicitCastExpr>(Init);
      if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
        Init = ICE->getSubExpr();
      else
        // We can't lifetime extend through this but we might still find some
        // retained temporaries.
        return visitLocalsRetainedByInitializer(Path, Init, Visit, true);
    }

    // Step into CXXDefaultInitExprs so we can diagnose cases where a
    // constructor inherits one as an implicit mem-initializer.
    if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
      Path.push_back(
          {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
      Init = DIE->getExpr();
    }
  } while (Init != Old);

  if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
    if (Visit(Path, Local(MTE), RK))
      visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit, true);
  }

  if (auto *M = dyn_cast<MemberExpr>(Init)) {
    // Lifetime of a non-reference type field is same as base object.
    if (auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
        F && !F->getType()->isReferenceType())
      visitLocalsRetainedByInitializer(Path, M->getBase(), Visit, true);
  }

  if (isa<CallExpr>(Init))
    return visitFunctionCallArguments(Path, Init, Visit);

  switch (Init->getStmtClass()) {
  case Stmt::DeclRefExprClass: {
    // If we find the name of a local non-reference parameter, we could have a
    // lifetime problem.
    auto *DRE = cast<DeclRefExpr>(Init);
    auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
    if (VD && VD->hasLocalStorage() &&
        !DRE->refersToEnclosingVariableOrCapture()) {
      if (!VD->getType()->isReferenceType()) {
        Visit(Path, Local(DRE), RK);
      } else if (isa<ParmVarDecl>(DRE->getDecl())) {
        // The lifetime of a reference parameter is unknown; assume it's OK
        // for now.
        break;
      } else if (VD->getInit() && !isVarOnPath(Path, VD)) {
        Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
        visitLocalsRetainedByReferenceBinding(Path, VD->getInit(),
                                              RK_ReferenceBinding, Visit);
      }
    }
    break;
  }

  case Stmt::UnaryOperatorClass: {
    // The only unary operator that make sense to handle here
    // is Deref.  All others don't resolve to a "name."  This includes
    // handling all sorts of rvalues passed to a unary operator.
    const UnaryOperator *U = cast<UnaryOperator>(Init);
    if (U->getOpcode() == UO_Deref)
      visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true);
    break;
  }

  case Stmt::ArraySectionExprClass: {
    visitLocalsRetainedByInitializer(
        Path, cast<ArraySectionExpr>(Init)->getBase(), Visit, true);
    break;
  }

  case Stmt::ConditionalOperatorClass:
  case Stmt::BinaryConditionalOperatorClass: {
    auto *C = cast<AbstractConditionalOperator>(Init);
    if (!C->getTrueExpr()->getType()->isVoidType())
      visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit);
    if (!C->getFalseExpr()->getType()->isVoidType())
      visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit);
    break;
  }

  case Stmt::CompoundLiteralExprClass: {
    if (auto *CLE = dyn_cast<CompoundLiteralExpr>(Init)) {
      if (!CLE->isFileScope())
        Visit(Path, Local(CLE), RK);
    }
    break;
  }

    // FIXME: Visit the left-hand side of an -> or ->*.

  default:
    break;
  }
}

/// Visit the locals that would be reachable through an object initialized by
/// the prvalue expression \c Init.
static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
                                             Expr *Init, LocalVisitor Visit,
                                             bool RevisitSubinits) {
  RevertToOldSizeRAII RAII(Path);

  Expr *Old;
  do {
    Old = Init;

    // Step into CXXDefaultInitExprs so we can diagnose cases where a
    // constructor inherits one as an implicit mem-initializer.
    if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
      Path.push_back(
          {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
      Init = DIE->getExpr();
    }

    if (auto *FE = dyn_cast<FullExpr>(Init))
      Init = FE->getSubExpr();

    // Dig out the expression which constructs the extended temporary.
    Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());

    if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
      Init = BTE->getSubExpr();

    Init = Init->IgnoreParens();

    // Step over value-preserving rvalue casts.
    if (auto *CE = dyn_cast<CastExpr>(Init)) {
      switch (CE->getCastKind()) {
      case CK_LValueToRValue:
        // If we can match the lvalue to a const object, we can look at its
        // initializer.
        Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
        return visitLocalsRetainedByReferenceBinding(
            Path, Init, RK_ReferenceBinding,
            [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
              if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
                auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
                if (VD && VD->getType().isConstQualified() && VD->getInit() &&
                    !isVarOnPath(Path, VD)) {
                  Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
                  visitLocalsRetainedByInitializer(Path, VD->getInit(), Visit,
                                                   true);
                }
              } else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
                if (MTE->getType().isConstQualified())
                  visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(),
                                                   Visit, true);
              }
              return false;
            });

        // We assume that objects can be retained by pointers cast to integers,
        // but not if the integer is cast to floating-point type or to _Complex.
        // We assume that casts to 'bool' do not preserve enough information to
        // retain a local object.
      case CK_NoOp:
      case CK_BitCast:
      case CK_BaseToDerived:
      case CK_DerivedToBase:
      case CK_UncheckedDerivedToBase:
      case CK_Dynamic:
      case CK_ToUnion:
      case CK_UserDefinedConversion:
      case CK_ConstructorConversion:
      case CK_IntegralToPointer:
      case CK_PointerToIntegral:
      case CK_VectorSplat:
      case CK_IntegralCast:
      case CK_CPointerToObjCPointerCast:
      case CK_BlockPointerToObjCPointerCast:
      case CK_AnyPointerToBlockPointerCast:
      case CK_AddressSpaceConversion:
        break;

      case CK_ArrayToPointerDecay:
        // Model array-to-pointer decay as taking the address of the array
        // lvalue.
        Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
        return visitLocalsRetainedByReferenceBinding(
            Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);

      default:
        return;
      }

      Init = CE->getSubExpr();
    }
  } while (Old != Init);

  // C++17 [dcl.init.list]p6:
  //   initializing an initializer_list object from the array extends the
  //   lifetime of the array exactly like binding a reference to a temporary.
  if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init))
    return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(),
                                                 RK_StdInitializerList, Visit);

  if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
    // We already visited the elements of this initializer list while
    // performing the initialization. Don't visit them again unless we've
    // changed the lifetime of the initialized entity.
    if (!RevisitSubinits)
      return;

    if (ILE->isTransparent())
      return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit,
                                              RevisitSubinits);

    if (ILE->getType()->isArrayType()) {
      for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
        visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit,
                                         RevisitSubinits);
      return;
    }

    if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
      assert(RD->isAggregate() && "aggregate init on non-aggregate");

      // If we lifetime-extend a braced initializer which is initializing an
      // aggregate, and that aggregate contains reference members which are
      // bound to temporaries, those temporaries are also lifetime-extended.
      if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
          ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
        visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0),
                                              RK_ReferenceBinding, Visit);
      else {
        unsigned Index = 0;
        for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
          visitLocalsRetainedByInitializer(Path, ILE->getInit(Index), Visit,
                                           RevisitSubinits);
        for (const auto *I : RD->fields()) {
          if (Index >= ILE->getNumInits())
            break;
          if (I->isUnnamedBitField())
            continue;
          Expr *SubInit = ILE->getInit(Index);
          if (I->getType()->isReferenceType())
            visitLocalsRetainedByReferenceBinding(Path, SubInit,
                                                  RK_ReferenceBinding, Visit);
          else
            // This might be either aggregate-initialization of a member or
            // initialization of a std::initializer_list object. Regardless,
            // we should recursively lifetime-extend that initializer.
            visitLocalsRetainedByInitializer(Path, SubInit, Visit,
                                             RevisitSubinits);
          ++Index;
        }
      }
    }
    return;
  }

  // The lifetime of an init-capture is that of the closure object constructed
  // by a lambda-expression.
  if (auto *LE = dyn_cast<LambdaExpr>(Init)) {
    LambdaExpr::capture_iterator CapI = LE->capture_begin();
    for (Expr *E : LE->capture_inits()) {
      assert(CapI != LE->capture_end());
      const LambdaCapture &Cap = *CapI++;
      if (!E)
        continue;
      if (Cap.capturesVariable())
        Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
      if (E->isGLValue())
        visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding,
                                              Visit);
      else
        visitLocalsRetainedByInitializer(Path, E, Visit, true);
      if (Cap.capturesVariable())
        Path.pop_back();
    }
  }

  // Assume that a copy or move from a temporary references the same objects
  // that the temporary does.
  if (auto *CCE = dyn_cast<CXXConstructExpr>(Init)) {
    if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
      if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
        Expr *Arg = MTE->getSubExpr();
        Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
                        CCE->getConstructor()});
        visitLocalsRetainedByInitializer(Path, Arg, Visit, true);
        Path.pop_back();
      }
    }
  }

  if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init))
    return visitFunctionCallArguments(Path, Init, Visit);

  if (auto *CPE = dyn_cast<CXXParenListInitExpr>(Init)) {
    RevertToOldSizeRAII RAII(Path);
    Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
    for (auto *I : CPE->getInitExprs()) {
      if (I->isGLValue())
        visitLocalsRetainedByReferenceBinding(Path, I, RK_ReferenceBinding,
                                              Visit);
      else
        visitLocalsRetainedByInitializer(Path, I, Visit, true);
    }
  }
  switch (Init->getStmtClass()) {
  case Stmt::UnaryOperatorClass: {
    auto *UO = cast<UnaryOperator>(Init);
    // If the initializer is the address of a local, we could have a lifetime
    // problem.
    if (UO->getOpcode() == UO_AddrOf) {
      // If this is &rvalue, then it's ill-formed and we have already diagnosed
      // it. Don't produce a redundant warning about the lifetime of the
      // temporary.
      if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
        return;

      Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
      visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(),
                                            RK_ReferenceBinding, Visit);
    }
    break;
  }

  case Stmt::BinaryOperatorClass: {
    // Handle pointer arithmetic.
    auto *BO = cast<BinaryOperator>(Init);
    BinaryOperatorKind BOK = BO->getOpcode();
    if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
      break;

    if (BO->getLHS()->getType()->isPointerType())
      visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true);
    else if (BO->getRHS()->getType()->isPointerType())
      visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true);
    break;
  }

  case Stmt::ConditionalOperatorClass:
  case Stmt::BinaryConditionalOperatorClass: {
    auto *C = cast<AbstractConditionalOperator>(Init);
    // In C++, we can have a throw-expression operand, which has 'void' type
    // and isn't interesting from a lifetime perspective.
    if (!C->getTrueExpr()->getType()->isVoidType())
      visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true);
    if (!C->getFalseExpr()->getType()->isVoidType())
      visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true);
    break;
  }

  case Stmt::BlockExprClass:
    if (cast<BlockExpr>(Init)->getBlockDecl()->hasCaptures()) {
      // This is a local block, whose lifetime is that of the function.
      Visit(Path, Local(cast<BlockExpr>(Init)), RK_ReferenceBinding);
    }
    break;

  case Stmt::AddrLabelExprClass:
    // We want to warn if the address of a label would escape the function.
    Visit(Path, Local(cast<AddrLabelExpr>(Init)), RK_ReferenceBinding);
    break;

  default:
    break;
  }
}

/// Whether a path to an object supports lifetime extension.
enum PathLifetimeKind {
  /// Lifetime-extend along this path.
  Extend,
  /// Do not lifetime extend along this path.
  NoExtend
};

/// Determine whether this is an indirect path to a temporary that we are
/// supposed to lifetime-extend along.
static PathLifetimeKind
shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
  for (auto Elem : Path) {
    if (Elem.Kind == IndirectLocalPathEntry::MemberExpr ||
        Elem.Kind == IndirectLocalPathEntry::LambdaCaptureInit)
      continue;
    return Elem.Kind == IndirectLocalPathEntry::DefaultInit
               ? PathLifetimeKind::Extend
               : PathLifetimeKind::NoExtend;
  }
  return PathLifetimeKind::Extend;
}

/// Find the range for the first interesting entry in the path at or after I.
static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
                                      Expr *E) {
  for (unsigned N = Path.size(); I != N; ++I) {
    switch (Path[I].Kind) {
    case IndirectLocalPathEntry::AddressOf:
    case IndirectLocalPathEntry::LValToRVal:
    case IndirectLocalPathEntry::LifetimeBoundCall:
    case IndirectLocalPathEntry::TemporaryCopy:
    case IndirectLocalPathEntry::GslReferenceInit:
    case IndirectLocalPathEntry::GslPointerInit:
    case IndirectLocalPathEntry::GslPointerAssignment:
    case IndirectLocalPathEntry::ParenAggInit:
    case IndirectLocalPathEntry::MemberExpr:
      // These exist primarily to mark the path as not permitting or
      // supporting lifetime extension.
      break;

    case IndirectLocalPathEntry::VarInit:
      if (cast<VarDecl>(Path[I].D)->isImplicit())
        return SourceRange();
      [[fallthrough]];
    case IndirectLocalPathEntry::DefaultInit:
      return Path[I].E->getSourceRange();

    case IndirectLocalPathEntry::LambdaCaptureInit:
      if (!Path[I].Capture->capturesVariable())
        continue;
      return Path[I].E->getSourceRange();

    case IndirectLocalPathEntry::DefaultArg:
      return cast<CXXDefaultArgExpr>(Path[I].E)->getUsedLocation();
    }
  }
  return E->getSourceRange();
}

static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path) {
  for (const auto &It : llvm::reverse(Path)) {
    switch (It.Kind) {
    case IndirectLocalPathEntry::VarInit:
    case IndirectLocalPathEntry::AddressOf:
    case IndirectLocalPathEntry::LifetimeBoundCall:
    case IndirectLocalPathEntry::MemberExpr:
      continue;
    case IndirectLocalPathEntry::GslPointerInit:
    case IndirectLocalPathEntry::GslReferenceInit:
    case IndirectLocalPathEntry::GslPointerAssignment:
      return true;
    default:
      return false;
    }
  }
  return false;
}
// Result of analyzing the Path for GSLPointer.
enum AnalysisResult {
  // Path does not correspond to a GSLPointer.
  NotGSLPointer,

  // A relevant case was identified.
  Report,
  // Stop the entire traversal.
  Abandon,
  // Skip this step and continue traversing inner AST nodes.
  Skip,
};
// Analyze cases where a GSLPointer is initialized or assigned from a
// temporary owner object.
static AnalysisResult analyzePathForGSLPointer(const IndirectLocalPath &Path,
                                               Local L, LifetimeKind LK) {
  if (!pathOnlyHandlesGslPointer(Path))
    return NotGSLPointer;

  // At this point, Path represents a series of operations involving a
  // GSLPointer, either in the process of initialization or assignment.

  // Process  temporary base objects for MemberExpr cases, e.g. Temp().field.
  for (const auto &E : Path) {
    if (E.Kind == IndirectLocalPathEntry::MemberExpr) {
      // Avoid interfering  with the local base object.
      if (pathContainsInit(Path))
        return Abandon;

      // We are not interested in the temporary base objects of gsl Pointers:
      //   auto p1 = Temp().ptr; // Here p1 might not dangle.
      // However, we want to diagnose for gsl owner fields:
      //   auto p2 = Temp().owner; // Here p2 is dangling.
      if (const auto *FD = llvm::dyn_cast_or_null<FieldDecl>(E.D);
          FD && !FD->getType()->isReferenceType() &&
          isGslOwnerType(FD->getType()) && LK != LK_MemInitializer) {
        return Report;
      }
      return Abandon;
    }
  }

  // Note: A LifetimeBoundCall can appear interleaved in this sequence.
  // For example:
  //    const std::string& Ref(const std::string& a [[clang::lifetimebound]]);
  //    string_view abc = Ref(std::string());
  // The "Path" is [GSLPointerInit, LifetimeboundCall], where "L" is the
  // temporary "std::string()" object. We need to check the return type of the
  // function with the lifetimebound attribute.
  if (Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
    // The lifetimebound applies to the implicit object parameter of a method.
    const FunctionDecl *FD =
        llvm::dyn_cast_or_null<FunctionDecl>(Path.back().D);
    // The lifetimebound applies to a function parameter.
    if (const auto *PD = llvm::dyn_cast<ParmVarDecl>(Path.back().D))
      FD = llvm::dyn_cast<FunctionDecl>(PD->getDeclContext());

    if (isa_and_present<CXXConstructorDecl>(FD)) {
      // Constructor case: the parameter is annotated with lifetimebound
      //   e.g., GSLPointer(const S& s [[clang::lifetimebound]])
      // We still respect this case even the type S is not an owner.
      return Report;
    }
    // Check the return type, e.g.
    //   const GSLOwner& func(const Foo& foo [[clang::lifetimebound]])
    //   GSLOwner* func(cosnt Foo& foo [[clang::lifetimebound]])
    //   GSLPointer func(const Foo& foo [[clang::lifetimebound]])
    if (FD && ((FD->getReturnType()->isPointerOrReferenceType() &&
                isGslOwnerType(FD->getReturnType()->getPointeeType())) ||
               isGslPointerType(FD->getReturnType())))
      return Report;

    return Abandon;
  }

  if (isa<DeclRefExpr>(L)) {
    // We do not want to follow the references when returning a pointer
    // originating from a local owner to avoid the following false positive:
    //   int &p = *localUniquePtr;
    //   someContainer.add(std::move(localUniquePtr));
    //   return p;
    if (!pathContainsInit(Path) && isGslOwnerType(L->getType()))
      return Report;
    return Abandon;
  }

  // The GSLPointer is from a temporary object.
  auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);

  bool IsGslPtrValueFromGslTempOwner =
      MTE && !MTE->getExtendingDecl() && isGslOwnerType(MTE->getType());
  // Skipping a chain of initializing gsl::Pointer annotated objects.
  // We are looking only for the final source to find out if it was
  // a local or temporary owner or the address of a local
  // variable/param.
  if (!IsGslPtrValueFromGslTempOwner)
    return Skip;
  return Report;
}

static bool shouldRunGSLAssignmentAnalysis(const Sema &SemaRef,
                                           const AssignedEntity &Entity) {
  bool EnableGSLAssignmentWarnings = !SemaRef.getDiagnostics().isIgnored(
      diag::warn_dangling_lifetime_pointer_assignment, SourceLocation());
  return (EnableGSLAssignmentWarnings &&
          (isGslPointerType(Entity.LHS->getType()) ||
           lifetimes::isAssignmentOperatorLifetimeBound(
               Entity.AssignmentOperator)));
}

static void
checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity,
                      const InitializedEntity *ExtendingEntity, LifetimeKind LK,
                      const AssignedEntity *AEntity,
                      const CapturingEntity *CapEntity, Expr *Init) {
  assert(!AEntity || LK == LK_Assignment);
  assert(!CapEntity || LK == LK_LifetimeCapture);
  assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
  // If this entity doesn't have an interesting lifetime, don't bother looking
  // for temporaries within its initializer.
  if (LK == LK_FullExpression)
    return;

  // FIXME: consider moving the TemporaryVisitor and visitLocalsRetained*
  // functions to a dedicated class.
  auto TemporaryVisitor = [&](const IndirectLocalPath &Path, Local L,
                              ReferenceKind RK) -> bool {
    SourceRange DiagRange = nextPathEntryRange(Path, 0, L);
    SourceLocation DiagLoc = DiagRange.getBegin();

    auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);

    bool IsGslPtrValueFromGslTempOwner = true;
    switch (analyzePathForGSLPointer(Path, L, LK)) {
    case Abandon:
      return false;
    case Skip:
      return true;
    case NotGSLPointer:
      IsGslPtrValueFromGslTempOwner = false;
      [[fallthrough]];
    case Report:
      break;
    }

    switch (LK) {
    case LK_FullExpression:
      llvm_unreachable("already handled this");

    case LK_Extended: {
      if (!MTE) {
        // The initialized entity has lifetime beyond the full-expression,
        // and the local entity does too, so don't warn.
        //
        // FIXME: We should consider warning if a static / thread storage
        // duration variable retains an automatic storage duration local.
        return false;
      }

      switch (shouldLifetimeExtendThroughPath(Path)) {
      case PathLifetimeKind::Extend:
        // Update the storage duration of the materialized temporary.
        // FIXME: Rebuild the expression instead of mutating it.
        MTE->setExtendingDecl(ExtendingEntity->getDecl(),
                              ExtendingEntity->allocateManglingNumber());
        // Also visit the temporaries lifetime-extended by this initializer.
        return true;

      case PathLifetimeKind::NoExtend:
        if (SemaRef.getLangOpts().CPlusPlus23 && InitEntity) {
          if (const VarDecl *VD =
                  dyn_cast_if_present<VarDecl>(InitEntity->getDecl());
              VD && VD->isCXXForRangeImplicitVar()) {
            return false;
          }
        }

        if (IsGslPtrValueFromGslTempOwner && DiagLoc.isValid()) {
          SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
              << DiagRange;
          return false;
        }

        // If the path goes through the initialization of a variable or field,
        // it can't possibly reach a temporary created in this full-expression.
        // We will have already diagnosed any problems with the initializer.
        if (pathContainsInit(Path))
          return false;

        SemaRef.Diag(DiagLoc, diag::warn_dangling_variable)
            << RK << !InitEntity->getParent()
            << ExtendingEntity->getDecl()->isImplicit()
            << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;
        break;
      }
      break;
    }

    case LK_LifetimeCapture: {
      // The captured entity has lifetime beyond the full-expression,
      // and the capturing entity does too, so don't warn.
      if (!MTE)
        return false;
      if (CapEntity->Entity)
        SemaRef.Diag(DiagLoc, diag::warn_dangling_reference_captured)
            << CapEntity->Entity << DiagRange;
      else
        SemaRef.Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
            << DiagRange;
      return false;
    }

    case LK_Assignment: {
      if (!MTE || pathContainsInit(Path))
        return false;
      if (IsGslPtrValueFromGslTempOwner)
        SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
            << AEntity->LHS << DiagRange;
      else
        SemaRef.Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
            << AEntity->LHS->getType()->isPointerType() << AEntity->LHS
            << DiagRange;
      return false;
    }
    case LK_MemInitializer: {
      if (MTE) {
        // Under C++ DR1696, if a mem-initializer (or a default member
        // initializer used by the absence of one) would lifetime-extend a
        // temporary, the program is ill-formed.
        if (auto *ExtendingDecl =
                ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
          if (IsGslPtrValueFromGslTempOwner) {
            SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
                << ExtendingDecl << DiagRange;
            SemaRef.Diag(ExtendingDecl->getLocation(),
                         diag::note_ref_or_ptr_member_declared_here)
                << true;
            return false;
          }
          bool IsSubobjectMember = ExtendingEntity != InitEntity;
          SemaRef.Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) !=
                                        PathLifetimeKind::NoExtend
                                    ? diag::err_dangling_member
                                    : diag::warn_dangling_member)
              << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
          // Don't bother adding a note pointing to the field if we're inside
          // its default member initializer; our primary diagnostic points to
          // the same place in that case.
          if (Path.empty() ||
              Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
            SemaRef.Diag(ExtendingDecl->getLocation(),
                         diag::note_lifetime_extending_member_declared_here)
                << RK << IsSubobjectMember;
          }
        } else {
          // We have a mem-initializer but no particular field within it; this
          // is either a base class or a delegating initializer directly
          // initializing the base-class from something that doesn't live long
          // enough.
          //
          // FIXME: Warn on this.
          return false;
        }
      } else {
        // Paths via a default initializer can only occur during error recovery
        // (there's no other way that a default initializer can refer to a
        // local). Don't produce a bogus warning on those cases.
        if (pathContainsInit(Path))
          return false;

        auto *DRE = dyn_cast<DeclRefExpr>(L);
        // Suppress false positives for code like the one below:
        //   Ctor(unique_ptr<T> up) : pointer(up.get()), owner(move(up)) {}
        // FIXME: move this logic to analyzePathForGSLPointer.
        if (DRE && isGslOwnerType(DRE->getType()))
          return false;

        auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
        if (!VD) {
          // A member was initialized to a local block.
          // FIXME: Warn on this.
          return false;
        }

        if (auto *Member =
                ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
          bool IsPointer = !Member->getType()->isReferenceType();
          SemaRef.Diag(DiagLoc,
                       IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
                                 : diag::warn_bind_ref_member_to_parameter)
              << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
          SemaRef.Diag(Member->getLocation(),
                       diag::note_ref_or_ptr_member_declared_here)
              << (unsigned)IsPointer;
        }
      }
      break;
    }

    case LK_New:
      if (isa<MaterializeTemporaryExpr>(L)) {
        if (IsGslPtrValueFromGslTempOwner)
          SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
              << DiagRange;
        else
          SemaRef.Diag(DiagLoc, RK == RK_ReferenceBinding
                                    ? diag::warn_new_dangling_reference
                                    : diag::warn_new_dangling_initializer_list)
              << !InitEntity->getParent() << DiagRange;
      } else {
        // We can't determine if the allocation outlives the local declaration.
        return false;
      }
      break;

    case LK_Return:
    case LK_MustTail:
    case LK_StmtExprResult:
      if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
        // We can't determine if the local variable outlives the statement
        // expression.
        if (LK == LK_StmtExprResult)
          return false;
        if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
          if (VD->getType().getAddressSpace() == LangAS::opencl_local)
            return false;
        SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
            << InitEntity->getType()->isReferenceType() << DRE->getDecl()
            << isa<ParmVarDecl>(DRE->getDecl()) << (LK == LK_MustTail)
            << DiagRange;
      } else if (isa<BlockExpr>(L)) {
        SemaRef.Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
      } else if (isa<AddrLabelExpr>(L)) {
        // Don't warn when returning a label from a statement expression.
        // Leaving the scope doesn't end its lifetime.
        if (LK == LK_StmtExprResult)
          return false;
        SemaRef.Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
      } else if (auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
        SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
            << InitEntity->getType()->isReferenceType() << CLE->getInitializer()
            << 2 << (LK == LK_MustTail) << DiagRange;
      } else {
        // P2748R5: Disallow Binding a Returned Glvalue to a Temporary.
        // [stmt.return]/p6: In a function whose return type is a reference,
        // other than an invented function for std::is_convertible ([meta.rel]),
        // a return statement that binds the returned reference to a temporary
        // expression ([class.temporary]) is ill-formed.
        if (SemaRef.getLangOpts().CPlusPlus26 &&
            InitEntity->getType()->isReferenceType())
          SemaRef.Diag(DiagLoc, diag::err_ret_local_temp_ref)
              << InitEntity->getType()->isReferenceType() << DiagRange;
        else if (LK == LK_MustTail)
          SemaRef.Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
              << InitEntity->getType()->isReferenceType() << DiagRange;
        else
          SemaRef.Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
              << InitEntity->getType()->isReferenceType() << DiagRange;
      }
      break;
    }

    for (unsigned I = 0; I != Path.size(); ++I) {
      auto Elem = Path[I];

      switch (Elem.Kind) {
      case IndirectLocalPathEntry::AddressOf:
      case IndirectLocalPathEntry::LValToRVal:
      case IndirectLocalPathEntry::ParenAggInit:
        // These exist primarily to mark the path as not permitting or
        // supporting lifetime extension.
        break;

      case IndirectLocalPathEntry::LifetimeBoundCall:
      case IndirectLocalPathEntry::TemporaryCopy:
      case IndirectLocalPathEntry::MemberExpr:
      case IndirectLocalPathEntry::GslPointerInit:
      case IndirectLocalPathEntry::GslReferenceInit:
      case IndirectLocalPathEntry::GslPointerAssignment:
        // FIXME: Consider adding a note for these.
        break;

      case IndirectLocalPathEntry::DefaultInit: {
        auto *FD = cast<FieldDecl>(Elem.D);
        SemaRef.Diag(FD->getLocation(),
                     diag::note_init_with_default_member_initializer)
            << FD << nextPathEntryRange(Path, I + 1, L);
        break;
      }

      case IndirectLocalPathEntry::VarInit: {
        const VarDecl *VD = cast<VarDecl>(Elem.D);
        SemaRef.Diag(VD->getLocation(), diag::note_local_var_initializer)
            << VD->getType()->isReferenceType() << VD->isImplicit()
            << VD->getDeclName() << nextPathEntryRange(Path, I + 1, L);
        break;
      }

      case IndirectLocalPathEntry::LambdaCaptureInit: {
        if (!Elem.Capture->capturesVariable())
          break;
        // FIXME: We can't easily tell apart an init-capture from a nested
        // capture of an init-capture.
        const ValueDecl *VD = Elem.Capture->getCapturedVar();
        SemaRef.Diag(Elem.Capture->getLocation(),
                     diag::note_lambda_capture_initializer)
            << VD << VD->isInitCapture() << Elem.Capture->isExplicit()
            << (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD
            << nextPathEntryRange(Path, I + 1, L);
        break;
      }

      case IndirectLocalPathEntry::DefaultArg: {
        const auto *DAE = cast<CXXDefaultArgExpr>(Elem.E);
        const ParmVarDecl *Param = DAE->getParam();
        SemaRef.Diag(Param->getDefaultArgRange().getBegin(),
                     diag::note_init_with_default_argument)
            << Param << nextPathEntryRange(Path, I + 1, L);
        break;
      }
      }
    }

    // We didn't lifetime-extend, so don't go any further; we don't need more
    // warnings or errors on inner temporaries within this one's initializer.
    return false;
  };

  llvm::SmallVector<IndirectLocalPathEntry, 8> Path;
  switch (LK) {
  case LK_Assignment: {
    if (shouldRunGSLAssignmentAnalysis(SemaRef, *AEntity))
      Path.push_back({lifetimes::isAssignmentOperatorLifetimeBound(
                          AEntity->AssignmentOperator)
                          ? IndirectLocalPathEntry::LifetimeBoundCall
                          : IndirectLocalPathEntry::GslPointerAssignment,
                      Init});
    break;
  }
  case LK_LifetimeCapture: {
    if (lifetimes::isPointerLikeType(Init->getType()))
      Path.push_back({IndirectLocalPathEntry::GslPointerInit, Init});
    break;
  }
  default:
    break;
  }

  if (Init->isGLValue())
    visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding,
                                          TemporaryVisitor);
  else
    visitLocalsRetainedByInitializer(
        Path, Init, TemporaryVisitor,
        // Don't revisit the sub inits for the initialization case.
        /*RevisitSubinits=*/!InitEntity);
}

void checkInitLifetime(Sema &SemaRef, const InitializedEntity &Entity,
                       Expr *Init) {
  auto LTResult = getEntityLifetime(&Entity);
  LifetimeKind LK = LTResult.getInt();
  const InitializedEntity *ExtendingEntity = LTResult.getPointer();
  checkExprLifetimeImpl(SemaRef, &Entity, ExtendingEntity, LK,
                        /*AEntity=*/nullptr, /*CapEntity=*/nullptr, Init);
}

void checkExprLifetimeMustTailArg(Sema &SemaRef,
                                  const InitializedEntity &Entity, Expr *Init) {
  checkExprLifetimeImpl(SemaRef, &Entity, nullptr, LK_MustTail,
                        /*AEntity=*/nullptr, /*CapEntity=*/nullptr, Init);
}

void checkAssignmentLifetime(Sema &SemaRef, const AssignedEntity &Entity,
                             Expr *Init) {
  bool EnableDanglingPointerAssignment = !SemaRef.getDiagnostics().isIgnored(
      diag::warn_dangling_pointer_assignment, SourceLocation());
  bool RunAnalysis = (EnableDanglingPointerAssignment &&
                      Entity.LHS->getType()->isPointerType()) ||
                     shouldRunGSLAssignmentAnalysis(SemaRef, Entity);

  if (!RunAnalysis)
    return;

  checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr,
                        /*ExtendingEntity=*/nullptr, LK_Assignment, &Entity,
                        /*CapEntity=*/nullptr, Init);
}

void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity,
                            Expr *Init) {
  if (SemaRef.getDiagnostics().isIgnored(diag::warn_dangling_reference_captured,
                                         SourceLocation()) &&
      SemaRef.getDiagnostics().isIgnored(
          diag::warn_dangling_reference_captured_by_unknown, SourceLocation()))
    return;
  return checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr,
                               /*ExtendingEntity=*/nullptr, LK_LifetimeCapture,
                               /*AEntity=*/nullptr,
                               /*CapEntity=*/&Entity, Init);
}

} // namespace clang::sema
