xref: /freebsd/contrib/llvm-project/clang/lib/Sema/CheckExprLifetime.cpp (revision 52418fc2be8efa5172b90a3a9e617017173612c4)
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