Path: blob/main/contrib/llvm-project/clang/lib/Sema/CheckExprLifetime.cpp
35234 views
//===--- CheckExprLifetime.cpp --------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "CheckExprLifetime.h"9#include "clang/AST/Decl.h"10#include "clang/AST/Expr.h"11#include "clang/Basic/DiagnosticSema.h"12#include "clang/Sema/Initialization.h"13#include "clang/Sema/Sema.h"14#include "llvm/ADT/PointerIntPair.h"1516namespace clang::sema {17namespace {18enum LifetimeKind {19/// The lifetime of a temporary bound to this entity ends at the end of the20/// full-expression, and that's (probably) fine.21LK_FullExpression,2223/// The lifetime of a temporary bound to this entity is extended to the24/// lifeitme of the entity itself.25LK_Extended,2627/// The lifetime of a temporary bound to this entity probably ends too soon,28/// because the entity is allocated in a new-expression.29LK_New,3031/// The lifetime of a temporary bound to this entity ends too soon, because32/// the entity is a return object.33LK_Return,3435/// The lifetime of a temporary bound to this entity ends too soon, because36/// the entity is the result of a statement expression.37LK_StmtExprResult,3839/// This is a mem-initializer: if it would extend a temporary (other than via40/// a default member initializer), the program is ill-formed.41LK_MemInitializer,4243/// The lifetime of a temporary bound to this entity probably ends too soon,44/// because the entity is a pointer and we assign the address of a temporary45/// object to it.46LK_Assignment,47};48using LifetimeResult =49llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;50} // namespace5152/// Determine the declaration which an initialized entity ultimately refers to,53/// for the purpose of lifetime-extending a temporary bound to a reference in54/// the initialization of \p Entity.55static LifetimeResult56getEntityLifetime(const InitializedEntity *Entity,57const InitializedEntity *InitField = nullptr) {58// C++11 [class.temporary]p5:59switch (Entity->getKind()) {60case InitializedEntity::EK_Variable:61// The temporary [...] persists for the lifetime of the reference62return {Entity, LK_Extended};6364case InitializedEntity::EK_Member:65// For subobjects, we look at the complete object.66if (Entity->getParent())67return getEntityLifetime(Entity->getParent(), Entity);6869// except:70// C++17 [class.base.init]p8:71// A temporary expression bound to a reference member in a72// mem-initializer is ill-formed.73// C++17 [class.base.init]p11:74// A temporary expression bound to a reference member from a75// default member initializer is ill-formed.76//77// The context of p11 and its example suggest that it's only the use of a78// default member initializer from a constructor that makes the program79// ill-formed, not its mere existence, and that it can even be used by80// aggregate initialization.81return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended82: LK_MemInitializer};8384case InitializedEntity::EK_Binding:85// Per [dcl.decomp]p3, the binding is treated as a variable of reference86// type.87return {Entity, LK_Extended};8889case InitializedEntity::EK_Parameter:90case InitializedEntity::EK_Parameter_CF_Audited:91// -- A temporary bound to a reference parameter in a function call92// persists until the completion of the full-expression containing93// the call.94return {nullptr, LK_FullExpression};9596case InitializedEntity::EK_TemplateParameter:97// FIXME: This will always be ill-formed; should we eagerly diagnose it98// here?99return {nullptr, LK_FullExpression};100101case InitializedEntity::EK_Result:102// -- The lifetime of a temporary bound to the returned value in a103// function return statement is not extended; the temporary is104// destroyed at the end of the full-expression in the return statement.105return {nullptr, LK_Return};106107case InitializedEntity::EK_StmtExprResult:108// FIXME: Should we lifetime-extend through the result of a statement109// expression?110return {nullptr, LK_StmtExprResult};111112case InitializedEntity::EK_New:113// -- A temporary bound to a reference in a new-initializer persists114// until the completion of the full-expression containing the115// new-initializer.116return {nullptr, LK_New};117118case InitializedEntity::EK_Temporary:119case InitializedEntity::EK_CompoundLiteralInit:120case InitializedEntity::EK_RelatedResult:121// We don't yet know the storage duration of the surrounding temporary.122// Assume it's got full-expression duration for now, it will patch up our123// storage duration if that's not correct.124return {nullptr, LK_FullExpression};125126case InitializedEntity::EK_ArrayElement:127// For subobjects, we look at the complete object.128return getEntityLifetime(Entity->getParent(), InitField);129130case InitializedEntity::EK_Base:131// For subobjects, we look at the complete object.132if (Entity->getParent())133return getEntityLifetime(Entity->getParent(), InitField);134return {InitField, LK_MemInitializer};135136case InitializedEntity::EK_Delegating:137// We can reach this case for aggregate initialization in a constructor:138// struct A { int &&r; };139// struct B : A { B() : A{0} {} };140// In this case, use the outermost field decl as the context.141return {InitField, LK_MemInitializer};142143case InitializedEntity::EK_BlockElement:144case InitializedEntity::EK_LambdaToBlockConversionBlockElement:145case InitializedEntity::EK_LambdaCapture:146case InitializedEntity::EK_VectorElement:147case InitializedEntity::EK_ComplexElement:148return {nullptr, LK_FullExpression};149150case InitializedEntity::EK_Exception:151// FIXME: Can we diagnose lifetime problems with exceptions?152return {nullptr, LK_FullExpression};153154case InitializedEntity::EK_ParenAggInitMember:155// -- A temporary object bound to a reference element of an aggregate of156// class type initialized from a parenthesized expression-list157// [dcl.init, 9.3] persists until the completion of the full-expression158// containing the expression-list.159return {nullptr, LK_FullExpression};160}161162llvm_unreachable("unknown entity kind");163}164165namespace {166enum ReferenceKind {167/// Lifetime would be extended by a reference binding to a temporary.168RK_ReferenceBinding,169/// Lifetime would be extended by a std::initializer_list object binding to170/// its backing array.171RK_StdInitializerList,172};173174/// A temporary or local variable. This will be one of:175/// * A MaterializeTemporaryExpr.176/// * A DeclRefExpr whose declaration is a local.177/// * An AddrLabelExpr.178/// * A BlockExpr for a block with captures.179using Local = Expr *;180181/// Expressions we stepped over when looking for the local state. Any steps182/// that would inhibit lifetime extension or take us out of subexpressions of183/// the initializer are included.184struct IndirectLocalPathEntry {185enum EntryKind {186DefaultInit,187AddressOf,188VarInit,189LValToRVal,190LifetimeBoundCall,191TemporaryCopy,192LambdaCaptureInit,193GslReferenceInit,194GslPointerInit,195GslPointerAssignment,196} Kind;197Expr *E;198union {199const Decl *D = nullptr;200const LambdaCapture *Capture;201};202IndirectLocalPathEntry() {}203IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}204IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D)205: Kind(K), E(E), D(D) {}206IndirectLocalPathEntry(EntryKind K, Expr *E, const LambdaCapture *Capture)207: Kind(K), E(E), Capture(Capture) {}208};209210using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;211212struct RevertToOldSizeRAII {213IndirectLocalPath &Path;214unsigned OldSize = Path.size();215RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}216~RevertToOldSizeRAII() { Path.resize(OldSize); }217};218219using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,220ReferenceKind RK)>;221} // namespace222223static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) {224for (auto E : Path)225if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)226return true;227return false;228}229230static bool pathContainsInit(IndirectLocalPath &Path) {231return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {232return E.Kind == IndirectLocalPathEntry::DefaultInit ||233E.Kind == IndirectLocalPathEntry::VarInit;234});235}236237static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,238Expr *Init, LocalVisitor Visit,239bool RevisitSubinits,240bool EnableLifetimeWarnings);241242static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,243Expr *Init, ReferenceKind RK,244LocalVisitor Visit,245bool EnableLifetimeWarnings);246247template <typename T> static bool isRecordWithAttr(QualType Type) {248if (auto *RD = Type->getAsCXXRecordDecl())249return RD->hasAttr<T>();250return false;251}252253// Decl::isInStdNamespace will return false for iterators in some STL254// implementations due to them being defined in a namespace outside of the std255// namespace.256static bool isInStlNamespace(const Decl *D) {257const DeclContext *DC = D->getDeclContext();258if (!DC)259return false;260if (const auto *ND = dyn_cast<NamespaceDecl>(DC))261if (const IdentifierInfo *II = ND->getIdentifier()) {262StringRef Name = II->getName();263if (Name.size() >= 2 && Name.front() == '_' &&264(Name[1] == '_' || isUppercase(Name[1])))265return true;266}267268return DC->isStdNamespace();269}270271static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {272if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))273if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()))274return true;275if (!isInStlNamespace(Callee->getParent()))276return false;277if (!isRecordWithAttr<PointerAttr>(278Callee->getFunctionObjectParameterType()) &&279!isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType()))280return false;281if (Callee->getReturnType()->isPointerType() ||282isRecordWithAttr<PointerAttr>(Callee->getReturnType())) {283if (!Callee->getIdentifier())284return false;285return llvm::StringSwitch<bool>(Callee->getName())286.Cases("begin", "rbegin", "cbegin", "crbegin", true)287.Cases("end", "rend", "cend", "crend", true)288.Cases("c_str", "data", "get", true)289// Map and set types.290.Cases("find", "equal_range", "lower_bound", "upper_bound", true)291.Default(false);292} else if (Callee->getReturnType()->isReferenceType()) {293if (!Callee->getIdentifier()) {294auto OO = Callee->getOverloadedOperator();295return OO == OverloadedOperatorKind::OO_Subscript ||296OO == OverloadedOperatorKind::OO_Star;297}298return llvm::StringSwitch<bool>(Callee->getName())299.Cases("front", "back", "at", "top", "value", true)300.Default(false);301}302return false;303}304305static bool shouldTrackFirstArgument(const FunctionDecl *FD) {306if (!FD->getIdentifier() || FD->getNumParams() != 1)307return false;308const auto *RD = FD->getParamDecl(0)->getType()->getPointeeCXXRecordDecl();309if (!FD->isInStdNamespace() || !RD || !RD->isInStdNamespace())310return false;311if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())312return false;313if (FD->getReturnType()->isPointerType() ||314isRecordWithAttr<PointerAttr>(FD->getReturnType())) {315return llvm::StringSwitch<bool>(FD->getName())316.Cases("begin", "rbegin", "cbegin", "crbegin", true)317.Cases("end", "rend", "cend", "crend", true)318.Case("data", true)319.Default(false);320} else if (FD->getReturnType()->isReferenceType()) {321return llvm::StringSwitch<bool>(FD->getName())322.Cases("get", "any_cast", true)323.Default(false);324}325return false;326}327328static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,329LocalVisitor Visit) {330auto VisitPointerArg = [&](const Decl *D, Expr *Arg, bool Value) {331// We are not interested in the temporary base objects of gsl Pointers:332// Temp().ptr; // Here ptr might not dangle.333if (isa<MemberExpr>(Arg->IgnoreImpCasts()))334return;335// Once we initialized a value with a reference, it can no longer dangle.336if (!Value) {337for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {338if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit)339continue;340if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||341PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)342return;343break;344}345}346Path.push_back({Value ? IndirectLocalPathEntry::GslPointerInit347: IndirectLocalPathEntry::GslReferenceInit,348Arg, D});349if (Arg->isGLValue())350visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,351Visit,352/*EnableLifetimeWarnings=*/true);353else354visitLocalsRetainedByInitializer(Path, Arg, Visit, true,355/*EnableLifetimeWarnings=*/true);356Path.pop_back();357};358359if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {360const auto *MD = cast_or_null<CXXMethodDecl>(MCE->getDirectCallee());361if (MD && shouldTrackImplicitObjectArg(MD))362VisitPointerArg(MD, MCE->getImplicitObjectArgument(),363!MD->getReturnType()->isReferenceType());364return;365} else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Call)) {366FunctionDecl *Callee = OCE->getDirectCallee();367if (Callee && Callee->isCXXInstanceMember() &&368shouldTrackImplicitObjectArg(cast<CXXMethodDecl>(Callee)))369VisitPointerArg(Callee, OCE->getArg(0),370!Callee->getReturnType()->isReferenceType());371return;372} else if (auto *CE = dyn_cast<CallExpr>(Call)) {373FunctionDecl *Callee = CE->getDirectCallee();374if (Callee && shouldTrackFirstArgument(Callee))375VisitPointerArg(Callee, CE->getArg(0),376!Callee->getReturnType()->isReferenceType());377return;378}379380if (auto *CCE = dyn_cast<CXXConstructExpr>(Call)) {381const auto *Ctor = CCE->getConstructor();382const CXXRecordDecl *RD = Ctor->getParent();383if (CCE->getNumArgs() > 0 && RD->hasAttr<PointerAttr>())384VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0], true);385}386}387388static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {389const TypeSourceInfo *TSI = FD->getTypeSourceInfo();390if (!TSI)391return false;392// Don't declare this variable in the second operand of the for-statement;393// GCC miscompiles that by ending its lifetime before evaluating the394// third operand. See gcc.gnu.org/PR86769.395AttributedTypeLoc ATL;396for (TypeLoc TL = TSI->getTypeLoc();397(ATL = TL.getAsAdjusted<AttributedTypeLoc>());398TL = ATL.getModifiedLoc()) {399if (ATL.getAttrAs<LifetimeBoundAttr>())400return true;401}402403// Assume that all assignment operators with a "normal" return type return404// *this, that is, an lvalue reference that is the same type as the implicit405// object parameter (or the LHS for a non-member operator$=).406OverloadedOperatorKind OO = FD->getDeclName().getCXXOverloadedOperator();407if (OO == OO_Equal || isCompoundAssignmentOperator(OO)) {408QualType RetT = FD->getReturnType();409if (RetT->isLValueReferenceType()) {410ASTContext &Ctx = FD->getASTContext();411QualType LHST;412auto *MD = dyn_cast<CXXMethodDecl>(FD);413if (MD && MD->isCXXInstanceMember())414LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType());415else416LHST = MD->getParamDecl(0)->getType();417if (Ctx.hasSameType(RetT, LHST))418return true;419}420}421422return false;423}424425static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,426LocalVisitor Visit) {427const FunctionDecl *Callee;428ArrayRef<Expr *> Args;429430if (auto *CE = dyn_cast<CallExpr>(Call)) {431Callee = CE->getDirectCallee();432Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());433} else {434auto *CCE = cast<CXXConstructExpr>(Call);435Callee = CCE->getConstructor();436Args = llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs());437}438if (!Callee)439return;440441Expr *ObjectArg = nullptr;442if (isa<CXXOperatorCallExpr>(Call) && Callee->isCXXInstanceMember()) {443ObjectArg = Args[0];444Args = Args.slice(1);445} else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {446ObjectArg = MCE->getImplicitObjectArgument();447}448449auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) {450Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});451if (Arg->isGLValue())452visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,453Visit,454/*EnableLifetimeWarnings=*/false);455else456visitLocalsRetainedByInitializer(Path, Arg, Visit, true,457/*EnableLifetimeWarnings=*/false);458Path.pop_back();459};460461bool CheckCoroCall = false;462if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {463CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&464RD->hasAttr<CoroReturnTypeAttr>() &&465!Callee->hasAttr<CoroDisableLifetimeBoundAttr>();466}467468if (ObjectArg) {469bool CheckCoroObjArg = CheckCoroCall;470// Coroutine lambda objects with empty capture list are not lifetimebound.471if (auto *LE = dyn_cast<LambdaExpr>(ObjectArg->IgnoreImplicit());472LE && LE->captures().empty())473CheckCoroObjArg = false;474// Allow `get_return_object()` as the object param (__promise) is not475// lifetimebound.476if (Sema::CanBeGetReturnObject(Callee))477CheckCoroObjArg = false;478if (implicitObjectParamIsLifetimeBound(Callee) || CheckCoroObjArg)479VisitLifetimeBoundArg(Callee, ObjectArg);480}481482for (unsigned I = 0,483N = std::min<unsigned>(Callee->getNumParams(), Args.size());484I != N; ++I) {485if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())486VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);487}488}489490/// Visit the locals that would be reachable through a reference bound to the491/// glvalue expression \c Init.492static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,493Expr *Init, ReferenceKind RK,494LocalVisitor Visit,495bool EnableLifetimeWarnings) {496RevertToOldSizeRAII RAII(Path);497498// Walk past any constructs which we can lifetime-extend across.499Expr *Old;500do {501Old = Init;502503if (auto *FE = dyn_cast<FullExpr>(Init))504Init = FE->getSubExpr();505506if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {507// If this is just redundant braces around an initializer, step over it.508if (ILE->isTransparent())509Init = ILE->getInit(0);510}511512// Step over any subobject adjustments; we may have a materialized513// temporary inside them.514Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());515516// Per current approach for DR1376, look through casts to reference type517// when performing lifetime extension.518if (CastExpr *CE = dyn_cast<CastExpr>(Init))519if (CE->getSubExpr()->isGLValue())520Init = CE->getSubExpr();521522// Per the current approach for DR1299, look through array element access523// on array glvalues when performing lifetime extension.524if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init)) {525Init = ASE->getBase();526auto *ICE = dyn_cast<ImplicitCastExpr>(Init);527if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)528Init = ICE->getSubExpr();529else530// We can't lifetime extend through this but we might still find some531// retained temporaries.532return visitLocalsRetainedByInitializer(Path, Init, Visit, true,533EnableLifetimeWarnings);534}535536// Step into CXXDefaultInitExprs so we can diagnose cases where a537// constructor inherits one as an implicit mem-initializer.538if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {539Path.push_back(540{IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});541Init = DIE->getExpr();542}543} while (Init != Old);544545if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {546if (Visit(Path, Local(MTE), RK))547visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit, true,548EnableLifetimeWarnings);549}550551if (auto *M = dyn_cast<MemberExpr>(Init)) {552// Lifetime of a non-reference type field is same as base object.553if (auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());554F && !F->getType()->isReferenceType())555visitLocalsRetainedByInitializer(Path, M->getBase(), Visit, true,556EnableLifetimeWarnings);557}558559if (isa<CallExpr>(Init)) {560if (EnableLifetimeWarnings)561handleGslAnnotatedTypes(Path, Init, Visit);562return visitLifetimeBoundArguments(Path, Init, Visit);563}564565switch (Init->getStmtClass()) {566case Stmt::DeclRefExprClass: {567// If we find the name of a local non-reference parameter, we could have a568// lifetime problem.569auto *DRE = cast<DeclRefExpr>(Init);570auto *VD = dyn_cast<VarDecl>(DRE->getDecl());571if (VD && VD->hasLocalStorage() &&572!DRE->refersToEnclosingVariableOrCapture()) {573if (!VD->getType()->isReferenceType()) {574Visit(Path, Local(DRE), RK);575} else if (isa<ParmVarDecl>(DRE->getDecl())) {576// The lifetime of a reference parameter is unknown; assume it's OK577// for now.578break;579} else if (VD->getInit() && !isVarOnPath(Path, VD)) {580Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});581visitLocalsRetainedByReferenceBinding(Path, VD->getInit(),582RK_ReferenceBinding, Visit,583EnableLifetimeWarnings);584}585}586break;587}588589case Stmt::UnaryOperatorClass: {590// The only unary operator that make sense to handle here591// is Deref. All others don't resolve to a "name." This includes592// handling all sorts of rvalues passed to a unary operator.593const UnaryOperator *U = cast<UnaryOperator>(Init);594if (U->getOpcode() == UO_Deref)595visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true,596EnableLifetimeWarnings);597break;598}599600case Stmt::ArraySectionExprClass: {601visitLocalsRetainedByInitializer(Path,602cast<ArraySectionExpr>(Init)->getBase(),603Visit, true, EnableLifetimeWarnings);604break;605}606607case Stmt::ConditionalOperatorClass:608case Stmt::BinaryConditionalOperatorClass: {609auto *C = cast<AbstractConditionalOperator>(Init);610if (!C->getTrueExpr()->getType()->isVoidType())611visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit,612EnableLifetimeWarnings);613if (!C->getFalseExpr()->getType()->isVoidType())614visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit,615EnableLifetimeWarnings);616break;617}618619case Stmt::CompoundLiteralExprClass: {620if (auto *CLE = dyn_cast<CompoundLiteralExpr>(Init)) {621if (!CLE->isFileScope())622Visit(Path, Local(CLE), RK);623}624break;625}626627// FIXME: Visit the left-hand side of an -> or ->*.628629default:630break;631}632}633634/// Visit the locals that would be reachable through an object initialized by635/// the prvalue expression \c Init.636static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,637Expr *Init, LocalVisitor Visit,638bool RevisitSubinits,639bool EnableLifetimeWarnings) {640RevertToOldSizeRAII RAII(Path);641642Expr *Old;643do {644Old = Init;645646// Step into CXXDefaultInitExprs so we can diagnose cases where a647// constructor inherits one as an implicit mem-initializer.648if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {649Path.push_back(650{IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});651Init = DIE->getExpr();652}653654if (auto *FE = dyn_cast<FullExpr>(Init))655Init = FE->getSubExpr();656657// Dig out the expression which constructs the extended temporary.658Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());659660if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))661Init = BTE->getSubExpr();662663Init = Init->IgnoreParens();664665// Step over value-preserving rvalue casts.666if (auto *CE = dyn_cast<CastExpr>(Init)) {667switch (CE->getCastKind()) {668case CK_LValueToRValue:669// If we can match the lvalue to a const object, we can look at its670// initializer.671Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});672return visitLocalsRetainedByReferenceBinding(673Path, Init, RK_ReferenceBinding,674[&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {675if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {676auto *VD = dyn_cast<VarDecl>(DRE->getDecl());677if (VD && VD->getType().isConstQualified() && VD->getInit() &&678!isVarOnPath(Path, VD)) {679Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});680visitLocalsRetainedByInitializer(681Path, VD->getInit(), Visit, true, EnableLifetimeWarnings);682}683} else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {684if (MTE->getType().isConstQualified())685visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(),686Visit, true,687EnableLifetimeWarnings);688}689return false;690},691EnableLifetimeWarnings);692693// We assume that objects can be retained by pointers cast to integers,694// but not if the integer is cast to floating-point type or to _Complex.695// We assume that casts to 'bool' do not preserve enough information to696// retain a local object.697case CK_NoOp:698case CK_BitCast:699case CK_BaseToDerived:700case CK_DerivedToBase:701case CK_UncheckedDerivedToBase:702case CK_Dynamic:703case CK_ToUnion:704case CK_UserDefinedConversion:705case CK_ConstructorConversion:706case CK_IntegralToPointer:707case CK_PointerToIntegral:708case CK_VectorSplat:709case CK_IntegralCast:710case CK_CPointerToObjCPointerCast:711case CK_BlockPointerToObjCPointerCast:712case CK_AnyPointerToBlockPointerCast:713case CK_AddressSpaceConversion:714break;715716case CK_ArrayToPointerDecay:717// Model array-to-pointer decay as taking the address of the array718// lvalue.719Path.push_back({IndirectLocalPathEntry::AddressOf, CE});720return visitLocalsRetainedByReferenceBinding(Path, CE->getSubExpr(),721RK_ReferenceBinding, Visit,722EnableLifetimeWarnings);723724default:725return;726}727728Init = CE->getSubExpr();729}730} while (Old != Init);731732// C++17 [dcl.init.list]p6:733// initializing an initializer_list object from the array extends the734// lifetime of the array exactly like binding a reference to a temporary.735if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init))736return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(),737RK_StdInitializerList, Visit,738EnableLifetimeWarnings);739740if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {741// We already visited the elements of this initializer list while742// performing the initialization. Don't visit them again unless we've743// changed the lifetime of the initialized entity.744if (!RevisitSubinits)745return;746747if (ILE->isTransparent())748return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit,749RevisitSubinits,750EnableLifetimeWarnings);751752if (ILE->getType()->isArrayType()) {753for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)754visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit,755RevisitSubinits,756EnableLifetimeWarnings);757return;758}759760if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {761assert(RD->isAggregate() && "aggregate init on non-aggregate");762763// If we lifetime-extend a braced initializer which is initializing an764// aggregate, and that aggregate contains reference members which are765// bound to temporaries, those temporaries are also lifetime-extended.766if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&767ILE->getInitializedFieldInUnion()->getType()->isReferenceType())768visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0),769RK_ReferenceBinding, Visit,770EnableLifetimeWarnings);771else {772unsigned Index = 0;773for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)774visitLocalsRetainedByInitializer(Path, ILE->getInit(Index), Visit,775RevisitSubinits,776EnableLifetimeWarnings);777for (const auto *I : RD->fields()) {778if (Index >= ILE->getNumInits())779break;780if (I->isUnnamedBitField())781continue;782Expr *SubInit = ILE->getInit(Index);783if (I->getType()->isReferenceType())784visitLocalsRetainedByReferenceBinding(Path, SubInit,785RK_ReferenceBinding, Visit,786EnableLifetimeWarnings);787else788// This might be either aggregate-initialization of a member or789// initialization of a std::initializer_list object. Regardless,790// we should recursively lifetime-extend that initializer.791visitLocalsRetainedByInitializer(792Path, SubInit, Visit, RevisitSubinits, EnableLifetimeWarnings);793++Index;794}795}796}797return;798}799800// The lifetime of an init-capture is that of the closure object constructed801// by a lambda-expression.802if (auto *LE = dyn_cast<LambdaExpr>(Init)) {803LambdaExpr::capture_iterator CapI = LE->capture_begin();804for (Expr *E : LE->capture_inits()) {805assert(CapI != LE->capture_end());806const LambdaCapture &Cap = *CapI++;807if (!E)808continue;809if (Cap.capturesVariable())810Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});811if (E->isGLValue())812visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding,813Visit, EnableLifetimeWarnings);814else815visitLocalsRetainedByInitializer(Path, E, Visit, true,816EnableLifetimeWarnings);817if (Cap.capturesVariable())818Path.pop_back();819}820}821822// Assume that a copy or move from a temporary references the same objects823// that the temporary does.824if (auto *CCE = dyn_cast<CXXConstructExpr>(Init)) {825if (CCE->getConstructor()->isCopyOrMoveConstructor()) {826if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {827// assert(false && "hit temporary copy path");828Expr *Arg = MTE->getSubExpr();829Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,830CCE->getConstructor()});831visitLocalsRetainedByInitializer(Path, Arg, Visit, true,832/*EnableLifetimeWarnings*/ false);833Path.pop_back();834}835}836}837838if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init)) {839if (EnableLifetimeWarnings)840handleGslAnnotatedTypes(Path, Init, Visit);841return visitLifetimeBoundArguments(Path, Init, Visit);842}843844switch (Init->getStmtClass()) {845case Stmt::UnaryOperatorClass: {846auto *UO = cast<UnaryOperator>(Init);847// If the initializer is the address of a local, we could have a lifetime848// problem.849if (UO->getOpcode() == UO_AddrOf) {850// If this is &rvalue, then it's ill-formed and we have already diagnosed851// it. Don't produce a redundant warning about the lifetime of the852// temporary.853if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))854return;855856Path.push_back({IndirectLocalPathEntry::AddressOf, UO});857visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(),858RK_ReferenceBinding, Visit,859EnableLifetimeWarnings);860}861break;862}863864case Stmt::BinaryOperatorClass: {865// Handle pointer arithmetic.866auto *BO = cast<BinaryOperator>(Init);867BinaryOperatorKind BOK = BO->getOpcode();868if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))869break;870871if (BO->getLHS()->getType()->isPointerType())872visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true,873EnableLifetimeWarnings);874else if (BO->getRHS()->getType()->isPointerType())875visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true,876EnableLifetimeWarnings);877break;878}879880case Stmt::ConditionalOperatorClass:881case Stmt::BinaryConditionalOperatorClass: {882auto *C = cast<AbstractConditionalOperator>(Init);883// In C++, we can have a throw-expression operand, which has 'void' type884// and isn't interesting from a lifetime perspective.885if (!C->getTrueExpr()->getType()->isVoidType())886visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true,887EnableLifetimeWarnings);888if (!C->getFalseExpr()->getType()->isVoidType())889visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true,890EnableLifetimeWarnings);891break;892}893894case Stmt::BlockExprClass:895if (cast<BlockExpr>(Init)->getBlockDecl()->hasCaptures()) {896// This is a local block, whose lifetime is that of the function.897Visit(Path, Local(cast<BlockExpr>(Init)), RK_ReferenceBinding);898}899break;900901case Stmt::AddrLabelExprClass:902// We want to warn if the address of a label would escape the function.903Visit(Path, Local(cast<AddrLabelExpr>(Init)), RK_ReferenceBinding);904break;905906default:907break;908}909}910911/// Whether a path to an object supports lifetime extension.912enum PathLifetimeKind {913/// Lifetime-extend along this path.914Extend,915/// We should lifetime-extend, but we don't because (due to technical916/// limitations) we can't. This happens for default member initializers,917/// which we don't clone for every use, so we don't have a unique918/// MaterializeTemporaryExpr to update.919ShouldExtend,920/// Do not lifetime extend along this path.921NoExtend922};923924/// Determine whether this is an indirect path to a temporary that we are925/// supposed to lifetime-extend along.926static PathLifetimeKind927shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {928PathLifetimeKind Kind = PathLifetimeKind::Extend;929for (auto Elem : Path) {930if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)931Kind = PathLifetimeKind::ShouldExtend;932else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)933return PathLifetimeKind::NoExtend;934}935return Kind;936}937938/// Find the range for the first interesting entry in the path at or after I.939static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,940Expr *E) {941for (unsigned N = Path.size(); I != N; ++I) {942switch (Path[I].Kind) {943case IndirectLocalPathEntry::AddressOf:944case IndirectLocalPathEntry::LValToRVal:945case IndirectLocalPathEntry::LifetimeBoundCall:946case IndirectLocalPathEntry::TemporaryCopy:947case IndirectLocalPathEntry::GslReferenceInit:948case IndirectLocalPathEntry::GslPointerInit:949case IndirectLocalPathEntry::GslPointerAssignment:950// These exist primarily to mark the path as not permitting or951// supporting lifetime extension.952break;953954case IndirectLocalPathEntry::VarInit:955if (cast<VarDecl>(Path[I].D)->isImplicit())956return SourceRange();957[[fallthrough]];958case IndirectLocalPathEntry::DefaultInit:959return Path[I].E->getSourceRange();960961case IndirectLocalPathEntry::LambdaCaptureInit:962if (!Path[I].Capture->capturesVariable())963continue;964return Path[I].E->getSourceRange();965}966}967return E->getSourceRange();968}969970static bool pathOnlyHandlesGslPointer(IndirectLocalPath &Path) {971for (const auto &It : llvm::reverse(Path)) {972switch (It.Kind) {973case IndirectLocalPathEntry::VarInit:974case IndirectLocalPathEntry::AddressOf:975case IndirectLocalPathEntry::LifetimeBoundCall:976continue;977case IndirectLocalPathEntry::GslPointerInit:978case IndirectLocalPathEntry::GslReferenceInit:979case IndirectLocalPathEntry::GslPointerAssignment:980return true;981default:982return false;983}984}985return false;986}987988static void checkExprLifetimeImpl(Sema &SemaRef,989const InitializedEntity *InitEntity,990const InitializedEntity *ExtendingEntity,991LifetimeKind LK,992const AssignedEntity *AEntity, Expr *Init,993bool EnableLifetimeWarnings) {994assert((AEntity && LK == LK_Assignment) ||995(InitEntity && LK != LK_Assignment));996// If this entity doesn't have an interesting lifetime, don't bother looking997// for temporaries within its initializer.998if (LK == LK_FullExpression)999return;10001001// FIXME: consider moving the TemporaryVisitor and visitLocalsRetained*1002// functions to a dedicated class.1003auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L,1004ReferenceKind RK) -> bool {1005SourceRange DiagRange = nextPathEntryRange(Path, 0, L);1006SourceLocation DiagLoc = DiagRange.getBegin();10071008auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);10091010bool IsGslPtrValueFromGslTempOwner = false;1011bool IsLocalGslOwner = false;1012if (pathOnlyHandlesGslPointer(Path)) {1013if (isa<DeclRefExpr>(L)) {1014// We do not want to follow the references when returning a pointer1015// originating from a local owner to avoid the following false positive:1016// int &p = *localUniquePtr;1017// someContainer.add(std::move(localUniquePtr));1018// return p;1019IsLocalGslOwner = isRecordWithAttr<OwnerAttr>(L->getType());1020if (pathContainsInit(Path) || !IsLocalGslOwner)1021return false;1022} else {1023IsGslPtrValueFromGslTempOwner =1024MTE && !MTE->getExtendingDecl() &&1025isRecordWithAttr<OwnerAttr>(MTE->getType());1026// Skipping a chain of initializing gsl::Pointer annotated objects.1027// We are looking only for the final source to find out if it was1028// a local or temporary owner or the address of a local variable/param.1029if (!IsGslPtrValueFromGslTempOwner)1030return true;1031}1032}10331034switch (LK) {1035case LK_FullExpression:1036llvm_unreachable("already handled this");10371038case LK_Extended: {1039if (!MTE) {1040// The initialized entity has lifetime beyond the full-expression,1041// and the local entity does too, so don't warn.1042//1043// FIXME: We should consider warning if a static / thread storage1044// duration variable retains an automatic storage duration local.1045return false;1046}10471048if (IsGslPtrValueFromGslTempOwner && DiagLoc.isValid()) {1049SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)1050<< DiagRange;1051return false;1052}10531054switch (shouldLifetimeExtendThroughPath(Path)) {1055case PathLifetimeKind::Extend:1056// Update the storage duration of the materialized temporary.1057// FIXME: Rebuild the expression instead of mutating it.1058MTE->setExtendingDecl(ExtendingEntity->getDecl(),1059ExtendingEntity->allocateManglingNumber());1060// Also visit the temporaries lifetime-extended by this initializer.1061return true;10621063case PathLifetimeKind::ShouldExtend:1064// We're supposed to lifetime-extend the temporary along this path (per1065// the resolution of DR1815), but we don't support that yet.1066//1067// FIXME: Properly handle this situation. Perhaps the easiest approach1068// would be to clone the initializer expression on each use that would1069// lifetime extend its temporaries.1070SemaRef.Diag(DiagLoc, diag::warn_unsupported_lifetime_extension)1071<< RK << DiagRange;1072break;10731074case PathLifetimeKind::NoExtend:1075// If the path goes through the initialization of a variable or field,1076// it can't possibly reach a temporary created in this full-expression.1077// We will have already diagnosed any problems with the initializer.1078if (pathContainsInit(Path))1079return false;10801081SemaRef.Diag(DiagLoc, diag::warn_dangling_variable)1082<< RK << !InitEntity->getParent()1083<< ExtendingEntity->getDecl()->isImplicit()1084<< ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;1085break;1086}1087break;1088}10891090case LK_Assignment: {1091if (!MTE || pathContainsInit(Path))1092return false;1093assert(shouldLifetimeExtendThroughPath(Path) ==1094PathLifetimeKind::NoExtend &&1095"No lifetime extension for assignments");1096SemaRef.Diag(DiagLoc,1097IsGslPtrValueFromGslTempOwner1098? diag::warn_dangling_lifetime_pointer_assignment1099: diag::warn_dangling_pointer_assignment)1100<< AEntity->LHS << DiagRange;1101return false;1102}1103case LK_MemInitializer: {1104if (MTE) {1105// Under C++ DR1696, if a mem-initializer (or a default member1106// initializer used by the absence of one) would lifetime-extend a1107// temporary, the program is ill-formed.1108if (auto *ExtendingDecl =1109ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {1110if (IsGslPtrValueFromGslTempOwner) {1111SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)1112<< ExtendingDecl << DiagRange;1113SemaRef.Diag(ExtendingDecl->getLocation(),1114diag::note_ref_or_ptr_member_declared_here)1115<< true;1116return false;1117}1118bool IsSubobjectMember = ExtendingEntity != InitEntity;1119SemaRef.Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) !=1120PathLifetimeKind::NoExtend1121? diag::err_dangling_member1122: diag::warn_dangling_member)1123<< ExtendingDecl << IsSubobjectMember << RK << DiagRange;1124// Don't bother adding a note pointing to the field if we're inside1125// its default member initializer; our primary diagnostic points to1126// the same place in that case.1127if (Path.empty() ||1128Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {1129SemaRef.Diag(ExtendingDecl->getLocation(),1130diag::note_lifetime_extending_member_declared_here)1131<< RK << IsSubobjectMember;1132}1133} else {1134// We have a mem-initializer but no particular field within it; this1135// is either a base class or a delegating initializer directly1136// initializing the base-class from something that doesn't live long1137// enough.1138//1139// FIXME: Warn on this.1140return false;1141}1142} else {1143// Paths via a default initializer can only occur during error recovery1144// (there's no other way that a default initializer can refer to a1145// local). Don't produce a bogus warning on those cases.1146if (pathContainsInit(Path))1147return false;11481149// Suppress false positives for code like the one below:1150// Ctor(unique_ptr<T> up) : member(*up), member2(move(up)) {}1151if (IsLocalGslOwner && pathOnlyHandlesGslPointer(Path))1152return false;11531154auto *DRE = dyn_cast<DeclRefExpr>(L);1155auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;1156if (!VD) {1157// A member was initialized to a local block.1158// FIXME: Warn on this.1159return false;1160}11611162if (auto *Member =1163ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {1164bool IsPointer = !Member->getType()->isReferenceType();1165SemaRef.Diag(DiagLoc,1166IsPointer ? diag::warn_init_ptr_member_to_parameter_addr1167: diag::warn_bind_ref_member_to_parameter)1168<< Member << VD << isa<ParmVarDecl>(VD) << DiagRange;1169SemaRef.Diag(Member->getLocation(),1170diag::note_ref_or_ptr_member_declared_here)1171<< (unsigned)IsPointer;1172}1173}1174break;1175}11761177case LK_New:1178if (isa<MaterializeTemporaryExpr>(L)) {1179if (IsGslPtrValueFromGslTempOwner)1180SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)1181<< DiagRange;1182else1183SemaRef.Diag(DiagLoc, RK == RK_ReferenceBinding1184? diag::warn_new_dangling_reference1185: diag::warn_new_dangling_initializer_list)1186<< !InitEntity->getParent() << DiagRange;1187} else {1188// We can't determine if the allocation outlives the local declaration.1189return false;1190}1191break;11921193case LK_Return:1194case LK_StmtExprResult:1195if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {1196// We can't determine if the local variable outlives the statement1197// expression.1198if (LK == LK_StmtExprResult)1199return false;1200SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)1201<< InitEntity->getType()->isReferenceType() << DRE->getDecl()1202<< isa<ParmVarDecl>(DRE->getDecl()) << DiagRange;1203} else if (isa<BlockExpr>(L)) {1204SemaRef.Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;1205} else if (isa<AddrLabelExpr>(L)) {1206// Don't warn when returning a label from a statement expression.1207// Leaving the scope doesn't end its lifetime.1208if (LK == LK_StmtExprResult)1209return false;1210SemaRef.Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;1211} else if (auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {1212SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)1213<< InitEntity->getType()->isReferenceType() << CLE->getInitializer()1214<< 2 << DiagRange;1215} else {1216// P2748R5: Disallow Binding a Returned Glvalue to a Temporary.1217// [stmt.return]/p6: In a function whose return type is a reference,1218// other than an invented function for std::is_convertible ([meta.rel]),1219// a return statement that binds the returned reference to a temporary1220// expression ([class.temporary]) is ill-formed.1221if (SemaRef.getLangOpts().CPlusPlus26 &&1222InitEntity->getType()->isReferenceType())1223SemaRef.Diag(DiagLoc, diag::err_ret_local_temp_ref)1224<< InitEntity->getType()->isReferenceType() << DiagRange;1225else1226SemaRef.Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)1227<< InitEntity->getType()->isReferenceType() << DiagRange;1228}1229break;1230}12311232for (unsigned I = 0; I != Path.size(); ++I) {1233auto Elem = Path[I];12341235switch (Elem.Kind) {1236case IndirectLocalPathEntry::AddressOf:1237case IndirectLocalPathEntry::LValToRVal:1238// These exist primarily to mark the path as not permitting or1239// supporting lifetime extension.1240break;12411242case IndirectLocalPathEntry::LifetimeBoundCall:1243case IndirectLocalPathEntry::TemporaryCopy:1244case IndirectLocalPathEntry::GslPointerInit:1245case IndirectLocalPathEntry::GslReferenceInit:1246case IndirectLocalPathEntry::GslPointerAssignment:1247// FIXME: Consider adding a note for these.1248break;12491250case IndirectLocalPathEntry::DefaultInit: {1251auto *FD = cast<FieldDecl>(Elem.D);1252SemaRef.Diag(FD->getLocation(),1253diag::note_init_with_default_member_initializer)1254<< FD << nextPathEntryRange(Path, I + 1, L);1255break;1256}12571258case IndirectLocalPathEntry::VarInit: {1259const VarDecl *VD = cast<VarDecl>(Elem.D);1260SemaRef.Diag(VD->getLocation(), diag::note_local_var_initializer)1261<< VD->getType()->isReferenceType() << VD->isImplicit()1262<< VD->getDeclName() << nextPathEntryRange(Path, I + 1, L);1263break;1264}12651266case IndirectLocalPathEntry::LambdaCaptureInit:1267if (!Elem.Capture->capturesVariable())1268break;1269// FIXME: We can't easily tell apart an init-capture from a nested1270// capture of an init-capture.1271const ValueDecl *VD = Elem.Capture->getCapturedVar();1272SemaRef.Diag(Elem.Capture->getLocation(),1273diag::note_lambda_capture_initializer)1274<< VD << VD->isInitCapture() << Elem.Capture->isExplicit()1275<< (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD1276<< nextPathEntryRange(Path, I + 1, L);1277break;1278}1279}12801281// We didn't lifetime-extend, so don't go any further; we don't need more1282// warnings or errors on inner temporaries within this one's initializer.1283return false;1284};12851286llvm::SmallVector<IndirectLocalPathEntry, 8> Path;1287if (EnableLifetimeWarnings && LK == LK_Assignment &&1288isRecordWithAttr<PointerAttr>(AEntity->LHS->getType()))1289Path.push_back({IndirectLocalPathEntry::GslPointerAssignment, Init});12901291if (Init->isGLValue())1292visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding,1293TemporaryVisitor,1294EnableLifetimeWarnings);1295else1296visitLocalsRetainedByInitializer(1297Path, Init, TemporaryVisitor,1298// Don't revisit the sub inits for the intialization case.1299/*RevisitSubinits=*/!InitEntity, EnableLifetimeWarnings);1300}13011302void checkExprLifetime(Sema &SemaRef, const InitializedEntity &Entity,1303Expr *Init) {1304auto LTResult = getEntityLifetime(&Entity);1305LifetimeKind LK = LTResult.getInt();1306const InitializedEntity *ExtendingEntity = LTResult.getPointer();1307bool EnableLifetimeWarnings = !SemaRef.getDiagnostics().isIgnored(1308diag::warn_dangling_lifetime_pointer, SourceLocation());1309checkExprLifetimeImpl(SemaRef, &Entity, ExtendingEntity, LK,1310/*AEntity*/ nullptr, Init, EnableLifetimeWarnings);1311}13121313void checkExprLifetime(Sema &SemaRef, const AssignedEntity &Entity,1314Expr *Init) {1315bool EnableLifetimeWarnings = !SemaRef.getDiagnostics().isIgnored(1316diag::warn_dangling_lifetime_pointer, SourceLocation());1317bool RunAnalysis = Entity.LHS->getType()->isPointerType() ||1318(EnableLifetimeWarnings &&1319isRecordWithAttr<PointerAttr>(Entity.LHS->getType()));13201321if (!RunAnalysis)1322return;13231324checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr,1325/*ExtendingEntity=*/nullptr, LK_Assignment, &Entity,1326Init, EnableLifetimeWarnings);1327}13281329} // namespace clang::sema133013311332