10fca6ea1SDimitry Andric //===--- CheckExprLifetime.cpp --------------------------------------------===//
20fca6ea1SDimitry Andric //
30fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60fca6ea1SDimitry Andric //
70fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
80fca6ea1SDimitry Andric
90fca6ea1SDimitry Andric #include "CheckExprLifetime.h"
10*52418fc2SDimitry Andric #include "clang/AST/Decl.h"
110fca6ea1SDimitry Andric #include "clang/AST/Expr.h"
120fca6ea1SDimitry Andric #include "clang/Basic/DiagnosticSema.h"
130fca6ea1SDimitry Andric #include "clang/Sema/Initialization.h"
140fca6ea1SDimitry Andric #include "clang/Sema/Sema.h"
150fca6ea1SDimitry Andric #include "llvm/ADT/PointerIntPair.h"
160fca6ea1SDimitry Andric
170fca6ea1SDimitry Andric namespace clang::sema {
180fca6ea1SDimitry Andric namespace {
190fca6ea1SDimitry Andric enum LifetimeKind {
200fca6ea1SDimitry Andric /// The lifetime of a temporary bound to this entity ends at the end of the
210fca6ea1SDimitry Andric /// full-expression, and that's (probably) fine.
220fca6ea1SDimitry Andric LK_FullExpression,
230fca6ea1SDimitry Andric
240fca6ea1SDimitry Andric /// The lifetime of a temporary bound to this entity is extended to the
250fca6ea1SDimitry Andric /// lifeitme of the entity itself.
260fca6ea1SDimitry Andric LK_Extended,
270fca6ea1SDimitry Andric
280fca6ea1SDimitry Andric /// The lifetime of a temporary bound to this entity probably ends too soon,
290fca6ea1SDimitry Andric /// because the entity is allocated in a new-expression.
300fca6ea1SDimitry Andric LK_New,
310fca6ea1SDimitry Andric
320fca6ea1SDimitry Andric /// The lifetime of a temporary bound to this entity ends too soon, because
330fca6ea1SDimitry Andric /// the entity is a return object.
340fca6ea1SDimitry Andric LK_Return,
350fca6ea1SDimitry Andric
360fca6ea1SDimitry Andric /// The lifetime of a temporary bound to this entity ends too soon, because
370fca6ea1SDimitry Andric /// the entity is the result of a statement expression.
380fca6ea1SDimitry Andric LK_StmtExprResult,
390fca6ea1SDimitry Andric
400fca6ea1SDimitry Andric /// This is a mem-initializer: if it would extend a temporary (other than via
410fca6ea1SDimitry Andric /// a default member initializer), the program is ill-formed.
420fca6ea1SDimitry Andric LK_MemInitializer,
430fca6ea1SDimitry Andric
440fca6ea1SDimitry Andric /// The lifetime of a temporary bound to this entity probably ends too soon,
450fca6ea1SDimitry Andric /// because the entity is a pointer and we assign the address of a temporary
460fca6ea1SDimitry Andric /// object to it.
470fca6ea1SDimitry Andric LK_Assignment,
480fca6ea1SDimitry Andric };
490fca6ea1SDimitry Andric using LifetimeResult =
500fca6ea1SDimitry Andric llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
510fca6ea1SDimitry Andric } // namespace
520fca6ea1SDimitry Andric
530fca6ea1SDimitry Andric /// Determine the declaration which an initialized entity ultimately refers to,
540fca6ea1SDimitry Andric /// for the purpose of lifetime-extending a temporary bound to a reference in
550fca6ea1SDimitry Andric /// the initialization of \p Entity.
560fca6ea1SDimitry Andric static LifetimeResult
getEntityLifetime(const InitializedEntity * Entity,const InitializedEntity * InitField=nullptr)570fca6ea1SDimitry Andric getEntityLifetime(const InitializedEntity *Entity,
580fca6ea1SDimitry Andric const InitializedEntity *InitField = nullptr) {
590fca6ea1SDimitry Andric // C++11 [class.temporary]p5:
600fca6ea1SDimitry Andric switch (Entity->getKind()) {
610fca6ea1SDimitry Andric case InitializedEntity::EK_Variable:
620fca6ea1SDimitry Andric // The temporary [...] persists for the lifetime of the reference
630fca6ea1SDimitry Andric return {Entity, LK_Extended};
640fca6ea1SDimitry Andric
650fca6ea1SDimitry Andric case InitializedEntity::EK_Member:
660fca6ea1SDimitry Andric // For subobjects, we look at the complete object.
670fca6ea1SDimitry Andric if (Entity->getParent())
680fca6ea1SDimitry Andric return getEntityLifetime(Entity->getParent(), Entity);
690fca6ea1SDimitry Andric
700fca6ea1SDimitry Andric // except:
710fca6ea1SDimitry Andric // C++17 [class.base.init]p8:
720fca6ea1SDimitry Andric // A temporary expression bound to a reference member in a
730fca6ea1SDimitry Andric // mem-initializer is ill-formed.
740fca6ea1SDimitry Andric // C++17 [class.base.init]p11:
750fca6ea1SDimitry Andric // A temporary expression bound to a reference member from a
760fca6ea1SDimitry Andric // default member initializer is ill-formed.
770fca6ea1SDimitry Andric //
780fca6ea1SDimitry Andric // The context of p11 and its example suggest that it's only the use of a
790fca6ea1SDimitry Andric // default member initializer from a constructor that makes the program
800fca6ea1SDimitry Andric // ill-formed, not its mere existence, and that it can even be used by
810fca6ea1SDimitry Andric // aggregate initialization.
820fca6ea1SDimitry Andric return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
830fca6ea1SDimitry Andric : LK_MemInitializer};
840fca6ea1SDimitry Andric
850fca6ea1SDimitry Andric case InitializedEntity::EK_Binding:
860fca6ea1SDimitry Andric // Per [dcl.decomp]p3, the binding is treated as a variable of reference
870fca6ea1SDimitry Andric // type.
880fca6ea1SDimitry Andric return {Entity, LK_Extended};
890fca6ea1SDimitry Andric
900fca6ea1SDimitry Andric case InitializedEntity::EK_Parameter:
910fca6ea1SDimitry Andric case InitializedEntity::EK_Parameter_CF_Audited:
920fca6ea1SDimitry Andric // -- A temporary bound to a reference parameter in a function call
930fca6ea1SDimitry Andric // persists until the completion of the full-expression containing
940fca6ea1SDimitry Andric // the call.
950fca6ea1SDimitry Andric return {nullptr, LK_FullExpression};
960fca6ea1SDimitry Andric
970fca6ea1SDimitry Andric case InitializedEntity::EK_TemplateParameter:
980fca6ea1SDimitry Andric // FIXME: This will always be ill-formed; should we eagerly diagnose it
990fca6ea1SDimitry Andric // here?
1000fca6ea1SDimitry Andric return {nullptr, LK_FullExpression};
1010fca6ea1SDimitry Andric
1020fca6ea1SDimitry Andric case InitializedEntity::EK_Result:
1030fca6ea1SDimitry Andric // -- The lifetime of a temporary bound to the returned value in a
1040fca6ea1SDimitry Andric // function return statement is not extended; the temporary is
1050fca6ea1SDimitry Andric // destroyed at the end of the full-expression in the return statement.
1060fca6ea1SDimitry Andric return {nullptr, LK_Return};
1070fca6ea1SDimitry Andric
1080fca6ea1SDimitry Andric case InitializedEntity::EK_StmtExprResult:
1090fca6ea1SDimitry Andric // FIXME: Should we lifetime-extend through the result of a statement
1100fca6ea1SDimitry Andric // expression?
1110fca6ea1SDimitry Andric return {nullptr, LK_StmtExprResult};
1120fca6ea1SDimitry Andric
1130fca6ea1SDimitry Andric case InitializedEntity::EK_New:
1140fca6ea1SDimitry Andric // -- A temporary bound to a reference in a new-initializer persists
1150fca6ea1SDimitry Andric // until the completion of the full-expression containing the
1160fca6ea1SDimitry Andric // new-initializer.
1170fca6ea1SDimitry Andric return {nullptr, LK_New};
1180fca6ea1SDimitry Andric
1190fca6ea1SDimitry Andric case InitializedEntity::EK_Temporary:
1200fca6ea1SDimitry Andric case InitializedEntity::EK_CompoundLiteralInit:
1210fca6ea1SDimitry Andric case InitializedEntity::EK_RelatedResult:
1220fca6ea1SDimitry Andric // We don't yet know the storage duration of the surrounding temporary.
1230fca6ea1SDimitry Andric // Assume it's got full-expression duration for now, it will patch up our
1240fca6ea1SDimitry Andric // storage duration if that's not correct.
1250fca6ea1SDimitry Andric return {nullptr, LK_FullExpression};
1260fca6ea1SDimitry Andric
1270fca6ea1SDimitry Andric case InitializedEntity::EK_ArrayElement:
1280fca6ea1SDimitry Andric // For subobjects, we look at the complete object.
1290fca6ea1SDimitry Andric return getEntityLifetime(Entity->getParent(), InitField);
1300fca6ea1SDimitry Andric
1310fca6ea1SDimitry Andric case InitializedEntity::EK_Base:
1320fca6ea1SDimitry Andric // For subobjects, we look at the complete object.
1330fca6ea1SDimitry Andric if (Entity->getParent())
1340fca6ea1SDimitry Andric return getEntityLifetime(Entity->getParent(), InitField);
1350fca6ea1SDimitry Andric return {InitField, LK_MemInitializer};
1360fca6ea1SDimitry Andric
1370fca6ea1SDimitry Andric case InitializedEntity::EK_Delegating:
1380fca6ea1SDimitry Andric // We can reach this case for aggregate initialization in a constructor:
1390fca6ea1SDimitry Andric // struct A { int &&r; };
1400fca6ea1SDimitry Andric // struct B : A { B() : A{0} {} };
1410fca6ea1SDimitry Andric // In this case, use the outermost field decl as the context.
1420fca6ea1SDimitry Andric return {InitField, LK_MemInitializer};
1430fca6ea1SDimitry Andric
1440fca6ea1SDimitry Andric case InitializedEntity::EK_BlockElement:
1450fca6ea1SDimitry Andric case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
1460fca6ea1SDimitry Andric case InitializedEntity::EK_LambdaCapture:
1470fca6ea1SDimitry Andric case InitializedEntity::EK_VectorElement:
1480fca6ea1SDimitry Andric case InitializedEntity::EK_ComplexElement:
1490fca6ea1SDimitry Andric return {nullptr, LK_FullExpression};
1500fca6ea1SDimitry Andric
1510fca6ea1SDimitry Andric case InitializedEntity::EK_Exception:
1520fca6ea1SDimitry Andric // FIXME: Can we diagnose lifetime problems with exceptions?
1530fca6ea1SDimitry Andric return {nullptr, LK_FullExpression};
1540fca6ea1SDimitry Andric
1550fca6ea1SDimitry Andric case InitializedEntity::EK_ParenAggInitMember:
1560fca6ea1SDimitry Andric // -- A temporary object bound to a reference element of an aggregate of
1570fca6ea1SDimitry Andric // class type initialized from a parenthesized expression-list
1580fca6ea1SDimitry Andric // [dcl.init, 9.3] persists until the completion of the full-expression
1590fca6ea1SDimitry Andric // containing the expression-list.
1600fca6ea1SDimitry Andric return {nullptr, LK_FullExpression};
1610fca6ea1SDimitry Andric }
1620fca6ea1SDimitry Andric
1630fca6ea1SDimitry Andric llvm_unreachable("unknown entity kind");
1640fca6ea1SDimitry Andric }
1650fca6ea1SDimitry Andric
1660fca6ea1SDimitry Andric namespace {
1670fca6ea1SDimitry Andric enum ReferenceKind {
1680fca6ea1SDimitry Andric /// Lifetime would be extended by a reference binding to a temporary.
1690fca6ea1SDimitry Andric RK_ReferenceBinding,
1700fca6ea1SDimitry Andric /// Lifetime would be extended by a std::initializer_list object binding to
1710fca6ea1SDimitry Andric /// its backing array.
1720fca6ea1SDimitry Andric RK_StdInitializerList,
1730fca6ea1SDimitry Andric };
1740fca6ea1SDimitry Andric
1750fca6ea1SDimitry Andric /// A temporary or local variable. This will be one of:
1760fca6ea1SDimitry Andric /// * A MaterializeTemporaryExpr.
1770fca6ea1SDimitry Andric /// * A DeclRefExpr whose declaration is a local.
1780fca6ea1SDimitry Andric /// * An AddrLabelExpr.
1790fca6ea1SDimitry Andric /// * A BlockExpr for a block with captures.
1800fca6ea1SDimitry Andric using Local = Expr *;
1810fca6ea1SDimitry Andric
1820fca6ea1SDimitry Andric /// Expressions we stepped over when looking for the local state. Any steps
1830fca6ea1SDimitry Andric /// that would inhibit lifetime extension or take us out of subexpressions of
1840fca6ea1SDimitry Andric /// the initializer are included.
1850fca6ea1SDimitry Andric struct IndirectLocalPathEntry {
1860fca6ea1SDimitry Andric enum EntryKind {
1870fca6ea1SDimitry Andric DefaultInit,
1880fca6ea1SDimitry Andric AddressOf,
1890fca6ea1SDimitry Andric VarInit,
1900fca6ea1SDimitry Andric LValToRVal,
1910fca6ea1SDimitry Andric LifetimeBoundCall,
1920fca6ea1SDimitry Andric TemporaryCopy,
1930fca6ea1SDimitry Andric LambdaCaptureInit,
1940fca6ea1SDimitry Andric GslReferenceInit,
1950fca6ea1SDimitry Andric GslPointerInit,
1960fca6ea1SDimitry Andric GslPointerAssignment,
1970fca6ea1SDimitry Andric } Kind;
1980fca6ea1SDimitry Andric Expr *E;
1990fca6ea1SDimitry Andric union {
2000fca6ea1SDimitry Andric const Decl *D = nullptr;
2010fca6ea1SDimitry Andric const LambdaCapture *Capture;
2020fca6ea1SDimitry Andric };
IndirectLocalPathEntryclang::sema::__anone4608efb0211::IndirectLocalPathEntry2030fca6ea1SDimitry Andric IndirectLocalPathEntry() {}
IndirectLocalPathEntryclang::sema::__anone4608efb0211::IndirectLocalPathEntry2040fca6ea1SDimitry Andric IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
IndirectLocalPathEntryclang::sema::__anone4608efb0211::IndirectLocalPathEntry2050fca6ea1SDimitry Andric IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D)
2060fca6ea1SDimitry Andric : Kind(K), E(E), D(D) {}
IndirectLocalPathEntryclang::sema::__anone4608efb0211::IndirectLocalPathEntry2070fca6ea1SDimitry Andric IndirectLocalPathEntry(EntryKind K, Expr *E, const LambdaCapture *Capture)
2080fca6ea1SDimitry Andric : Kind(K), E(E), Capture(Capture) {}
2090fca6ea1SDimitry Andric };
2100fca6ea1SDimitry Andric
2110fca6ea1SDimitry Andric using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;
2120fca6ea1SDimitry Andric
2130fca6ea1SDimitry Andric struct RevertToOldSizeRAII {
2140fca6ea1SDimitry Andric IndirectLocalPath &Path;
2150fca6ea1SDimitry Andric unsigned OldSize = Path.size();
RevertToOldSizeRAIIclang::sema::__anone4608efb0211::RevertToOldSizeRAII2160fca6ea1SDimitry Andric RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
~RevertToOldSizeRAIIclang::sema::__anone4608efb0211::RevertToOldSizeRAII2170fca6ea1SDimitry Andric ~RevertToOldSizeRAII() { Path.resize(OldSize); }
2180fca6ea1SDimitry Andric };
2190fca6ea1SDimitry Andric
2200fca6ea1SDimitry Andric using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
2210fca6ea1SDimitry Andric ReferenceKind RK)>;
2220fca6ea1SDimitry Andric } // namespace
2230fca6ea1SDimitry Andric
isVarOnPath(IndirectLocalPath & Path,VarDecl * VD)2240fca6ea1SDimitry Andric static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) {
2250fca6ea1SDimitry Andric for (auto E : Path)
2260fca6ea1SDimitry Andric if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
2270fca6ea1SDimitry Andric return true;
2280fca6ea1SDimitry Andric return false;
2290fca6ea1SDimitry Andric }
2300fca6ea1SDimitry Andric
pathContainsInit(IndirectLocalPath & Path)2310fca6ea1SDimitry Andric static bool pathContainsInit(IndirectLocalPath &Path) {
2320fca6ea1SDimitry Andric return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
2330fca6ea1SDimitry Andric return E.Kind == IndirectLocalPathEntry::DefaultInit ||
2340fca6ea1SDimitry Andric E.Kind == IndirectLocalPathEntry::VarInit;
2350fca6ea1SDimitry Andric });
2360fca6ea1SDimitry Andric }
2370fca6ea1SDimitry Andric
2380fca6ea1SDimitry Andric static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
2390fca6ea1SDimitry Andric Expr *Init, LocalVisitor Visit,
2400fca6ea1SDimitry Andric bool RevisitSubinits,
2410fca6ea1SDimitry Andric bool EnableLifetimeWarnings);
2420fca6ea1SDimitry Andric
2430fca6ea1SDimitry Andric static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
2440fca6ea1SDimitry Andric Expr *Init, ReferenceKind RK,
2450fca6ea1SDimitry Andric LocalVisitor Visit,
2460fca6ea1SDimitry Andric bool EnableLifetimeWarnings);
2470fca6ea1SDimitry Andric
isRecordWithAttr(QualType Type)2480fca6ea1SDimitry Andric template <typename T> static bool isRecordWithAttr(QualType Type) {
2490fca6ea1SDimitry Andric if (auto *RD = Type->getAsCXXRecordDecl())
2500fca6ea1SDimitry Andric return RD->hasAttr<T>();
2510fca6ea1SDimitry Andric return false;
2520fca6ea1SDimitry Andric }
2530fca6ea1SDimitry Andric
2540fca6ea1SDimitry Andric // Decl::isInStdNamespace will return false for iterators in some STL
2550fca6ea1SDimitry Andric // implementations due to them being defined in a namespace outside of the std
2560fca6ea1SDimitry Andric // namespace.
isInStlNamespace(const Decl * D)2570fca6ea1SDimitry Andric static bool isInStlNamespace(const Decl *D) {
2580fca6ea1SDimitry Andric const DeclContext *DC = D->getDeclContext();
2590fca6ea1SDimitry Andric if (!DC)
2600fca6ea1SDimitry Andric return false;
2610fca6ea1SDimitry Andric if (const auto *ND = dyn_cast<NamespaceDecl>(DC))
2620fca6ea1SDimitry Andric if (const IdentifierInfo *II = ND->getIdentifier()) {
2630fca6ea1SDimitry Andric StringRef Name = II->getName();
2640fca6ea1SDimitry Andric if (Name.size() >= 2 && Name.front() == '_' &&
2650fca6ea1SDimitry Andric (Name[1] == '_' || isUppercase(Name[1])))
2660fca6ea1SDimitry Andric return true;
2670fca6ea1SDimitry Andric }
2680fca6ea1SDimitry Andric
2690fca6ea1SDimitry Andric return DC->isStdNamespace();
2700fca6ea1SDimitry Andric }
2710fca6ea1SDimitry Andric
shouldTrackImplicitObjectArg(const CXXMethodDecl * Callee)2720fca6ea1SDimitry Andric static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
2730fca6ea1SDimitry Andric if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
2740fca6ea1SDimitry Andric if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()))
2750fca6ea1SDimitry Andric return true;
2760fca6ea1SDimitry Andric if (!isInStlNamespace(Callee->getParent()))
2770fca6ea1SDimitry Andric return false;
2780fca6ea1SDimitry Andric if (!isRecordWithAttr<PointerAttr>(
2790fca6ea1SDimitry Andric Callee->getFunctionObjectParameterType()) &&
2800fca6ea1SDimitry Andric !isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType()))
2810fca6ea1SDimitry Andric return false;
2820fca6ea1SDimitry Andric if (Callee->getReturnType()->isPointerType() ||
2830fca6ea1SDimitry Andric isRecordWithAttr<PointerAttr>(Callee->getReturnType())) {
2840fca6ea1SDimitry Andric if (!Callee->getIdentifier())
2850fca6ea1SDimitry Andric return false;
2860fca6ea1SDimitry Andric return llvm::StringSwitch<bool>(Callee->getName())
2870fca6ea1SDimitry Andric .Cases("begin", "rbegin", "cbegin", "crbegin", true)
2880fca6ea1SDimitry Andric .Cases("end", "rend", "cend", "crend", true)
2890fca6ea1SDimitry Andric .Cases("c_str", "data", "get", true)
2900fca6ea1SDimitry Andric // Map and set types.
2910fca6ea1SDimitry Andric .Cases("find", "equal_range", "lower_bound", "upper_bound", true)
2920fca6ea1SDimitry Andric .Default(false);
2930fca6ea1SDimitry Andric } else if (Callee->getReturnType()->isReferenceType()) {
2940fca6ea1SDimitry Andric if (!Callee->getIdentifier()) {
2950fca6ea1SDimitry Andric auto OO = Callee->getOverloadedOperator();
2960fca6ea1SDimitry Andric return OO == OverloadedOperatorKind::OO_Subscript ||
2970fca6ea1SDimitry Andric OO == OverloadedOperatorKind::OO_Star;
2980fca6ea1SDimitry Andric }
2990fca6ea1SDimitry Andric return llvm::StringSwitch<bool>(Callee->getName())
3000fca6ea1SDimitry Andric .Cases("front", "back", "at", "top", "value", true)
3010fca6ea1SDimitry Andric .Default(false);
3020fca6ea1SDimitry Andric }
3030fca6ea1SDimitry Andric return false;
3040fca6ea1SDimitry Andric }
3050fca6ea1SDimitry Andric
shouldTrackFirstArgument(const FunctionDecl * FD)3060fca6ea1SDimitry Andric static bool shouldTrackFirstArgument(const FunctionDecl *FD) {
3070fca6ea1SDimitry Andric if (!FD->getIdentifier() || FD->getNumParams() != 1)
3080fca6ea1SDimitry Andric return false;
3090fca6ea1SDimitry Andric const auto *RD = FD->getParamDecl(0)->getType()->getPointeeCXXRecordDecl();
3100fca6ea1SDimitry Andric if (!FD->isInStdNamespace() || !RD || !RD->isInStdNamespace())
3110fca6ea1SDimitry Andric return false;
3120fca6ea1SDimitry Andric if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
3130fca6ea1SDimitry Andric return false;
3140fca6ea1SDimitry Andric if (FD->getReturnType()->isPointerType() ||
3150fca6ea1SDimitry Andric isRecordWithAttr<PointerAttr>(FD->getReturnType())) {
3160fca6ea1SDimitry Andric return llvm::StringSwitch<bool>(FD->getName())
3170fca6ea1SDimitry Andric .Cases("begin", "rbegin", "cbegin", "crbegin", true)
3180fca6ea1SDimitry Andric .Cases("end", "rend", "cend", "crend", true)
3190fca6ea1SDimitry Andric .Case("data", true)
3200fca6ea1SDimitry Andric .Default(false);
3210fca6ea1SDimitry Andric } else if (FD->getReturnType()->isReferenceType()) {
3220fca6ea1SDimitry Andric return llvm::StringSwitch<bool>(FD->getName())
3230fca6ea1SDimitry Andric .Cases("get", "any_cast", true)
3240fca6ea1SDimitry Andric .Default(false);
3250fca6ea1SDimitry Andric }
3260fca6ea1SDimitry Andric return false;
3270fca6ea1SDimitry Andric }
3280fca6ea1SDimitry Andric
handleGslAnnotatedTypes(IndirectLocalPath & Path,Expr * Call,LocalVisitor Visit)3290fca6ea1SDimitry Andric static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
3300fca6ea1SDimitry Andric LocalVisitor Visit) {
3310fca6ea1SDimitry Andric auto VisitPointerArg = [&](const Decl *D, Expr *Arg, bool Value) {
3320fca6ea1SDimitry Andric // We are not interested in the temporary base objects of gsl Pointers:
3330fca6ea1SDimitry Andric // Temp().ptr; // Here ptr might not dangle.
3340fca6ea1SDimitry Andric if (isa<MemberExpr>(Arg->IgnoreImpCasts()))
3350fca6ea1SDimitry Andric return;
3360fca6ea1SDimitry Andric // Once we initialized a value with a reference, it can no longer dangle.
3370fca6ea1SDimitry Andric if (!Value) {
3380fca6ea1SDimitry Andric for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
3390fca6ea1SDimitry Andric if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit)
3400fca6ea1SDimitry Andric continue;
3410fca6ea1SDimitry Andric if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
3420fca6ea1SDimitry Andric PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
3430fca6ea1SDimitry Andric return;
3440fca6ea1SDimitry Andric break;
3450fca6ea1SDimitry Andric }
3460fca6ea1SDimitry Andric }
3470fca6ea1SDimitry Andric Path.push_back({Value ? IndirectLocalPathEntry::GslPointerInit
3480fca6ea1SDimitry Andric : IndirectLocalPathEntry::GslReferenceInit,
3490fca6ea1SDimitry Andric Arg, D});
3500fca6ea1SDimitry Andric if (Arg->isGLValue())
3510fca6ea1SDimitry Andric visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
3520fca6ea1SDimitry Andric Visit,
3530fca6ea1SDimitry Andric /*EnableLifetimeWarnings=*/true);
3540fca6ea1SDimitry Andric else
3550fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
3560fca6ea1SDimitry Andric /*EnableLifetimeWarnings=*/true);
3570fca6ea1SDimitry Andric Path.pop_back();
3580fca6ea1SDimitry Andric };
3590fca6ea1SDimitry Andric
3600fca6ea1SDimitry Andric if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
3610fca6ea1SDimitry Andric const auto *MD = cast_or_null<CXXMethodDecl>(MCE->getDirectCallee());
3620fca6ea1SDimitry Andric if (MD && shouldTrackImplicitObjectArg(MD))
3630fca6ea1SDimitry Andric VisitPointerArg(MD, MCE->getImplicitObjectArgument(),
3640fca6ea1SDimitry Andric !MD->getReturnType()->isReferenceType());
3650fca6ea1SDimitry Andric return;
3660fca6ea1SDimitry Andric } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Call)) {
3670fca6ea1SDimitry Andric FunctionDecl *Callee = OCE->getDirectCallee();
3680fca6ea1SDimitry Andric if (Callee && Callee->isCXXInstanceMember() &&
3690fca6ea1SDimitry Andric shouldTrackImplicitObjectArg(cast<CXXMethodDecl>(Callee)))
3700fca6ea1SDimitry Andric VisitPointerArg(Callee, OCE->getArg(0),
3710fca6ea1SDimitry Andric !Callee->getReturnType()->isReferenceType());
3720fca6ea1SDimitry Andric return;
3730fca6ea1SDimitry Andric } else if (auto *CE = dyn_cast<CallExpr>(Call)) {
3740fca6ea1SDimitry Andric FunctionDecl *Callee = CE->getDirectCallee();
3750fca6ea1SDimitry Andric if (Callee && shouldTrackFirstArgument(Callee))
3760fca6ea1SDimitry Andric VisitPointerArg(Callee, CE->getArg(0),
3770fca6ea1SDimitry Andric !Callee->getReturnType()->isReferenceType());
3780fca6ea1SDimitry Andric return;
3790fca6ea1SDimitry Andric }
3800fca6ea1SDimitry Andric
3810fca6ea1SDimitry Andric if (auto *CCE = dyn_cast<CXXConstructExpr>(Call)) {
3820fca6ea1SDimitry Andric const auto *Ctor = CCE->getConstructor();
3830fca6ea1SDimitry Andric const CXXRecordDecl *RD = Ctor->getParent();
3840fca6ea1SDimitry Andric if (CCE->getNumArgs() > 0 && RD->hasAttr<PointerAttr>())
3850fca6ea1SDimitry Andric VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0], true);
3860fca6ea1SDimitry Andric }
3870fca6ea1SDimitry Andric }
3880fca6ea1SDimitry Andric
implicitObjectParamIsLifetimeBound(const FunctionDecl * FD)3890fca6ea1SDimitry Andric static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
3900fca6ea1SDimitry Andric const TypeSourceInfo *TSI = FD->getTypeSourceInfo();
3910fca6ea1SDimitry Andric if (!TSI)
3920fca6ea1SDimitry Andric return false;
3930fca6ea1SDimitry Andric // Don't declare this variable in the second operand of the for-statement;
3940fca6ea1SDimitry Andric // GCC miscompiles that by ending its lifetime before evaluating the
3950fca6ea1SDimitry Andric // third operand. See gcc.gnu.org/PR86769.
3960fca6ea1SDimitry Andric AttributedTypeLoc ATL;
3970fca6ea1SDimitry Andric for (TypeLoc TL = TSI->getTypeLoc();
3980fca6ea1SDimitry Andric (ATL = TL.getAsAdjusted<AttributedTypeLoc>());
3990fca6ea1SDimitry Andric TL = ATL.getModifiedLoc()) {
4000fca6ea1SDimitry Andric if (ATL.getAttrAs<LifetimeBoundAttr>())
4010fca6ea1SDimitry Andric return true;
4020fca6ea1SDimitry Andric }
4030fca6ea1SDimitry Andric
4040fca6ea1SDimitry Andric // Assume that all assignment operators with a "normal" return type return
4050fca6ea1SDimitry Andric // *this, that is, an lvalue reference that is the same type as the implicit
4060fca6ea1SDimitry Andric // object parameter (or the LHS for a non-member operator$=).
4070fca6ea1SDimitry Andric OverloadedOperatorKind OO = FD->getDeclName().getCXXOverloadedOperator();
4080fca6ea1SDimitry Andric if (OO == OO_Equal || isCompoundAssignmentOperator(OO)) {
4090fca6ea1SDimitry Andric QualType RetT = FD->getReturnType();
4100fca6ea1SDimitry Andric if (RetT->isLValueReferenceType()) {
4110fca6ea1SDimitry Andric ASTContext &Ctx = FD->getASTContext();
4120fca6ea1SDimitry Andric QualType LHST;
4130fca6ea1SDimitry Andric auto *MD = dyn_cast<CXXMethodDecl>(FD);
4140fca6ea1SDimitry Andric if (MD && MD->isCXXInstanceMember())
4150fca6ea1SDimitry Andric LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType());
4160fca6ea1SDimitry Andric else
4170fca6ea1SDimitry Andric LHST = MD->getParamDecl(0)->getType();
4180fca6ea1SDimitry Andric if (Ctx.hasSameType(RetT, LHST))
4190fca6ea1SDimitry Andric return true;
4200fca6ea1SDimitry Andric }
4210fca6ea1SDimitry Andric }
4220fca6ea1SDimitry Andric
4230fca6ea1SDimitry Andric return false;
4240fca6ea1SDimitry Andric }
4250fca6ea1SDimitry Andric
visitLifetimeBoundArguments(IndirectLocalPath & Path,Expr * Call,LocalVisitor Visit)4260fca6ea1SDimitry Andric static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,
4270fca6ea1SDimitry Andric LocalVisitor Visit) {
4280fca6ea1SDimitry Andric const FunctionDecl *Callee;
4290fca6ea1SDimitry Andric ArrayRef<Expr *> Args;
4300fca6ea1SDimitry Andric
4310fca6ea1SDimitry Andric if (auto *CE = dyn_cast<CallExpr>(Call)) {
4320fca6ea1SDimitry Andric Callee = CE->getDirectCallee();
4330fca6ea1SDimitry Andric Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
4340fca6ea1SDimitry Andric } else {
4350fca6ea1SDimitry Andric auto *CCE = cast<CXXConstructExpr>(Call);
4360fca6ea1SDimitry Andric Callee = CCE->getConstructor();
4370fca6ea1SDimitry Andric Args = llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs());
4380fca6ea1SDimitry Andric }
4390fca6ea1SDimitry Andric if (!Callee)
4400fca6ea1SDimitry Andric return;
4410fca6ea1SDimitry Andric
4420fca6ea1SDimitry Andric Expr *ObjectArg = nullptr;
4430fca6ea1SDimitry Andric if (isa<CXXOperatorCallExpr>(Call) && Callee->isCXXInstanceMember()) {
4440fca6ea1SDimitry Andric ObjectArg = Args[0];
4450fca6ea1SDimitry Andric Args = Args.slice(1);
4460fca6ea1SDimitry Andric } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
4470fca6ea1SDimitry Andric ObjectArg = MCE->getImplicitObjectArgument();
4480fca6ea1SDimitry Andric }
4490fca6ea1SDimitry Andric
4500fca6ea1SDimitry Andric auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) {
4510fca6ea1SDimitry Andric Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
4520fca6ea1SDimitry Andric if (Arg->isGLValue())
4530fca6ea1SDimitry Andric visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
4540fca6ea1SDimitry Andric Visit,
4550fca6ea1SDimitry Andric /*EnableLifetimeWarnings=*/false);
4560fca6ea1SDimitry Andric else
4570fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
4580fca6ea1SDimitry Andric /*EnableLifetimeWarnings=*/false);
4590fca6ea1SDimitry Andric Path.pop_back();
4600fca6ea1SDimitry Andric };
4610fca6ea1SDimitry Andric
4620fca6ea1SDimitry Andric bool CheckCoroCall = false;
4630fca6ea1SDimitry Andric if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
4640fca6ea1SDimitry Andric CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
4650fca6ea1SDimitry Andric RD->hasAttr<CoroReturnTypeAttr>() &&
4660fca6ea1SDimitry Andric !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
4670fca6ea1SDimitry Andric }
4680fca6ea1SDimitry Andric
4690fca6ea1SDimitry Andric if (ObjectArg) {
4700fca6ea1SDimitry Andric bool CheckCoroObjArg = CheckCoroCall;
4710fca6ea1SDimitry Andric // Coroutine lambda objects with empty capture list are not lifetimebound.
4720fca6ea1SDimitry Andric if (auto *LE = dyn_cast<LambdaExpr>(ObjectArg->IgnoreImplicit());
4730fca6ea1SDimitry Andric LE && LE->captures().empty())
4740fca6ea1SDimitry Andric CheckCoroObjArg = false;
4750fca6ea1SDimitry Andric // Allow `get_return_object()` as the object param (__promise) is not
4760fca6ea1SDimitry Andric // lifetimebound.
4770fca6ea1SDimitry Andric if (Sema::CanBeGetReturnObject(Callee))
4780fca6ea1SDimitry Andric CheckCoroObjArg = false;
4790fca6ea1SDimitry Andric if (implicitObjectParamIsLifetimeBound(Callee) || CheckCoroObjArg)
4800fca6ea1SDimitry Andric VisitLifetimeBoundArg(Callee, ObjectArg);
4810fca6ea1SDimitry Andric }
4820fca6ea1SDimitry Andric
4830fca6ea1SDimitry Andric for (unsigned I = 0,
4840fca6ea1SDimitry Andric N = std::min<unsigned>(Callee->getNumParams(), Args.size());
4850fca6ea1SDimitry Andric I != N; ++I) {
4860fca6ea1SDimitry Andric if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
4870fca6ea1SDimitry Andric VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
4880fca6ea1SDimitry Andric }
4890fca6ea1SDimitry Andric }
4900fca6ea1SDimitry Andric
4910fca6ea1SDimitry Andric /// Visit the locals that would be reachable through a reference bound to the
4920fca6ea1SDimitry Andric /// glvalue expression \c Init.
visitLocalsRetainedByReferenceBinding(IndirectLocalPath & Path,Expr * Init,ReferenceKind RK,LocalVisitor Visit,bool EnableLifetimeWarnings)4930fca6ea1SDimitry Andric static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
4940fca6ea1SDimitry Andric Expr *Init, ReferenceKind RK,
4950fca6ea1SDimitry Andric LocalVisitor Visit,
4960fca6ea1SDimitry Andric bool EnableLifetimeWarnings) {
4970fca6ea1SDimitry Andric RevertToOldSizeRAII RAII(Path);
4980fca6ea1SDimitry Andric
4990fca6ea1SDimitry Andric // Walk past any constructs which we can lifetime-extend across.
5000fca6ea1SDimitry Andric Expr *Old;
5010fca6ea1SDimitry Andric do {
5020fca6ea1SDimitry Andric Old = Init;
5030fca6ea1SDimitry Andric
5040fca6ea1SDimitry Andric if (auto *FE = dyn_cast<FullExpr>(Init))
5050fca6ea1SDimitry Andric Init = FE->getSubExpr();
5060fca6ea1SDimitry Andric
5070fca6ea1SDimitry Andric if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
5080fca6ea1SDimitry Andric // If this is just redundant braces around an initializer, step over it.
5090fca6ea1SDimitry Andric if (ILE->isTransparent())
5100fca6ea1SDimitry Andric Init = ILE->getInit(0);
5110fca6ea1SDimitry Andric }
5120fca6ea1SDimitry Andric
5130fca6ea1SDimitry Andric // Step over any subobject adjustments; we may have a materialized
5140fca6ea1SDimitry Andric // temporary inside them.
5150fca6ea1SDimitry Andric Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
5160fca6ea1SDimitry Andric
5170fca6ea1SDimitry Andric // Per current approach for DR1376, look through casts to reference type
5180fca6ea1SDimitry Andric // when performing lifetime extension.
5190fca6ea1SDimitry Andric if (CastExpr *CE = dyn_cast<CastExpr>(Init))
5200fca6ea1SDimitry Andric if (CE->getSubExpr()->isGLValue())
5210fca6ea1SDimitry Andric Init = CE->getSubExpr();
5220fca6ea1SDimitry Andric
5230fca6ea1SDimitry Andric // Per the current approach for DR1299, look through array element access
5240fca6ea1SDimitry Andric // on array glvalues when performing lifetime extension.
5250fca6ea1SDimitry Andric if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init)) {
5260fca6ea1SDimitry Andric Init = ASE->getBase();
5270fca6ea1SDimitry Andric auto *ICE = dyn_cast<ImplicitCastExpr>(Init);
5280fca6ea1SDimitry Andric if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
5290fca6ea1SDimitry Andric Init = ICE->getSubExpr();
5300fca6ea1SDimitry Andric else
5310fca6ea1SDimitry Andric // We can't lifetime extend through this but we might still find some
5320fca6ea1SDimitry Andric // retained temporaries.
5330fca6ea1SDimitry Andric return visitLocalsRetainedByInitializer(Path, Init, Visit, true,
5340fca6ea1SDimitry Andric EnableLifetimeWarnings);
5350fca6ea1SDimitry Andric }
5360fca6ea1SDimitry Andric
5370fca6ea1SDimitry Andric // Step into CXXDefaultInitExprs so we can diagnose cases where a
5380fca6ea1SDimitry Andric // constructor inherits one as an implicit mem-initializer.
5390fca6ea1SDimitry Andric if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
5400fca6ea1SDimitry Andric Path.push_back(
5410fca6ea1SDimitry Andric {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
5420fca6ea1SDimitry Andric Init = DIE->getExpr();
5430fca6ea1SDimitry Andric }
5440fca6ea1SDimitry Andric } while (Init != Old);
5450fca6ea1SDimitry Andric
5460fca6ea1SDimitry Andric if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
5470fca6ea1SDimitry Andric if (Visit(Path, Local(MTE), RK))
5480fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit, true,
5490fca6ea1SDimitry Andric EnableLifetimeWarnings);
5500fca6ea1SDimitry Andric }
5510fca6ea1SDimitry Andric
552*52418fc2SDimitry Andric if (auto *M = dyn_cast<MemberExpr>(Init)) {
553*52418fc2SDimitry Andric // Lifetime of a non-reference type field is same as base object.
554*52418fc2SDimitry Andric if (auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
555*52418fc2SDimitry Andric F && !F->getType()->isReferenceType())
556*52418fc2SDimitry Andric visitLocalsRetainedByInitializer(Path, M->getBase(), Visit, true,
557*52418fc2SDimitry Andric EnableLifetimeWarnings);
558*52418fc2SDimitry Andric }
559*52418fc2SDimitry Andric
5600fca6ea1SDimitry Andric if (isa<CallExpr>(Init)) {
5610fca6ea1SDimitry Andric if (EnableLifetimeWarnings)
5620fca6ea1SDimitry Andric handleGslAnnotatedTypes(Path, Init, Visit);
5630fca6ea1SDimitry Andric return visitLifetimeBoundArguments(Path, Init, Visit);
5640fca6ea1SDimitry Andric }
5650fca6ea1SDimitry Andric
5660fca6ea1SDimitry Andric switch (Init->getStmtClass()) {
5670fca6ea1SDimitry Andric case Stmt::DeclRefExprClass: {
5680fca6ea1SDimitry Andric // If we find the name of a local non-reference parameter, we could have a
5690fca6ea1SDimitry Andric // lifetime problem.
5700fca6ea1SDimitry Andric auto *DRE = cast<DeclRefExpr>(Init);
5710fca6ea1SDimitry Andric auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
5720fca6ea1SDimitry Andric if (VD && VD->hasLocalStorage() &&
5730fca6ea1SDimitry Andric !DRE->refersToEnclosingVariableOrCapture()) {
5740fca6ea1SDimitry Andric if (!VD->getType()->isReferenceType()) {
5750fca6ea1SDimitry Andric Visit(Path, Local(DRE), RK);
5760fca6ea1SDimitry Andric } else if (isa<ParmVarDecl>(DRE->getDecl())) {
5770fca6ea1SDimitry Andric // The lifetime of a reference parameter is unknown; assume it's OK
5780fca6ea1SDimitry Andric // for now.
5790fca6ea1SDimitry Andric break;
5800fca6ea1SDimitry Andric } else if (VD->getInit() && !isVarOnPath(Path, VD)) {
5810fca6ea1SDimitry Andric Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
5820fca6ea1SDimitry Andric visitLocalsRetainedByReferenceBinding(Path, VD->getInit(),
5830fca6ea1SDimitry Andric RK_ReferenceBinding, Visit,
5840fca6ea1SDimitry Andric EnableLifetimeWarnings);
5850fca6ea1SDimitry Andric }
5860fca6ea1SDimitry Andric }
5870fca6ea1SDimitry Andric break;
5880fca6ea1SDimitry Andric }
5890fca6ea1SDimitry Andric
5900fca6ea1SDimitry Andric case Stmt::UnaryOperatorClass: {
5910fca6ea1SDimitry Andric // The only unary operator that make sense to handle here
5920fca6ea1SDimitry Andric // is Deref. All others don't resolve to a "name." This includes
5930fca6ea1SDimitry Andric // handling all sorts of rvalues passed to a unary operator.
5940fca6ea1SDimitry Andric const UnaryOperator *U = cast<UnaryOperator>(Init);
5950fca6ea1SDimitry Andric if (U->getOpcode() == UO_Deref)
5960fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true,
5970fca6ea1SDimitry Andric EnableLifetimeWarnings);
5980fca6ea1SDimitry Andric break;
5990fca6ea1SDimitry Andric }
6000fca6ea1SDimitry Andric
6010fca6ea1SDimitry Andric case Stmt::ArraySectionExprClass: {
6020fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path,
6030fca6ea1SDimitry Andric cast<ArraySectionExpr>(Init)->getBase(),
6040fca6ea1SDimitry Andric Visit, true, EnableLifetimeWarnings);
6050fca6ea1SDimitry Andric break;
6060fca6ea1SDimitry Andric }
6070fca6ea1SDimitry Andric
6080fca6ea1SDimitry Andric case Stmt::ConditionalOperatorClass:
6090fca6ea1SDimitry Andric case Stmt::BinaryConditionalOperatorClass: {
6100fca6ea1SDimitry Andric auto *C = cast<AbstractConditionalOperator>(Init);
6110fca6ea1SDimitry Andric if (!C->getTrueExpr()->getType()->isVoidType())
6120fca6ea1SDimitry Andric visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit,
6130fca6ea1SDimitry Andric EnableLifetimeWarnings);
6140fca6ea1SDimitry Andric if (!C->getFalseExpr()->getType()->isVoidType())
6150fca6ea1SDimitry Andric visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit,
6160fca6ea1SDimitry Andric EnableLifetimeWarnings);
6170fca6ea1SDimitry Andric break;
6180fca6ea1SDimitry Andric }
6190fca6ea1SDimitry Andric
6200fca6ea1SDimitry Andric case Stmt::CompoundLiteralExprClass: {
6210fca6ea1SDimitry Andric if (auto *CLE = dyn_cast<CompoundLiteralExpr>(Init)) {
6220fca6ea1SDimitry Andric if (!CLE->isFileScope())
6230fca6ea1SDimitry Andric Visit(Path, Local(CLE), RK);
6240fca6ea1SDimitry Andric }
6250fca6ea1SDimitry Andric break;
6260fca6ea1SDimitry Andric }
6270fca6ea1SDimitry Andric
6280fca6ea1SDimitry Andric // FIXME: Visit the left-hand side of an -> or ->*.
6290fca6ea1SDimitry Andric
6300fca6ea1SDimitry Andric default:
6310fca6ea1SDimitry Andric break;
6320fca6ea1SDimitry Andric }
6330fca6ea1SDimitry Andric }
6340fca6ea1SDimitry Andric
6350fca6ea1SDimitry Andric /// Visit the locals that would be reachable through an object initialized by
6360fca6ea1SDimitry Andric /// the prvalue expression \c Init.
visitLocalsRetainedByInitializer(IndirectLocalPath & Path,Expr * Init,LocalVisitor Visit,bool RevisitSubinits,bool EnableLifetimeWarnings)6370fca6ea1SDimitry Andric static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
6380fca6ea1SDimitry Andric Expr *Init, LocalVisitor Visit,
6390fca6ea1SDimitry Andric bool RevisitSubinits,
6400fca6ea1SDimitry Andric bool EnableLifetimeWarnings) {
6410fca6ea1SDimitry Andric RevertToOldSizeRAII RAII(Path);
6420fca6ea1SDimitry Andric
6430fca6ea1SDimitry Andric Expr *Old;
6440fca6ea1SDimitry Andric do {
6450fca6ea1SDimitry Andric Old = Init;
6460fca6ea1SDimitry Andric
6470fca6ea1SDimitry Andric // Step into CXXDefaultInitExprs so we can diagnose cases where a
6480fca6ea1SDimitry Andric // constructor inherits one as an implicit mem-initializer.
6490fca6ea1SDimitry Andric if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
6500fca6ea1SDimitry Andric Path.push_back(
6510fca6ea1SDimitry Andric {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
6520fca6ea1SDimitry Andric Init = DIE->getExpr();
6530fca6ea1SDimitry Andric }
6540fca6ea1SDimitry Andric
6550fca6ea1SDimitry Andric if (auto *FE = dyn_cast<FullExpr>(Init))
6560fca6ea1SDimitry Andric Init = FE->getSubExpr();
6570fca6ea1SDimitry Andric
6580fca6ea1SDimitry Andric // Dig out the expression which constructs the extended temporary.
6590fca6ea1SDimitry Andric Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
6600fca6ea1SDimitry Andric
6610fca6ea1SDimitry Andric if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
6620fca6ea1SDimitry Andric Init = BTE->getSubExpr();
6630fca6ea1SDimitry Andric
6640fca6ea1SDimitry Andric Init = Init->IgnoreParens();
6650fca6ea1SDimitry Andric
6660fca6ea1SDimitry Andric // Step over value-preserving rvalue casts.
6670fca6ea1SDimitry Andric if (auto *CE = dyn_cast<CastExpr>(Init)) {
6680fca6ea1SDimitry Andric switch (CE->getCastKind()) {
6690fca6ea1SDimitry Andric case CK_LValueToRValue:
6700fca6ea1SDimitry Andric // If we can match the lvalue to a const object, we can look at its
6710fca6ea1SDimitry Andric // initializer.
6720fca6ea1SDimitry Andric Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
6730fca6ea1SDimitry Andric return visitLocalsRetainedByReferenceBinding(
6740fca6ea1SDimitry Andric Path, Init, RK_ReferenceBinding,
6750fca6ea1SDimitry Andric [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
6760fca6ea1SDimitry Andric if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
6770fca6ea1SDimitry Andric auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
6780fca6ea1SDimitry Andric if (VD && VD->getType().isConstQualified() && VD->getInit() &&
6790fca6ea1SDimitry Andric !isVarOnPath(Path, VD)) {
6800fca6ea1SDimitry Andric Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
6810fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(
6820fca6ea1SDimitry Andric Path, VD->getInit(), Visit, true, EnableLifetimeWarnings);
6830fca6ea1SDimitry Andric }
6840fca6ea1SDimitry Andric } else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
6850fca6ea1SDimitry Andric if (MTE->getType().isConstQualified())
6860fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(),
6870fca6ea1SDimitry Andric Visit, true,
6880fca6ea1SDimitry Andric EnableLifetimeWarnings);
6890fca6ea1SDimitry Andric }
6900fca6ea1SDimitry Andric return false;
6910fca6ea1SDimitry Andric },
6920fca6ea1SDimitry Andric EnableLifetimeWarnings);
6930fca6ea1SDimitry Andric
6940fca6ea1SDimitry Andric // We assume that objects can be retained by pointers cast to integers,
6950fca6ea1SDimitry Andric // but not if the integer is cast to floating-point type or to _Complex.
6960fca6ea1SDimitry Andric // We assume that casts to 'bool' do not preserve enough information to
6970fca6ea1SDimitry Andric // retain a local object.
6980fca6ea1SDimitry Andric case CK_NoOp:
6990fca6ea1SDimitry Andric case CK_BitCast:
7000fca6ea1SDimitry Andric case CK_BaseToDerived:
7010fca6ea1SDimitry Andric case CK_DerivedToBase:
7020fca6ea1SDimitry Andric case CK_UncheckedDerivedToBase:
7030fca6ea1SDimitry Andric case CK_Dynamic:
7040fca6ea1SDimitry Andric case CK_ToUnion:
7050fca6ea1SDimitry Andric case CK_UserDefinedConversion:
7060fca6ea1SDimitry Andric case CK_ConstructorConversion:
7070fca6ea1SDimitry Andric case CK_IntegralToPointer:
7080fca6ea1SDimitry Andric case CK_PointerToIntegral:
7090fca6ea1SDimitry Andric case CK_VectorSplat:
7100fca6ea1SDimitry Andric case CK_IntegralCast:
7110fca6ea1SDimitry Andric case CK_CPointerToObjCPointerCast:
7120fca6ea1SDimitry Andric case CK_BlockPointerToObjCPointerCast:
7130fca6ea1SDimitry Andric case CK_AnyPointerToBlockPointerCast:
7140fca6ea1SDimitry Andric case CK_AddressSpaceConversion:
7150fca6ea1SDimitry Andric break;
7160fca6ea1SDimitry Andric
7170fca6ea1SDimitry Andric case CK_ArrayToPointerDecay:
7180fca6ea1SDimitry Andric // Model array-to-pointer decay as taking the address of the array
7190fca6ea1SDimitry Andric // lvalue.
7200fca6ea1SDimitry Andric Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
7210fca6ea1SDimitry Andric return visitLocalsRetainedByReferenceBinding(Path, CE->getSubExpr(),
7220fca6ea1SDimitry Andric RK_ReferenceBinding, Visit,
7230fca6ea1SDimitry Andric EnableLifetimeWarnings);
7240fca6ea1SDimitry Andric
7250fca6ea1SDimitry Andric default:
7260fca6ea1SDimitry Andric return;
7270fca6ea1SDimitry Andric }
7280fca6ea1SDimitry Andric
7290fca6ea1SDimitry Andric Init = CE->getSubExpr();
7300fca6ea1SDimitry Andric }
7310fca6ea1SDimitry Andric } while (Old != Init);
7320fca6ea1SDimitry Andric
7330fca6ea1SDimitry Andric // C++17 [dcl.init.list]p6:
7340fca6ea1SDimitry Andric // initializing an initializer_list object from the array extends the
7350fca6ea1SDimitry Andric // lifetime of the array exactly like binding a reference to a temporary.
7360fca6ea1SDimitry Andric if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init))
7370fca6ea1SDimitry Andric return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(),
7380fca6ea1SDimitry Andric RK_StdInitializerList, Visit,
7390fca6ea1SDimitry Andric EnableLifetimeWarnings);
7400fca6ea1SDimitry Andric
7410fca6ea1SDimitry Andric if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
7420fca6ea1SDimitry Andric // We already visited the elements of this initializer list while
7430fca6ea1SDimitry Andric // performing the initialization. Don't visit them again unless we've
7440fca6ea1SDimitry Andric // changed the lifetime of the initialized entity.
7450fca6ea1SDimitry Andric if (!RevisitSubinits)
7460fca6ea1SDimitry Andric return;
7470fca6ea1SDimitry Andric
7480fca6ea1SDimitry Andric if (ILE->isTransparent())
7490fca6ea1SDimitry Andric return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit,
7500fca6ea1SDimitry Andric RevisitSubinits,
7510fca6ea1SDimitry Andric EnableLifetimeWarnings);
7520fca6ea1SDimitry Andric
7530fca6ea1SDimitry Andric if (ILE->getType()->isArrayType()) {
7540fca6ea1SDimitry Andric for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
7550fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit,
7560fca6ea1SDimitry Andric RevisitSubinits,
7570fca6ea1SDimitry Andric EnableLifetimeWarnings);
7580fca6ea1SDimitry Andric return;
7590fca6ea1SDimitry Andric }
7600fca6ea1SDimitry Andric
7610fca6ea1SDimitry Andric if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
7620fca6ea1SDimitry Andric assert(RD->isAggregate() && "aggregate init on non-aggregate");
7630fca6ea1SDimitry Andric
7640fca6ea1SDimitry Andric // If we lifetime-extend a braced initializer which is initializing an
7650fca6ea1SDimitry Andric // aggregate, and that aggregate contains reference members which are
7660fca6ea1SDimitry Andric // bound to temporaries, those temporaries are also lifetime-extended.
7670fca6ea1SDimitry Andric if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
7680fca6ea1SDimitry Andric ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
7690fca6ea1SDimitry Andric visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0),
7700fca6ea1SDimitry Andric RK_ReferenceBinding, Visit,
7710fca6ea1SDimitry Andric EnableLifetimeWarnings);
7720fca6ea1SDimitry Andric else {
7730fca6ea1SDimitry Andric unsigned Index = 0;
7740fca6ea1SDimitry Andric for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
7750fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, ILE->getInit(Index), Visit,
7760fca6ea1SDimitry Andric RevisitSubinits,
7770fca6ea1SDimitry Andric EnableLifetimeWarnings);
7780fca6ea1SDimitry Andric for (const auto *I : RD->fields()) {
7790fca6ea1SDimitry Andric if (Index >= ILE->getNumInits())
7800fca6ea1SDimitry Andric break;
7810fca6ea1SDimitry Andric if (I->isUnnamedBitField())
7820fca6ea1SDimitry Andric continue;
7830fca6ea1SDimitry Andric Expr *SubInit = ILE->getInit(Index);
7840fca6ea1SDimitry Andric if (I->getType()->isReferenceType())
7850fca6ea1SDimitry Andric visitLocalsRetainedByReferenceBinding(Path, SubInit,
7860fca6ea1SDimitry Andric RK_ReferenceBinding, Visit,
7870fca6ea1SDimitry Andric EnableLifetimeWarnings);
7880fca6ea1SDimitry Andric else
7890fca6ea1SDimitry Andric // This might be either aggregate-initialization of a member or
7900fca6ea1SDimitry Andric // initialization of a std::initializer_list object. Regardless,
7910fca6ea1SDimitry Andric // we should recursively lifetime-extend that initializer.
7920fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(
7930fca6ea1SDimitry Andric Path, SubInit, Visit, RevisitSubinits, EnableLifetimeWarnings);
7940fca6ea1SDimitry Andric ++Index;
7950fca6ea1SDimitry Andric }
7960fca6ea1SDimitry Andric }
7970fca6ea1SDimitry Andric }
7980fca6ea1SDimitry Andric return;
7990fca6ea1SDimitry Andric }
8000fca6ea1SDimitry Andric
8010fca6ea1SDimitry Andric // The lifetime of an init-capture is that of the closure object constructed
8020fca6ea1SDimitry Andric // by a lambda-expression.
8030fca6ea1SDimitry Andric if (auto *LE = dyn_cast<LambdaExpr>(Init)) {
8040fca6ea1SDimitry Andric LambdaExpr::capture_iterator CapI = LE->capture_begin();
8050fca6ea1SDimitry Andric for (Expr *E : LE->capture_inits()) {
8060fca6ea1SDimitry Andric assert(CapI != LE->capture_end());
8070fca6ea1SDimitry Andric const LambdaCapture &Cap = *CapI++;
8080fca6ea1SDimitry Andric if (!E)
8090fca6ea1SDimitry Andric continue;
8100fca6ea1SDimitry Andric if (Cap.capturesVariable())
8110fca6ea1SDimitry Andric Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
8120fca6ea1SDimitry Andric if (E->isGLValue())
8130fca6ea1SDimitry Andric visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding,
8140fca6ea1SDimitry Andric Visit, EnableLifetimeWarnings);
8150fca6ea1SDimitry Andric else
8160fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, E, Visit, true,
8170fca6ea1SDimitry Andric EnableLifetimeWarnings);
8180fca6ea1SDimitry Andric if (Cap.capturesVariable())
8190fca6ea1SDimitry Andric Path.pop_back();
8200fca6ea1SDimitry Andric }
8210fca6ea1SDimitry Andric }
8220fca6ea1SDimitry Andric
8230fca6ea1SDimitry Andric // Assume that a copy or move from a temporary references the same objects
8240fca6ea1SDimitry Andric // that the temporary does.
8250fca6ea1SDimitry Andric if (auto *CCE = dyn_cast<CXXConstructExpr>(Init)) {
8260fca6ea1SDimitry Andric if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
8270fca6ea1SDimitry Andric if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
8280fca6ea1SDimitry Andric // assert(false && "hit temporary copy path");
8290fca6ea1SDimitry Andric Expr *Arg = MTE->getSubExpr();
8300fca6ea1SDimitry Andric Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
8310fca6ea1SDimitry Andric CCE->getConstructor()});
8320fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
8330fca6ea1SDimitry Andric /*EnableLifetimeWarnings*/ false);
8340fca6ea1SDimitry Andric Path.pop_back();
8350fca6ea1SDimitry Andric }
8360fca6ea1SDimitry Andric }
8370fca6ea1SDimitry Andric }
8380fca6ea1SDimitry Andric
8390fca6ea1SDimitry Andric if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init)) {
8400fca6ea1SDimitry Andric if (EnableLifetimeWarnings)
8410fca6ea1SDimitry Andric handleGslAnnotatedTypes(Path, Init, Visit);
8420fca6ea1SDimitry Andric return visitLifetimeBoundArguments(Path, Init, Visit);
8430fca6ea1SDimitry Andric }
8440fca6ea1SDimitry Andric
8450fca6ea1SDimitry Andric switch (Init->getStmtClass()) {
8460fca6ea1SDimitry Andric case Stmt::UnaryOperatorClass: {
8470fca6ea1SDimitry Andric auto *UO = cast<UnaryOperator>(Init);
8480fca6ea1SDimitry Andric // If the initializer is the address of a local, we could have a lifetime
8490fca6ea1SDimitry Andric // problem.
8500fca6ea1SDimitry Andric if (UO->getOpcode() == UO_AddrOf) {
8510fca6ea1SDimitry Andric // If this is &rvalue, then it's ill-formed and we have already diagnosed
8520fca6ea1SDimitry Andric // it. Don't produce a redundant warning about the lifetime of the
8530fca6ea1SDimitry Andric // temporary.
8540fca6ea1SDimitry Andric if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
8550fca6ea1SDimitry Andric return;
8560fca6ea1SDimitry Andric
8570fca6ea1SDimitry Andric Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
8580fca6ea1SDimitry Andric visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(),
8590fca6ea1SDimitry Andric RK_ReferenceBinding, Visit,
8600fca6ea1SDimitry Andric EnableLifetimeWarnings);
8610fca6ea1SDimitry Andric }
8620fca6ea1SDimitry Andric break;
8630fca6ea1SDimitry Andric }
8640fca6ea1SDimitry Andric
8650fca6ea1SDimitry Andric case Stmt::BinaryOperatorClass: {
8660fca6ea1SDimitry Andric // Handle pointer arithmetic.
8670fca6ea1SDimitry Andric auto *BO = cast<BinaryOperator>(Init);
8680fca6ea1SDimitry Andric BinaryOperatorKind BOK = BO->getOpcode();
8690fca6ea1SDimitry Andric if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
8700fca6ea1SDimitry Andric break;
8710fca6ea1SDimitry Andric
8720fca6ea1SDimitry Andric if (BO->getLHS()->getType()->isPointerType())
8730fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true,
8740fca6ea1SDimitry Andric EnableLifetimeWarnings);
8750fca6ea1SDimitry Andric else if (BO->getRHS()->getType()->isPointerType())
8760fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true,
8770fca6ea1SDimitry Andric EnableLifetimeWarnings);
8780fca6ea1SDimitry Andric break;
8790fca6ea1SDimitry Andric }
8800fca6ea1SDimitry Andric
8810fca6ea1SDimitry Andric case Stmt::ConditionalOperatorClass:
8820fca6ea1SDimitry Andric case Stmt::BinaryConditionalOperatorClass: {
8830fca6ea1SDimitry Andric auto *C = cast<AbstractConditionalOperator>(Init);
8840fca6ea1SDimitry Andric // In C++, we can have a throw-expression operand, which has 'void' type
8850fca6ea1SDimitry Andric // and isn't interesting from a lifetime perspective.
8860fca6ea1SDimitry Andric if (!C->getTrueExpr()->getType()->isVoidType())
8870fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true,
8880fca6ea1SDimitry Andric EnableLifetimeWarnings);
8890fca6ea1SDimitry Andric if (!C->getFalseExpr()->getType()->isVoidType())
8900fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true,
8910fca6ea1SDimitry Andric EnableLifetimeWarnings);
8920fca6ea1SDimitry Andric break;
8930fca6ea1SDimitry Andric }
8940fca6ea1SDimitry Andric
8950fca6ea1SDimitry Andric case Stmt::BlockExprClass:
8960fca6ea1SDimitry Andric if (cast<BlockExpr>(Init)->getBlockDecl()->hasCaptures()) {
8970fca6ea1SDimitry Andric // This is a local block, whose lifetime is that of the function.
8980fca6ea1SDimitry Andric Visit(Path, Local(cast<BlockExpr>(Init)), RK_ReferenceBinding);
8990fca6ea1SDimitry Andric }
9000fca6ea1SDimitry Andric break;
9010fca6ea1SDimitry Andric
9020fca6ea1SDimitry Andric case Stmt::AddrLabelExprClass:
9030fca6ea1SDimitry Andric // We want to warn if the address of a label would escape the function.
9040fca6ea1SDimitry Andric Visit(Path, Local(cast<AddrLabelExpr>(Init)), RK_ReferenceBinding);
9050fca6ea1SDimitry Andric break;
9060fca6ea1SDimitry Andric
9070fca6ea1SDimitry Andric default:
9080fca6ea1SDimitry Andric break;
9090fca6ea1SDimitry Andric }
9100fca6ea1SDimitry Andric }
9110fca6ea1SDimitry Andric
9120fca6ea1SDimitry Andric /// Whether a path to an object supports lifetime extension.
9130fca6ea1SDimitry Andric enum PathLifetimeKind {
9140fca6ea1SDimitry Andric /// Lifetime-extend along this path.
9150fca6ea1SDimitry Andric Extend,
9160fca6ea1SDimitry Andric /// We should lifetime-extend, but we don't because (due to technical
9170fca6ea1SDimitry Andric /// limitations) we can't. This happens for default member initializers,
9180fca6ea1SDimitry Andric /// which we don't clone for every use, so we don't have a unique
9190fca6ea1SDimitry Andric /// MaterializeTemporaryExpr to update.
9200fca6ea1SDimitry Andric ShouldExtend,
9210fca6ea1SDimitry Andric /// Do not lifetime extend along this path.
9220fca6ea1SDimitry Andric NoExtend
9230fca6ea1SDimitry Andric };
9240fca6ea1SDimitry Andric
9250fca6ea1SDimitry Andric /// Determine whether this is an indirect path to a temporary that we are
9260fca6ea1SDimitry Andric /// supposed to lifetime-extend along.
9270fca6ea1SDimitry Andric static PathLifetimeKind
shouldLifetimeExtendThroughPath(const IndirectLocalPath & Path)9280fca6ea1SDimitry Andric shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
9290fca6ea1SDimitry Andric PathLifetimeKind Kind = PathLifetimeKind::Extend;
9300fca6ea1SDimitry Andric for (auto Elem : Path) {
9310fca6ea1SDimitry Andric if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)
9320fca6ea1SDimitry Andric Kind = PathLifetimeKind::ShouldExtend;
9330fca6ea1SDimitry Andric else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
9340fca6ea1SDimitry Andric return PathLifetimeKind::NoExtend;
9350fca6ea1SDimitry Andric }
9360fca6ea1SDimitry Andric return Kind;
9370fca6ea1SDimitry Andric }
9380fca6ea1SDimitry Andric
9390fca6ea1SDimitry Andric /// Find the range for the first interesting entry in the path at or after I.
nextPathEntryRange(const IndirectLocalPath & Path,unsigned I,Expr * E)9400fca6ea1SDimitry Andric static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
9410fca6ea1SDimitry Andric Expr *E) {
9420fca6ea1SDimitry Andric for (unsigned N = Path.size(); I != N; ++I) {
9430fca6ea1SDimitry Andric switch (Path[I].Kind) {
9440fca6ea1SDimitry Andric case IndirectLocalPathEntry::AddressOf:
9450fca6ea1SDimitry Andric case IndirectLocalPathEntry::LValToRVal:
9460fca6ea1SDimitry Andric case IndirectLocalPathEntry::LifetimeBoundCall:
9470fca6ea1SDimitry Andric case IndirectLocalPathEntry::TemporaryCopy:
9480fca6ea1SDimitry Andric case IndirectLocalPathEntry::GslReferenceInit:
9490fca6ea1SDimitry Andric case IndirectLocalPathEntry::GslPointerInit:
9500fca6ea1SDimitry Andric case IndirectLocalPathEntry::GslPointerAssignment:
9510fca6ea1SDimitry Andric // These exist primarily to mark the path as not permitting or
9520fca6ea1SDimitry Andric // supporting lifetime extension.
9530fca6ea1SDimitry Andric break;
9540fca6ea1SDimitry Andric
9550fca6ea1SDimitry Andric case IndirectLocalPathEntry::VarInit:
9560fca6ea1SDimitry Andric if (cast<VarDecl>(Path[I].D)->isImplicit())
9570fca6ea1SDimitry Andric return SourceRange();
9580fca6ea1SDimitry Andric [[fallthrough]];
9590fca6ea1SDimitry Andric case IndirectLocalPathEntry::DefaultInit:
9600fca6ea1SDimitry Andric return Path[I].E->getSourceRange();
9610fca6ea1SDimitry Andric
9620fca6ea1SDimitry Andric case IndirectLocalPathEntry::LambdaCaptureInit:
9630fca6ea1SDimitry Andric if (!Path[I].Capture->capturesVariable())
9640fca6ea1SDimitry Andric continue;
9650fca6ea1SDimitry Andric return Path[I].E->getSourceRange();
9660fca6ea1SDimitry Andric }
9670fca6ea1SDimitry Andric }
9680fca6ea1SDimitry Andric return E->getSourceRange();
9690fca6ea1SDimitry Andric }
9700fca6ea1SDimitry Andric
pathOnlyHandlesGslPointer(IndirectLocalPath & Path)9710fca6ea1SDimitry Andric static bool pathOnlyHandlesGslPointer(IndirectLocalPath &Path) {
9720fca6ea1SDimitry Andric for (const auto &It : llvm::reverse(Path)) {
9730fca6ea1SDimitry Andric switch (It.Kind) {
9740fca6ea1SDimitry Andric case IndirectLocalPathEntry::VarInit:
9750fca6ea1SDimitry Andric case IndirectLocalPathEntry::AddressOf:
9760fca6ea1SDimitry Andric case IndirectLocalPathEntry::LifetimeBoundCall:
9770fca6ea1SDimitry Andric continue;
9780fca6ea1SDimitry Andric case IndirectLocalPathEntry::GslPointerInit:
9790fca6ea1SDimitry Andric case IndirectLocalPathEntry::GslReferenceInit:
9800fca6ea1SDimitry Andric case IndirectLocalPathEntry::GslPointerAssignment:
9810fca6ea1SDimitry Andric return true;
9820fca6ea1SDimitry Andric default:
9830fca6ea1SDimitry Andric return false;
9840fca6ea1SDimitry Andric }
9850fca6ea1SDimitry Andric }
9860fca6ea1SDimitry Andric return false;
9870fca6ea1SDimitry Andric }
9880fca6ea1SDimitry Andric
checkExprLifetimeImpl(Sema & SemaRef,const InitializedEntity * InitEntity,const InitializedEntity * ExtendingEntity,LifetimeKind LK,const AssignedEntity * AEntity,Expr * Init,bool EnableLifetimeWarnings)9890fca6ea1SDimitry Andric static void checkExprLifetimeImpl(Sema &SemaRef,
9900fca6ea1SDimitry Andric const InitializedEntity *InitEntity,
9910fca6ea1SDimitry Andric const InitializedEntity *ExtendingEntity,
9920fca6ea1SDimitry Andric LifetimeKind LK,
9930fca6ea1SDimitry Andric const AssignedEntity *AEntity, Expr *Init,
9940fca6ea1SDimitry Andric bool EnableLifetimeWarnings) {
9950fca6ea1SDimitry Andric assert((AEntity && LK == LK_Assignment) ||
9960fca6ea1SDimitry Andric (InitEntity && LK != LK_Assignment));
9970fca6ea1SDimitry Andric // If this entity doesn't have an interesting lifetime, don't bother looking
9980fca6ea1SDimitry Andric // for temporaries within its initializer.
9990fca6ea1SDimitry Andric if (LK == LK_FullExpression)
10000fca6ea1SDimitry Andric return;
10010fca6ea1SDimitry Andric
10020fca6ea1SDimitry Andric // FIXME: consider moving the TemporaryVisitor and visitLocalsRetained*
10030fca6ea1SDimitry Andric // functions to a dedicated class.
10040fca6ea1SDimitry Andric auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L,
10050fca6ea1SDimitry Andric ReferenceKind RK) -> bool {
10060fca6ea1SDimitry Andric SourceRange DiagRange = nextPathEntryRange(Path, 0, L);
10070fca6ea1SDimitry Andric SourceLocation DiagLoc = DiagRange.getBegin();
10080fca6ea1SDimitry Andric
10090fca6ea1SDimitry Andric auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
10100fca6ea1SDimitry Andric
10110fca6ea1SDimitry Andric bool IsGslPtrValueFromGslTempOwner = false;
10120fca6ea1SDimitry Andric bool IsLocalGslOwner = false;
10130fca6ea1SDimitry Andric if (pathOnlyHandlesGslPointer(Path)) {
10140fca6ea1SDimitry Andric if (isa<DeclRefExpr>(L)) {
10150fca6ea1SDimitry Andric // We do not want to follow the references when returning a pointer
10160fca6ea1SDimitry Andric // originating from a local owner to avoid the following false positive:
10170fca6ea1SDimitry Andric // int &p = *localUniquePtr;
10180fca6ea1SDimitry Andric // someContainer.add(std::move(localUniquePtr));
10190fca6ea1SDimitry Andric // return p;
10200fca6ea1SDimitry Andric IsLocalGslOwner = isRecordWithAttr<OwnerAttr>(L->getType());
10210fca6ea1SDimitry Andric if (pathContainsInit(Path) || !IsLocalGslOwner)
10220fca6ea1SDimitry Andric return false;
10230fca6ea1SDimitry Andric } else {
10240fca6ea1SDimitry Andric IsGslPtrValueFromGslTempOwner =
10250fca6ea1SDimitry Andric MTE && !MTE->getExtendingDecl() &&
10260fca6ea1SDimitry Andric isRecordWithAttr<OwnerAttr>(MTE->getType());
10270fca6ea1SDimitry Andric // Skipping a chain of initializing gsl::Pointer annotated objects.
10280fca6ea1SDimitry Andric // We are looking only for the final source to find out if it was
10290fca6ea1SDimitry Andric // a local or temporary owner or the address of a local variable/param.
10300fca6ea1SDimitry Andric if (!IsGslPtrValueFromGslTempOwner)
10310fca6ea1SDimitry Andric return true;
10320fca6ea1SDimitry Andric }
10330fca6ea1SDimitry Andric }
10340fca6ea1SDimitry Andric
10350fca6ea1SDimitry Andric switch (LK) {
10360fca6ea1SDimitry Andric case LK_FullExpression:
10370fca6ea1SDimitry Andric llvm_unreachable("already handled this");
10380fca6ea1SDimitry Andric
10390fca6ea1SDimitry Andric case LK_Extended: {
10400fca6ea1SDimitry Andric if (!MTE) {
10410fca6ea1SDimitry Andric // The initialized entity has lifetime beyond the full-expression,
10420fca6ea1SDimitry Andric // and the local entity does too, so don't warn.
10430fca6ea1SDimitry Andric //
10440fca6ea1SDimitry Andric // FIXME: We should consider warning if a static / thread storage
10450fca6ea1SDimitry Andric // duration variable retains an automatic storage duration local.
10460fca6ea1SDimitry Andric return false;
10470fca6ea1SDimitry Andric }
10480fca6ea1SDimitry Andric
10490fca6ea1SDimitry Andric if (IsGslPtrValueFromGslTempOwner && DiagLoc.isValid()) {
10500fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
10510fca6ea1SDimitry Andric << DiagRange;
10520fca6ea1SDimitry Andric return false;
10530fca6ea1SDimitry Andric }
10540fca6ea1SDimitry Andric
10550fca6ea1SDimitry Andric switch (shouldLifetimeExtendThroughPath(Path)) {
10560fca6ea1SDimitry Andric case PathLifetimeKind::Extend:
10570fca6ea1SDimitry Andric // Update the storage duration of the materialized temporary.
10580fca6ea1SDimitry Andric // FIXME: Rebuild the expression instead of mutating it.
10590fca6ea1SDimitry Andric MTE->setExtendingDecl(ExtendingEntity->getDecl(),
10600fca6ea1SDimitry Andric ExtendingEntity->allocateManglingNumber());
10610fca6ea1SDimitry Andric // Also visit the temporaries lifetime-extended by this initializer.
10620fca6ea1SDimitry Andric return true;
10630fca6ea1SDimitry Andric
10640fca6ea1SDimitry Andric case PathLifetimeKind::ShouldExtend:
10650fca6ea1SDimitry Andric // We're supposed to lifetime-extend the temporary along this path (per
10660fca6ea1SDimitry Andric // the resolution of DR1815), but we don't support that yet.
10670fca6ea1SDimitry Andric //
10680fca6ea1SDimitry Andric // FIXME: Properly handle this situation. Perhaps the easiest approach
10690fca6ea1SDimitry Andric // would be to clone the initializer expression on each use that would
10700fca6ea1SDimitry Andric // lifetime extend its temporaries.
10710fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, diag::warn_unsupported_lifetime_extension)
10720fca6ea1SDimitry Andric << RK << DiagRange;
10730fca6ea1SDimitry Andric break;
10740fca6ea1SDimitry Andric
10750fca6ea1SDimitry Andric case PathLifetimeKind::NoExtend:
10760fca6ea1SDimitry Andric // If the path goes through the initialization of a variable or field,
10770fca6ea1SDimitry Andric // it can't possibly reach a temporary created in this full-expression.
10780fca6ea1SDimitry Andric // We will have already diagnosed any problems with the initializer.
10790fca6ea1SDimitry Andric if (pathContainsInit(Path))
10800fca6ea1SDimitry Andric return false;
10810fca6ea1SDimitry Andric
10820fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, diag::warn_dangling_variable)
10830fca6ea1SDimitry Andric << RK << !InitEntity->getParent()
10840fca6ea1SDimitry Andric << ExtendingEntity->getDecl()->isImplicit()
10850fca6ea1SDimitry Andric << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;
10860fca6ea1SDimitry Andric break;
10870fca6ea1SDimitry Andric }
10880fca6ea1SDimitry Andric break;
10890fca6ea1SDimitry Andric }
10900fca6ea1SDimitry Andric
10910fca6ea1SDimitry Andric case LK_Assignment: {
10920fca6ea1SDimitry Andric if (!MTE || pathContainsInit(Path))
10930fca6ea1SDimitry Andric return false;
10940fca6ea1SDimitry Andric assert(shouldLifetimeExtendThroughPath(Path) ==
10950fca6ea1SDimitry Andric PathLifetimeKind::NoExtend &&
10960fca6ea1SDimitry Andric "No lifetime extension for assignments");
10970fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc,
10980fca6ea1SDimitry Andric IsGslPtrValueFromGslTempOwner
10990fca6ea1SDimitry Andric ? diag::warn_dangling_lifetime_pointer_assignment
11000fca6ea1SDimitry Andric : diag::warn_dangling_pointer_assignment)
11010fca6ea1SDimitry Andric << AEntity->LHS << DiagRange;
11020fca6ea1SDimitry Andric return false;
11030fca6ea1SDimitry Andric }
11040fca6ea1SDimitry Andric case LK_MemInitializer: {
11050fca6ea1SDimitry Andric if (MTE) {
11060fca6ea1SDimitry Andric // Under C++ DR1696, if a mem-initializer (or a default member
11070fca6ea1SDimitry Andric // initializer used by the absence of one) would lifetime-extend a
11080fca6ea1SDimitry Andric // temporary, the program is ill-formed.
11090fca6ea1SDimitry Andric if (auto *ExtendingDecl =
11100fca6ea1SDimitry Andric ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
11110fca6ea1SDimitry Andric if (IsGslPtrValueFromGslTempOwner) {
11120fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
11130fca6ea1SDimitry Andric << ExtendingDecl << DiagRange;
11140fca6ea1SDimitry Andric SemaRef.Diag(ExtendingDecl->getLocation(),
11150fca6ea1SDimitry Andric diag::note_ref_or_ptr_member_declared_here)
11160fca6ea1SDimitry Andric << true;
11170fca6ea1SDimitry Andric return false;
11180fca6ea1SDimitry Andric }
11190fca6ea1SDimitry Andric bool IsSubobjectMember = ExtendingEntity != InitEntity;
11200fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) !=
11210fca6ea1SDimitry Andric PathLifetimeKind::NoExtend
11220fca6ea1SDimitry Andric ? diag::err_dangling_member
11230fca6ea1SDimitry Andric : diag::warn_dangling_member)
11240fca6ea1SDimitry Andric << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
11250fca6ea1SDimitry Andric // Don't bother adding a note pointing to the field if we're inside
11260fca6ea1SDimitry Andric // its default member initializer; our primary diagnostic points to
11270fca6ea1SDimitry Andric // the same place in that case.
11280fca6ea1SDimitry Andric if (Path.empty() ||
11290fca6ea1SDimitry Andric Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
11300fca6ea1SDimitry Andric SemaRef.Diag(ExtendingDecl->getLocation(),
11310fca6ea1SDimitry Andric diag::note_lifetime_extending_member_declared_here)
11320fca6ea1SDimitry Andric << RK << IsSubobjectMember;
11330fca6ea1SDimitry Andric }
11340fca6ea1SDimitry Andric } else {
11350fca6ea1SDimitry Andric // We have a mem-initializer but no particular field within it; this
11360fca6ea1SDimitry Andric // is either a base class or a delegating initializer directly
11370fca6ea1SDimitry Andric // initializing the base-class from something that doesn't live long
11380fca6ea1SDimitry Andric // enough.
11390fca6ea1SDimitry Andric //
11400fca6ea1SDimitry Andric // FIXME: Warn on this.
11410fca6ea1SDimitry Andric return false;
11420fca6ea1SDimitry Andric }
11430fca6ea1SDimitry Andric } else {
11440fca6ea1SDimitry Andric // Paths via a default initializer can only occur during error recovery
11450fca6ea1SDimitry Andric // (there's no other way that a default initializer can refer to a
11460fca6ea1SDimitry Andric // local). Don't produce a bogus warning on those cases.
11470fca6ea1SDimitry Andric if (pathContainsInit(Path))
11480fca6ea1SDimitry Andric return false;
11490fca6ea1SDimitry Andric
11500fca6ea1SDimitry Andric // Suppress false positives for code like the one below:
11510fca6ea1SDimitry Andric // Ctor(unique_ptr<T> up) : member(*up), member2(move(up)) {}
11520fca6ea1SDimitry Andric if (IsLocalGslOwner && pathOnlyHandlesGslPointer(Path))
11530fca6ea1SDimitry Andric return false;
11540fca6ea1SDimitry Andric
11550fca6ea1SDimitry Andric auto *DRE = dyn_cast<DeclRefExpr>(L);
11560fca6ea1SDimitry Andric auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
11570fca6ea1SDimitry Andric if (!VD) {
11580fca6ea1SDimitry Andric // A member was initialized to a local block.
11590fca6ea1SDimitry Andric // FIXME: Warn on this.
11600fca6ea1SDimitry Andric return false;
11610fca6ea1SDimitry Andric }
11620fca6ea1SDimitry Andric
11630fca6ea1SDimitry Andric if (auto *Member =
11640fca6ea1SDimitry Andric ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
11650fca6ea1SDimitry Andric bool IsPointer = !Member->getType()->isReferenceType();
11660fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc,
11670fca6ea1SDimitry Andric IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
11680fca6ea1SDimitry Andric : diag::warn_bind_ref_member_to_parameter)
11690fca6ea1SDimitry Andric << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
11700fca6ea1SDimitry Andric SemaRef.Diag(Member->getLocation(),
11710fca6ea1SDimitry Andric diag::note_ref_or_ptr_member_declared_here)
11720fca6ea1SDimitry Andric << (unsigned)IsPointer;
11730fca6ea1SDimitry Andric }
11740fca6ea1SDimitry Andric }
11750fca6ea1SDimitry Andric break;
11760fca6ea1SDimitry Andric }
11770fca6ea1SDimitry Andric
11780fca6ea1SDimitry Andric case LK_New:
11790fca6ea1SDimitry Andric if (isa<MaterializeTemporaryExpr>(L)) {
11800fca6ea1SDimitry Andric if (IsGslPtrValueFromGslTempOwner)
11810fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
11820fca6ea1SDimitry Andric << DiagRange;
11830fca6ea1SDimitry Andric else
11840fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, RK == RK_ReferenceBinding
11850fca6ea1SDimitry Andric ? diag::warn_new_dangling_reference
11860fca6ea1SDimitry Andric : diag::warn_new_dangling_initializer_list)
11870fca6ea1SDimitry Andric << !InitEntity->getParent() << DiagRange;
11880fca6ea1SDimitry Andric } else {
11890fca6ea1SDimitry Andric // We can't determine if the allocation outlives the local declaration.
11900fca6ea1SDimitry Andric return false;
11910fca6ea1SDimitry Andric }
11920fca6ea1SDimitry Andric break;
11930fca6ea1SDimitry Andric
11940fca6ea1SDimitry Andric case LK_Return:
11950fca6ea1SDimitry Andric case LK_StmtExprResult:
11960fca6ea1SDimitry Andric if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
11970fca6ea1SDimitry Andric // We can't determine if the local variable outlives the statement
11980fca6ea1SDimitry Andric // expression.
11990fca6ea1SDimitry Andric if (LK == LK_StmtExprResult)
12000fca6ea1SDimitry Andric return false;
12010fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
12020fca6ea1SDimitry Andric << InitEntity->getType()->isReferenceType() << DRE->getDecl()
12030fca6ea1SDimitry Andric << isa<ParmVarDecl>(DRE->getDecl()) << DiagRange;
12040fca6ea1SDimitry Andric } else if (isa<BlockExpr>(L)) {
12050fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
12060fca6ea1SDimitry Andric } else if (isa<AddrLabelExpr>(L)) {
12070fca6ea1SDimitry Andric // Don't warn when returning a label from a statement expression.
12080fca6ea1SDimitry Andric // Leaving the scope doesn't end its lifetime.
12090fca6ea1SDimitry Andric if (LK == LK_StmtExprResult)
12100fca6ea1SDimitry Andric return false;
12110fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
12120fca6ea1SDimitry Andric } else if (auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
12130fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
12140fca6ea1SDimitry Andric << InitEntity->getType()->isReferenceType() << CLE->getInitializer()
12150fca6ea1SDimitry Andric << 2 << DiagRange;
12160fca6ea1SDimitry Andric } else {
12170fca6ea1SDimitry Andric // P2748R5: Disallow Binding a Returned Glvalue to a Temporary.
12180fca6ea1SDimitry Andric // [stmt.return]/p6: In a function whose return type is a reference,
12190fca6ea1SDimitry Andric // other than an invented function for std::is_convertible ([meta.rel]),
12200fca6ea1SDimitry Andric // a return statement that binds the returned reference to a temporary
12210fca6ea1SDimitry Andric // expression ([class.temporary]) is ill-formed.
12220fca6ea1SDimitry Andric if (SemaRef.getLangOpts().CPlusPlus26 &&
12230fca6ea1SDimitry Andric InitEntity->getType()->isReferenceType())
12240fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, diag::err_ret_local_temp_ref)
12250fca6ea1SDimitry Andric << InitEntity->getType()->isReferenceType() << DiagRange;
12260fca6ea1SDimitry Andric else
12270fca6ea1SDimitry Andric SemaRef.Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
12280fca6ea1SDimitry Andric << InitEntity->getType()->isReferenceType() << DiagRange;
12290fca6ea1SDimitry Andric }
12300fca6ea1SDimitry Andric break;
12310fca6ea1SDimitry Andric }
12320fca6ea1SDimitry Andric
12330fca6ea1SDimitry Andric for (unsigned I = 0; I != Path.size(); ++I) {
12340fca6ea1SDimitry Andric auto Elem = Path[I];
12350fca6ea1SDimitry Andric
12360fca6ea1SDimitry Andric switch (Elem.Kind) {
12370fca6ea1SDimitry Andric case IndirectLocalPathEntry::AddressOf:
12380fca6ea1SDimitry Andric case IndirectLocalPathEntry::LValToRVal:
12390fca6ea1SDimitry Andric // These exist primarily to mark the path as not permitting or
12400fca6ea1SDimitry Andric // supporting lifetime extension.
12410fca6ea1SDimitry Andric break;
12420fca6ea1SDimitry Andric
12430fca6ea1SDimitry Andric case IndirectLocalPathEntry::LifetimeBoundCall:
12440fca6ea1SDimitry Andric case IndirectLocalPathEntry::TemporaryCopy:
12450fca6ea1SDimitry Andric case IndirectLocalPathEntry::GslPointerInit:
12460fca6ea1SDimitry Andric case IndirectLocalPathEntry::GslReferenceInit:
12470fca6ea1SDimitry Andric case IndirectLocalPathEntry::GslPointerAssignment:
12480fca6ea1SDimitry Andric // FIXME: Consider adding a note for these.
12490fca6ea1SDimitry Andric break;
12500fca6ea1SDimitry Andric
12510fca6ea1SDimitry Andric case IndirectLocalPathEntry::DefaultInit: {
12520fca6ea1SDimitry Andric auto *FD = cast<FieldDecl>(Elem.D);
12530fca6ea1SDimitry Andric SemaRef.Diag(FD->getLocation(),
12540fca6ea1SDimitry Andric diag::note_init_with_default_member_initializer)
12550fca6ea1SDimitry Andric << FD << nextPathEntryRange(Path, I + 1, L);
12560fca6ea1SDimitry Andric break;
12570fca6ea1SDimitry Andric }
12580fca6ea1SDimitry Andric
12590fca6ea1SDimitry Andric case IndirectLocalPathEntry::VarInit: {
12600fca6ea1SDimitry Andric const VarDecl *VD = cast<VarDecl>(Elem.D);
12610fca6ea1SDimitry Andric SemaRef.Diag(VD->getLocation(), diag::note_local_var_initializer)
12620fca6ea1SDimitry Andric << VD->getType()->isReferenceType() << VD->isImplicit()
12630fca6ea1SDimitry Andric << VD->getDeclName() << nextPathEntryRange(Path, I + 1, L);
12640fca6ea1SDimitry Andric break;
12650fca6ea1SDimitry Andric }
12660fca6ea1SDimitry Andric
12670fca6ea1SDimitry Andric case IndirectLocalPathEntry::LambdaCaptureInit:
12680fca6ea1SDimitry Andric if (!Elem.Capture->capturesVariable())
12690fca6ea1SDimitry Andric break;
12700fca6ea1SDimitry Andric // FIXME: We can't easily tell apart an init-capture from a nested
12710fca6ea1SDimitry Andric // capture of an init-capture.
12720fca6ea1SDimitry Andric const ValueDecl *VD = Elem.Capture->getCapturedVar();
12730fca6ea1SDimitry Andric SemaRef.Diag(Elem.Capture->getLocation(),
12740fca6ea1SDimitry Andric diag::note_lambda_capture_initializer)
12750fca6ea1SDimitry Andric << VD << VD->isInitCapture() << Elem.Capture->isExplicit()
12760fca6ea1SDimitry Andric << (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD
12770fca6ea1SDimitry Andric << nextPathEntryRange(Path, I + 1, L);
12780fca6ea1SDimitry Andric break;
12790fca6ea1SDimitry Andric }
12800fca6ea1SDimitry Andric }
12810fca6ea1SDimitry Andric
12820fca6ea1SDimitry Andric // We didn't lifetime-extend, so don't go any further; we don't need more
12830fca6ea1SDimitry Andric // warnings or errors on inner temporaries within this one's initializer.
12840fca6ea1SDimitry Andric return false;
12850fca6ea1SDimitry Andric };
12860fca6ea1SDimitry Andric
12870fca6ea1SDimitry Andric llvm::SmallVector<IndirectLocalPathEntry, 8> Path;
12880fca6ea1SDimitry Andric if (EnableLifetimeWarnings && LK == LK_Assignment &&
12890fca6ea1SDimitry Andric isRecordWithAttr<PointerAttr>(AEntity->LHS->getType()))
12900fca6ea1SDimitry Andric Path.push_back({IndirectLocalPathEntry::GslPointerAssignment, Init});
12910fca6ea1SDimitry Andric
12920fca6ea1SDimitry Andric if (Init->isGLValue())
12930fca6ea1SDimitry Andric visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding,
12940fca6ea1SDimitry Andric TemporaryVisitor,
12950fca6ea1SDimitry Andric EnableLifetimeWarnings);
12960fca6ea1SDimitry Andric else
12970fca6ea1SDimitry Andric visitLocalsRetainedByInitializer(
12980fca6ea1SDimitry Andric Path, Init, TemporaryVisitor,
12990fca6ea1SDimitry Andric // Don't revisit the sub inits for the intialization case.
13000fca6ea1SDimitry Andric /*RevisitSubinits=*/!InitEntity, EnableLifetimeWarnings);
13010fca6ea1SDimitry Andric }
13020fca6ea1SDimitry Andric
checkExprLifetime(Sema & SemaRef,const InitializedEntity & Entity,Expr * Init)13030fca6ea1SDimitry Andric void checkExprLifetime(Sema &SemaRef, const InitializedEntity &Entity,
13040fca6ea1SDimitry Andric Expr *Init) {
13050fca6ea1SDimitry Andric auto LTResult = getEntityLifetime(&Entity);
13060fca6ea1SDimitry Andric LifetimeKind LK = LTResult.getInt();
13070fca6ea1SDimitry Andric const InitializedEntity *ExtendingEntity = LTResult.getPointer();
13080fca6ea1SDimitry Andric bool EnableLifetimeWarnings = !SemaRef.getDiagnostics().isIgnored(
13090fca6ea1SDimitry Andric diag::warn_dangling_lifetime_pointer, SourceLocation());
13100fca6ea1SDimitry Andric checkExprLifetimeImpl(SemaRef, &Entity, ExtendingEntity, LK,
13110fca6ea1SDimitry Andric /*AEntity*/ nullptr, Init, EnableLifetimeWarnings);
13120fca6ea1SDimitry Andric }
13130fca6ea1SDimitry Andric
checkExprLifetime(Sema & SemaRef,const AssignedEntity & Entity,Expr * Init)13140fca6ea1SDimitry Andric void checkExprLifetime(Sema &SemaRef, const AssignedEntity &Entity,
13150fca6ea1SDimitry Andric Expr *Init) {
13160fca6ea1SDimitry Andric bool EnableLifetimeWarnings = !SemaRef.getDiagnostics().isIgnored(
13170fca6ea1SDimitry Andric diag::warn_dangling_lifetime_pointer, SourceLocation());
13180fca6ea1SDimitry Andric bool RunAnalysis = Entity.LHS->getType()->isPointerType() ||
13190fca6ea1SDimitry Andric (EnableLifetimeWarnings &&
13200fca6ea1SDimitry Andric isRecordWithAttr<PointerAttr>(Entity.LHS->getType()));
13210fca6ea1SDimitry Andric
13220fca6ea1SDimitry Andric if (!RunAnalysis)
13230fca6ea1SDimitry Andric return;
13240fca6ea1SDimitry Andric
13250fca6ea1SDimitry Andric checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr,
13260fca6ea1SDimitry Andric /*ExtendingEntity=*/nullptr, LK_Assignment, &Entity,
13270fca6ea1SDimitry Andric Init, EnableLifetimeWarnings);
13280fca6ea1SDimitry Andric }
13290fca6ea1SDimitry Andric
13300fca6ea1SDimitry Andric } // namespace clang::sema
1331