xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/CheckExprLifetime.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===--- CheckExprLifetime.cpp --------------------------------------------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric 
9*0fca6ea1SDimitry Andric #include "CheckExprLifetime.h"
10*0fca6ea1SDimitry Andric #include "clang/AST/Expr.h"
11*0fca6ea1SDimitry Andric #include "clang/Basic/DiagnosticSema.h"
12*0fca6ea1SDimitry Andric #include "clang/Sema/Initialization.h"
13*0fca6ea1SDimitry Andric #include "clang/Sema/Sema.h"
14*0fca6ea1SDimitry Andric #include "llvm/ADT/PointerIntPair.h"
15*0fca6ea1SDimitry Andric 
16*0fca6ea1SDimitry Andric namespace clang::sema {
17*0fca6ea1SDimitry Andric namespace {
18*0fca6ea1SDimitry Andric enum LifetimeKind {
19*0fca6ea1SDimitry Andric   /// The lifetime of a temporary bound to this entity ends at the end of the
20*0fca6ea1SDimitry Andric   /// full-expression, and that's (probably) fine.
21*0fca6ea1SDimitry Andric   LK_FullExpression,
22*0fca6ea1SDimitry Andric 
23*0fca6ea1SDimitry Andric   /// The lifetime of a temporary bound to this entity is extended to the
24*0fca6ea1SDimitry Andric   /// lifeitme of the entity itself.
25*0fca6ea1SDimitry Andric   LK_Extended,
26*0fca6ea1SDimitry Andric 
27*0fca6ea1SDimitry Andric   /// The lifetime of a temporary bound to this entity probably ends too soon,
28*0fca6ea1SDimitry Andric   /// because the entity is allocated in a new-expression.
29*0fca6ea1SDimitry Andric   LK_New,
30*0fca6ea1SDimitry Andric 
31*0fca6ea1SDimitry Andric   /// The lifetime of a temporary bound to this entity ends too soon, because
32*0fca6ea1SDimitry Andric   /// the entity is a return object.
33*0fca6ea1SDimitry Andric   LK_Return,
34*0fca6ea1SDimitry Andric 
35*0fca6ea1SDimitry Andric   /// The lifetime of a temporary bound to this entity ends too soon, because
36*0fca6ea1SDimitry Andric   /// the entity is the result of a statement expression.
37*0fca6ea1SDimitry Andric   LK_StmtExprResult,
38*0fca6ea1SDimitry Andric 
39*0fca6ea1SDimitry Andric   /// This is a mem-initializer: if it would extend a temporary (other than via
40*0fca6ea1SDimitry Andric   /// a default member initializer), the program is ill-formed.
41*0fca6ea1SDimitry Andric   LK_MemInitializer,
42*0fca6ea1SDimitry Andric 
43*0fca6ea1SDimitry Andric   /// The lifetime of a temporary bound to this entity probably ends too soon,
44*0fca6ea1SDimitry Andric   /// because the entity is a pointer and we assign the address of a temporary
45*0fca6ea1SDimitry Andric   /// object to it.
46*0fca6ea1SDimitry Andric   LK_Assignment,
47*0fca6ea1SDimitry Andric };
48*0fca6ea1SDimitry Andric using LifetimeResult =
49*0fca6ea1SDimitry Andric     llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
50*0fca6ea1SDimitry Andric } // namespace
51*0fca6ea1SDimitry Andric 
52*0fca6ea1SDimitry Andric /// Determine the declaration which an initialized entity ultimately refers to,
53*0fca6ea1SDimitry Andric /// for the purpose of lifetime-extending a temporary bound to a reference in
54*0fca6ea1SDimitry Andric /// the initialization of \p Entity.
55*0fca6ea1SDimitry Andric static LifetimeResult
56*0fca6ea1SDimitry Andric getEntityLifetime(const InitializedEntity *Entity,
57*0fca6ea1SDimitry Andric                   const InitializedEntity *InitField = nullptr) {
58*0fca6ea1SDimitry Andric   // C++11 [class.temporary]p5:
59*0fca6ea1SDimitry Andric   switch (Entity->getKind()) {
60*0fca6ea1SDimitry Andric   case InitializedEntity::EK_Variable:
61*0fca6ea1SDimitry Andric     //   The temporary [...] persists for the lifetime of the reference
62*0fca6ea1SDimitry Andric     return {Entity, LK_Extended};
63*0fca6ea1SDimitry Andric 
64*0fca6ea1SDimitry Andric   case InitializedEntity::EK_Member:
65*0fca6ea1SDimitry Andric     // For subobjects, we look at the complete object.
66*0fca6ea1SDimitry Andric     if (Entity->getParent())
67*0fca6ea1SDimitry Andric       return getEntityLifetime(Entity->getParent(), Entity);
68*0fca6ea1SDimitry Andric 
69*0fca6ea1SDimitry Andric     //   except:
70*0fca6ea1SDimitry Andric     // C++17 [class.base.init]p8:
71*0fca6ea1SDimitry Andric     //   A temporary expression bound to a reference member in a
72*0fca6ea1SDimitry Andric     //   mem-initializer is ill-formed.
73*0fca6ea1SDimitry Andric     // C++17 [class.base.init]p11:
74*0fca6ea1SDimitry Andric     //   A temporary expression bound to a reference member from a
75*0fca6ea1SDimitry Andric     //   default member initializer is ill-formed.
76*0fca6ea1SDimitry Andric     //
77*0fca6ea1SDimitry Andric     // The context of p11 and its example suggest that it's only the use of a
78*0fca6ea1SDimitry Andric     // default member initializer from a constructor that makes the program
79*0fca6ea1SDimitry Andric     // ill-formed, not its mere existence, and that it can even be used by
80*0fca6ea1SDimitry Andric     // aggregate initialization.
81*0fca6ea1SDimitry Andric     return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
82*0fca6ea1SDimitry Andric                                                          : LK_MemInitializer};
83*0fca6ea1SDimitry Andric 
84*0fca6ea1SDimitry Andric   case InitializedEntity::EK_Binding:
85*0fca6ea1SDimitry Andric     // Per [dcl.decomp]p3, the binding is treated as a variable of reference
86*0fca6ea1SDimitry Andric     // type.
87*0fca6ea1SDimitry Andric     return {Entity, LK_Extended};
88*0fca6ea1SDimitry Andric 
89*0fca6ea1SDimitry Andric   case InitializedEntity::EK_Parameter:
90*0fca6ea1SDimitry Andric   case InitializedEntity::EK_Parameter_CF_Audited:
91*0fca6ea1SDimitry Andric     //   -- A temporary bound to a reference parameter in a function call
92*0fca6ea1SDimitry Andric     //      persists until the completion of the full-expression containing
93*0fca6ea1SDimitry Andric     //      the call.
94*0fca6ea1SDimitry Andric     return {nullptr, LK_FullExpression};
95*0fca6ea1SDimitry Andric 
96*0fca6ea1SDimitry Andric   case InitializedEntity::EK_TemplateParameter:
97*0fca6ea1SDimitry Andric     // FIXME: This will always be ill-formed; should we eagerly diagnose it
98*0fca6ea1SDimitry Andric     // here?
99*0fca6ea1SDimitry Andric     return {nullptr, LK_FullExpression};
100*0fca6ea1SDimitry Andric 
101*0fca6ea1SDimitry Andric   case InitializedEntity::EK_Result:
102*0fca6ea1SDimitry Andric     //   -- The lifetime of a temporary bound to the returned value in a
103*0fca6ea1SDimitry Andric     //      function return statement is not extended; the temporary is
104*0fca6ea1SDimitry Andric     //      destroyed at the end of the full-expression in the return statement.
105*0fca6ea1SDimitry Andric     return {nullptr, LK_Return};
106*0fca6ea1SDimitry Andric 
107*0fca6ea1SDimitry Andric   case InitializedEntity::EK_StmtExprResult:
108*0fca6ea1SDimitry Andric     // FIXME: Should we lifetime-extend through the result of a statement
109*0fca6ea1SDimitry Andric     // expression?
110*0fca6ea1SDimitry Andric     return {nullptr, LK_StmtExprResult};
111*0fca6ea1SDimitry Andric 
112*0fca6ea1SDimitry Andric   case InitializedEntity::EK_New:
113*0fca6ea1SDimitry Andric     //   -- A temporary bound to a reference in a new-initializer persists
114*0fca6ea1SDimitry Andric     //      until the completion of the full-expression containing the
115*0fca6ea1SDimitry Andric     //      new-initializer.
116*0fca6ea1SDimitry Andric     return {nullptr, LK_New};
117*0fca6ea1SDimitry Andric 
118*0fca6ea1SDimitry Andric   case InitializedEntity::EK_Temporary:
119*0fca6ea1SDimitry Andric   case InitializedEntity::EK_CompoundLiteralInit:
120*0fca6ea1SDimitry Andric   case InitializedEntity::EK_RelatedResult:
121*0fca6ea1SDimitry Andric     // We don't yet know the storage duration of the surrounding temporary.
122*0fca6ea1SDimitry Andric     // Assume it's got full-expression duration for now, it will patch up our
123*0fca6ea1SDimitry Andric     // storage duration if that's not correct.
124*0fca6ea1SDimitry Andric     return {nullptr, LK_FullExpression};
125*0fca6ea1SDimitry Andric 
126*0fca6ea1SDimitry Andric   case InitializedEntity::EK_ArrayElement:
127*0fca6ea1SDimitry Andric     // For subobjects, we look at the complete object.
128*0fca6ea1SDimitry Andric     return getEntityLifetime(Entity->getParent(), InitField);
129*0fca6ea1SDimitry Andric 
130*0fca6ea1SDimitry Andric   case InitializedEntity::EK_Base:
131*0fca6ea1SDimitry Andric     // For subobjects, we look at the complete object.
132*0fca6ea1SDimitry Andric     if (Entity->getParent())
133*0fca6ea1SDimitry Andric       return getEntityLifetime(Entity->getParent(), InitField);
134*0fca6ea1SDimitry Andric     return {InitField, LK_MemInitializer};
135*0fca6ea1SDimitry Andric 
136*0fca6ea1SDimitry Andric   case InitializedEntity::EK_Delegating:
137*0fca6ea1SDimitry Andric     // We can reach this case for aggregate initialization in a constructor:
138*0fca6ea1SDimitry Andric     //   struct A { int &&r; };
139*0fca6ea1SDimitry Andric     //   struct B : A { B() : A{0} {} };
140*0fca6ea1SDimitry Andric     // In this case, use the outermost field decl as the context.
141*0fca6ea1SDimitry Andric     return {InitField, LK_MemInitializer};
142*0fca6ea1SDimitry Andric 
143*0fca6ea1SDimitry Andric   case InitializedEntity::EK_BlockElement:
144*0fca6ea1SDimitry Andric   case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
145*0fca6ea1SDimitry Andric   case InitializedEntity::EK_LambdaCapture:
146*0fca6ea1SDimitry Andric   case InitializedEntity::EK_VectorElement:
147*0fca6ea1SDimitry Andric   case InitializedEntity::EK_ComplexElement:
148*0fca6ea1SDimitry Andric     return {nullptr, LK_FullExpression};
149*0fca6ea1SDimitry Andric 
150*0fca6ea1SDimitry Andric   case InitializedEntity::EK_Exception:
151*0fca6ea1SDimitry Andric     // FIXME: Can we diagnose lifetime problems with exceptions?
152*0fca6ea1SDimitry Andric     return {nullptr, LK_FullExpression};
153*0fca6ea1SDimitry Andric 
154*0fca6ea1SDimitry Andric   case InitializedEntity::EK_ParenAggInitMember:
155*0fca6ea1SDimitry Andric     //   -- A temporary object bound to a reference element of an aggregate of
156*0fca6ea1SDimitry Andric     //      class type initialized from a parenthesized expression-list
157*0fca6ea1SDimitry Andric     //      [dcl.init, 9.3] persists until the completion of the full-expression
158*0fca6ea1SDimitry Andric     //      containing the expression-list.
159*0fca6ea1SDimitry Andric     return {nullptr, LK_FullExpression};
160*0fca6ea1SDimitry Andric   }
161*0fca6ea1SDimitry Andric 
162*0fca6ea1SDimitry Andric   llvm_unreachable("unknown entity kind");
163*0fca6ea1SDimitry Andric }
164*0fca6ea1SDimitry Andric 
165*0fca6ea1SDimitry Andric namespace {
166*0fca6ea1SDimitry Andric enum ReferenceKind {
167*0fca6ea1SDimitry Andric   /// Lifetime would be extended by a reference binding to a temporary.
168*0fca6ea1SDimitry Andric   RK_ReferenceBinding,
169*0fca6ea1SDimitry Andric   /// Lifetime would be extended by a std::initializer_list object binding to
170*0fca6ea1SDimitry Andric   /// its backing array.
171*0fca6ea1SDimitry Andric   RK_StdInitializerList,
172*0fca6ea1SDimitry Andric };
173*0fca6ea1SDimitry Andric 
174*0fca6ea1SDimitry Andric /// A temporary or local variable. This will be one of:
175*0fca6ea1SDimitry Andric ///  * A MaterializeTemporaryExpr.
176*0fca6ea1SDimitry Andric ///  * A DeclRefExpr whose declaration is a local.
177*0fca6ea1SDimitry Andric ///  * An AddrLabelExpr.
178*0fca6ea1SDimitry Andric ///  * A BlockExpr for a block with captures.
179*0fca6ea1SDimitry Andric using Local = Expr *;
180*0fca6ea1SDimitry Andric 
181*0fca6ea1SDimitry Andric /// Expressions we stepped over when looking for the local state. Any steps
182*0fca6ea1SDimitry Andric /// that would inhibit lifetime extension or take us out of subexpressions of
183*0fca6ea1SDimitry Andric /// the initializer are included.
184*0fca6ea1SDimitry Andric struct IndirectLocalPathEntry {
185*0fca6ea1SDimitry Andric   enum EntryKind {
186*0fca6ea1SDimitry Andric     DefaultInit,
187*0fca6ea1SDimitry Andric     AddressOf,
188*0fca6ea1SDimitry Andric     VarInit,
189*0fca6ea1SDimitry Andric     LValToRVal,
190*0fca6ea1SDimitry Andric     LifetimeBoundCall,
191*0fca6ea1SDimitry Andric     TemporaryCopy,
192*0fca6ea1SDimitry Andric     LambdaCaptureInit,
193*0fca6ea1SDimitry Andric     GslReferenceInit,
194*0fca6ea1SDimitry Andric     GslPointerInit,
195*0fca6ea1SDimitry Andric     GslPointerAssignment,
196*0fca6ea1SDimitry Andric   } Kind;
197*0fca6ea1SDimitry Andric   Expr *E;
198*0fca6ea1SDimitry Andric   union {
199*0fca6ea1SDimitry Andric     const Decl *D = nullptr;
200*0fca6ea1SDimitry Andric     const LambdaCapture *Capture;
201*0fca6ea1SDimitry Andric   };
202*0fca6ea1SDimitry Andric   IndirectLocalPathEntry() {}
203*0fca6ea1SDimitry Andric   IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
204*0fca6ea1SDimitry Andric   IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D)
205*0fca6ea1SDimitry Andric       : Kind(K), E(E), D(D) {}
206*0fca6ea1SDimitry Andric   IndirectLocalPathEntry(EntryKind K, Expr *E, const LambdaCapture *Capture)
207*0fca6ea1SDimitry Andric       : Kind(K), E(E), Capture(Capture) {}
208*0fca6ea1SDimitry Andric };
209*0fca6ea1SDimitry Andric 
210*0fca6ea1SDimitry Andric using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;
211*0fca6ea1SDimitry Andric 
212*0fca6ea1SDimitry Andric struct RevertToOldSizeRAII {
213*0fca6ea1SDimitry Andric   IndirectLocalPath &Path;
214*0fca6ea1SDimitry Andric   unsigned OldSize = Path.size();
215*0fca6ea1SDimitry Andric   RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
216*0fca6ea1SDimitry Andric   ~RevertToOldSizeRAII() { Path.resize(OldSize); }
217*0fca6ea1SDimitry Andric };
218*0fca6ea1SDimitry Andric 
219*0fca6ea1SDimitry Andric using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
220*0fca6ea1SDimitry Andric                                              ReferenceKind RK)>;
221*0fca6ea1SDimitry Andric } // namespace
222*0fca6ea1SDimitry Andric 
223*0fca6ea1SDimitry Andric static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) {
224*0fca6ea1SDimitry Andric   for (auto E : Path)
225*0fca6ea1SDimitry Andric     if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
226*0fca6ea1SDimitry Andric       return true;
227*0fca6ea1SDimitry Andric   return false;
228*0fca6ea1SDimitry Andric }
229*0fca6ea1SDimitry Andric 
230*0fca6ea1SDimitry Andric static bool pathContainsInit(IndirectLocalPath &Path) {
231*0fca6ea1SDimitry Andric   return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
232*0fca6ea1SDimitry Andric     return E.Kind == IndirectLocalPathEntry::DefaultInit ||
233*0fca6ea1SDimitry Andric            E.Kind == IndirectLocalPathEntry::VarInit;
234*0fca6ea1SDimitry Andric   });
235*0fca6ea1SDimitry Andric }
236*0fca6ea1SDimitry Andric 
237*0fca6ea1SDimitry Andric static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
238*0fca6ea1SDimitry Andric                                              Expr *Init, LocalVisitor Visit,
239*0fca6ea1SDimitry Andric                                              bool RevisitSubinits,
240*0fca6ea1SDimitry Andric                                              bool EnableLifetimeWarnings);
241*0fca6ea1SDimitry Andric 
242*0fca6ea1SDimitry Andric static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
243*0fca6ea1SDimitry Andric                                                   Expr *Init, ReferenceKind RK,
244*0fca6ea1SDimitry Andric                                                   LocalVisitor Visit,
245*0fca6ea1SDimitry Andric                                                   bool EnableLifetimeWarnings);
246*0fca6ea1SDimitry Andric 
247*0fca6ea1SDimitry Andric template <typename T> static bool isRecordWithAttr(QualType Type) {
248*0fca6ea1SDimitry Andric   if (auto *RD = Type->getAsCXXRecordDecl())
249*0fca6ea1SDimitry Andric     return RD->hasAttr<T>();
250*0fca6ea1SDimitry Andric   return false;
251*0fca6ea1SDimitry Andric }
252*0fca6ea1SDimitry Andric 
253*0fca6ea1SDimitry Andric // Decl::isInStdNamespace will return false for iterators in some STL
254*0fca6ea1SDimitry Andric // implementations due to them being defined in a namespace outside of the std
255*0fca6ea1SDimitry Andric // namespace.
256*0fca6ea1SDimitry Andric static bool isInStlNamespace(const Decl *D) {
257*0fca6ea1SDimitry Andric   const DeclContext *DC = D->getDeclContext();
258*0fca6ea1SDimitry Andric   if (!DC)
259*0fca6ea1SDimitry Andric     return false;
260*0fca6ea1SDimitry Andric   if (const auto *ND = dyn_cast<NamespaceDecl>(DC))
261*0fca6ea1SDimitry Andric     if (const IdentifierInfo *II = ND->getIdentifier()) {
262*0fca6ea1SDimitry Andric       StringRef Name = II->getName();
263*0fca6ea1SDimitry Andric       if (Name.size() >= 2 && Name.front() == '_' &&
264*0fca6ea1SDimitry Andric           (Name[1] == '_' || isUppercase(Name[1])))
265*0fca6ea1SDimitry Andric         return true;
266*0fca6ea1SDimitry Andric     }
267*0fca6ea1SDimitry Andric 
268*0fca6ea1SDimitry Andric   return DC->isStdNamespace();
269*0fca6ea1SDimitry Andric }
270*0fca6ea1SDimitry Andric 
271*0fca6ea1SDimitry Andric static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
272*0fca6ea1SDimitry Andric   if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
273*0fca6ea1SDimitry Andric     if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()))
274*0fca6ea1SDimitry Andric       return true;
275*0fca6ea1SDimitry Andric   if (!isInStlNamespace(Callee->getParent()))
276*0fca6ea1SDimitry Andric     return false;
277*0fca6ea1SDimitry Andric   if (!isRecordWithAttr<PointerAttr>(
278*0fca6ea1SDimitry Andric           Callee->getFunctionObjectParameterType()) &&
279*0fca6ea1SDimitry Andric       !isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType()))
280*0fca6ea1SDimitry Andric     return false;
281*0fca6ea1SDimitry Andric   if (Callee->getReturnType()->isPointerType() ||
282*0fca6ea1SDimitry Andric       isRecordWithAttr<PointerAttr>(Callee->getReturnType())) {
283*0fca6ea1SDimitry Andric     if (!Callee->getIdentifier())
284*0fca6ea1SDimitry Andric       return false;
285*0fca6ea1SDimitry Andric     return llvm::StringSwitch<bool>(Callee->getName())
286*0fca6ea1SDimitry Andric         .Cases("begin", "rbegin", "cbegin", "crbegin", true)
287*0fca6ea1SDimitry Andric         .Cases("end", "rend", "cend", "crend", true)
288*0fca6ea1SDimitry Andric         .Cases("c_str", "data", "get", true)
289*0fca6ea1SDimitry Andric         // Map and set types.
290*0fca6ea1SDimitry Andric         .Cases("find", "equal_range", "lower_bound", "upper_bound", true)
291*0fca6ea1SDimitry Andric         .Default(false);
292*0fca6ea1SDimitry Andric   } else if (Callee->getReturnType()->isReferenceType()) {
293*0fca6ea1SDimitry Andric     if (!Callee->getIdentifier()) {
294*0fca6ea1SDimitry Andric       auto OO = Callee->getOverloadedOperator();
295*0fca6ea1SDimitry Andric       return OO == OverloadedOperatorKind::OO_Subscript ||
296*0fca6ea1SDimitry Andric              OO == OverloadedOperatorKind::OO_Star;
297*0fca6ea1SDimitry Andric     }
298*0fca6ea1SDimitry Andric     return llvm::StringSwitch<bool>(Callee->getName())
299*0fca6ea1SDimitry Andric         .Cases("front", "back", "at", "top", "value", true)
300*0fca6ea1SDimitry Andric         .Default(false);
301*0fca6ea1SDimitry Andric   }
302*0fca6ea1SDimitry Andric   return false;
303*0fca6ea1SDimitry Andric }
304*0fca6ea1SDimitry Andric 
305*0fca6ea1SDimitry Andric static bool shouldTrackFirstArgument(const FunctionDecl *FD) {
306*0fca6ea1SDimitry Andric   if (!FD->getIdentifier() || FD->getNumParams() != 1)
307*0fca6ea1SDimitry Andric     return false;
308*0fca6ea1SDimitry Andric   const auto *RD = FD->getParamDecl(0)->getType()->getPointeeCXXRecordDecl();
309*0fca6ea1SDimitry Andric   if (!FD->isInStdNamespace() || !RD || !RD->isInStdNamespace())
310*0fca6ea1SDimitry Andric     return false;
311*0fca6ea1SDimitry Andric   if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
312*0fca6ea1SDimitry Andric     return false;
313*0fca6ea1SDimitry Andric   if (FD->getReturnType()->isPointerType() ||
314*0fca6ea1SDimitry Andric       isRecordWithAttr<PointerAttr>(FD->getReturnType())) {
315*0fca6ea1SDimitry Andric     return llvm::StringSwitch<bool>(FD->getName())
316*0fca6ea1SDimitry Andric         .Cases("begin", "rbegin", "cbegin", "crbegin", true)
317*0fca6ea1SDimitry Andric         .Cases("end", "rend", "cend", "crend", true)
318*0fca6ea1SDimitry Andric         .Case("data", true)
319*0fca6ea1SDimitry Andric         .Default(false);
320*0fca6ea1SDimitry Andric   } else if (FD->getReturnType()->isReferenceType()) {
321*0fca6ea1SDimitry Andric     return llvm::StringSwitch<bool>(FD->getName())
322*0fca6ea1SDimitry Andric         .Cases("get", "any_cast", true)
323*0fca6ea1SDimitry Andric         .Default(false);
324*0fca6ea1SDimitry Andric   }
325*0fca6ea1SDimitry Andric   return false;
326*0fca6ea1SDimitry Andric }
327*0fca6ea1SDimitry Andric 
328*0fca6ea1SDimitry Andric static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
329*0fca6ea1SDimitry Andric                                     LocalVisitor Visit) {
330*0fca6ea1SDimitry Andric   auto VisitPointerArg = [&](const Decl *D, Expr *Arg, bool Value) {
331*0fca6ea1SDimitry Andric     // We are not interested in the temporary base objects of gsl Pointers:
332*0fca6ea1SDimitry Andric     //   Temp().ptr; // Here ptr might not dangle.
333*0fca6ea1SDimitry Andric     if (isa<MemberExpr>(Arg->IgnoreImpCasts()))
334*0fca6ea1SDimitry Andric       return;
335*0fca6ea1SDimitry Andric     // Once we initialized a value with a reference, it can no longer dangle.
336*0fca6ea1SDimitry Andric     if (!Value) {
337*0fca6ea1SDimitry Andric       for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
338*0fca6ea1SDimitry Andric         if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit)
339*0fca6ea1SDimitry Andric           continue;
340*0fca6ea1SDimitry Andric         if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
341*0fca6ea1SDimitry Andric             PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
342*0fca6ea1SDimitry Andric           return;
343*0fca6ea1SDimitry Andric         break;
344*0fca6ea1SDimitry Andric       }
345*0fca6ea1SDimitry Andric     }
346*0fca6ea1SDimitry Andric     Path.push_back({Value ? IndirectLocalPathEntry::GslPointerInit
347*0fca6ea1SDimitry Andric                           : IndirectLocalPathEntry::GslReferenceInit,
348*0fca6ea1SDimitry Andric                     Arg, D});
349*0fca6ea1SDimitry Andric     if (Arg->isGLValue())
350*0fca6ea1SDimitry Andric       visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
351*0fca6ea1SDimitry Andric                                             Visit,
352*0fca6ea1SDimitry Andric                                             /*EnableLifetimeWarnings=*/true);
353*0fca6ea1SDimitry Andric     else
354*0fca6ea1SDimitry Andric       visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
355*0fca6ea1SDimitry Andric                                        /*EnableLifetimeWarnings=*/true);
356*0fca6ea1SDimitry Andric     Path.pop_back();
357*0fca6ea1SDimitry Andric   };
358*0fca6ea1SDimitry Andric 
359*0fca6ea1SDimitry Andric   if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
360*0fca6ea1SDimitry Andric     const auto *MD = cast_or_null<CXXMethodDecl>(MCE->getDirectCallee());
361*0fca6ea1SDimitry Andric     if (MD && shouldTrackImplicitObjectArg(MD))
362*0fca6ea1SDimitry Andric       VisitPointerArg(MD, MCE->getImplicitObjectArgument(),
363*0fca6ea1SDimitry Andric                       !MD->getReturnType()->isReferenceType());
364*0fca6ea1SDimitry Andric     return;
365*0fca6ea1SDimitry Andric   } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Call)) {
366*0fca6ea1SDimitry Andric     FunctionDecl *Callee = OCE->getDirectCallee();
367*0fca6ea1SDimitry Andric     if (Callee && Callee->isCXXInstanceMember() &&
368*0fca6ea1SDimitry Andric         shouldTrackImplicitObjectArg(cast<CXXMethodDecl>(Callee)))
369*0fca6ea1SDimitry Andric       VisitPointerArg(Callee, OCE->getArg(0),
370*0fca6ea1SDimitry Andric                       !Callee->getReturnType()->isReferenceType());
371*0fca6ea1SDimitry Andric     return;
372*0fca6ea1SDimitry Andric   } else if (auto *CE = dyn_cast<CallExpr>(Call)) {
373*0fca6ea1SDimitry Andric     FunctionDecl *Callee = CE->getDirectCallee();
374*0fca6ea1SDimitry Andric     if (Callee && shouldTrackFirstArgument(Callee))
375*0fca6ea1SDimitry Andric       VisitPointerArg(Callee, CE->getArg(0),
376*0fca6ea1SDimitry Andric                       !Callee->getReturnType()->isReferenceType());
377*0fca6ea1SDimitry Andric     return;
378*0fca6ea1SDimitry Andric   }
379*0fca6ea1SDimitry Andric 
380*0fca6ea1SDimitry Andric   if (auto *CCE = dyn_cast<CXXConstructExpr>(Call)) {
381*0fca6ea1SDimitry Andric     const auto *Ctor = CCE->getConstructor();
382*0fca6ea1SDimitry Andric     const CXXRecordDecl *RD = Ctor->getParent();
383*0fca6ea1SDimitry Andric     if (CCE->getNumArgs() > 0 && RD->hasAttr<PointerAttr>())
384*0fca6ea1SDimitry Andric       VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0], true);
385*0fca6ea1SDimitry Andric   }
386*0fca6ea1SDimitry Andric }
387*0fca6ea1SDimitry Andric 
388*0fca6ea1SDimitry Andric static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
389*0fca6ea1SDimitry Andric   const TypeSourceInfo *TSI = FD->getTypeSourceInfo();
390*0fca6ea1SDimitry Andric   if (!TSI)
391*0fca6ea1SDimitry Andric     return false;
392*0fca6ea1SDimitry Andric   // Don't declare this variable in the second operand of the for-statement;
393*0fca6ea1SDimitry Andric   // GCC miscompiles that by ending its lifetime before evaluating the
394*0fca6ea1SDimitry Andric   // third operand. See gcc.gnu.org/PR86769.
395*0fca6ea1SDimitry Andric   AttributedTypeLoc ATL;
396*0fca6ea1SDimitry Andric   for (TypeLoc TL = TSI->getTypeLoc();
397*0fca6ea1SDimitry Andric        (ATL = TL.getAsAdjusted<AttributedTypeLoc>());
398*0fca6ea1SDimitry Andric        TL = ATL.getModifiedLoc()) {
399*0fca6ea1SDimitry Andric     if (ATL.getAttrAs<LifetimeBoundAttr>())
400*0fca6ea1SDimitry Andric       return true;
401*0fca6ea1SDimitry Andric   }
402*0fca6ea1SDimitry Andric 
403*0fca6ea1SDimitry Andric   // Assume that all assignment operators with a "normal" return type return
404*0fca6ea1SDimitry Andric   // *this, that is, an lvalue reference that is the same type as the implicit
405*0fca6ea1SDimitry Andric   // object parameter (or the LHS for a non-member operator$=).
406*0fca6ea1SDimitry Andric   OverloadedOperatorKind OO = FD->getDeclName().getCXXOverloadedOperator();
407*0fca6ea1SDimitry Andric   if (OO == OO_Equal || isCompoundAssignmentOperator(OO)) {
408*0fca6ea1SDimitry Andric     QualType RetT = FD->getReturnType();
409*0fca6ea1SDimitry Andric     if (RetT->isLValueReferenceType()) {
410*0fca6ea1SDimitry Andric       ASTContext &Ctx = FD->getASTContext();
411*0fca6ea1SDimitry Andric       QualType LHST;
412*0fca6ea1SDimitry Andric       auto *MD = dyn_cast<CXXMethodDecl>(FD);
413*0fca6ea1SDimitry Andric       if (MD && MD->isCXXInstanceMember())
414*0fca6ea1SDimitry Andric         LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType());
415*0fca6ea1SDimitry Andric       else
416*0fca6ea1SDimitry Andric         LHST = MD->getParamDecl(0)->getType();
417*0fca6ea1SDimitry Andric       if (Ctx.hasSameType(RetT, LHST))
418*0fca6ea1SDimitry Andric         return true;
419*0fca6ea1SDimitry Andric     }
420*0fca6ea1SDimitry Andric   }
421*0fca6ea1SDimitry Andric 
422*0fca6ea1SDimitry Andric   return false;
423*0fca6ea1SDimitry Andric }
424*0fca6ea1SDimitry Andric 
425*0fca6ea1SDimitry Andric static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,
426*0fca6ea1SDimitry Andric                                         LocalVisitor Visit) {
427*0fca6ea1SDimitry Andric   const FunctionDecl *Callee;
428*0fca6ea1SDimitry Andric   ArrayRef<Expr *> Args;
429*0fca6ea1SDimitry Andric 
430*0fca6ea1SDimitry Andric   if (auto *CE = dyn_cast<CallExpr>(Call)) {
431*0fca6ea1SDimitry Andric     Callee = CE->getDirectCallee();
432*0fca6ea1SDimitry Andric     Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
433*0fca6ea1SDimitry Andric   } else {
434*0fca6ea1SDimitry Andric     auto *CCE = cast<CXXConstructExpr>(Call);
435*0fca6ea1SDimitry Andric     Callee = CCE->getConstructor();
436*0fca6ea1SDimitry Andric     Args = llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs());
437*0fca6ea1SDimitry Andric   }
438*0fca6ea1SDimitry Andric   if (!Callee)
439*0fca6ea1SDimitry Andric     return;
440*0fca6ea1SDimitry Andric 
441*0fca6ea1SDimitry Andric   Expr *ObjectArg = nullptr;
442*0fca6ea1SDimitry Andric   if (isa<CXXOperatorCallExpr>(Call) && Callee->isCXXInstanceMember()) {
443*0fca6ea1SDimitry Andric     ObjectArg = Args[0];
444*0fca6ea1SDimitry Andric     Args = Args.slice(1);
445*0fca6ea1SDimitry Andric   } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
446*0fca6ea1SDimitry Andric     ObjectArg = MCE->getImplicitObjectArgument();
447*0fca6ea1SDimitry Andric   }
448*0fca6ea1SDimitry Andric 
449*0fca6ea1SDimitry Andric   auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) {
450*0fca6ea1SDimitry Andric     Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
451*0fca6ea1SDimitry Andric     if (Arg->isGLValue())
452*0fca6ea1SDimitry Andric       visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
453*0fca6ea1SDimitry Andric                                             Visit,
454*0fca6ea1SDimitry Andric                                             /*EnableLifetimeWarnings=*/false);
455*0fca6ea1SDimitry Andric     else
456*0fca6ea1SDimitry Andric       visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
457*0fca6ea1SDimitry Andric                                        /*EnableLifetimeWarnings=*/false);
458*0fca6ea1SDimitry Andric     Path.pop_back();
459*0fca6ea1SDimitry Andric   };
460*0fca6ea1SDimitry Andric 
461*0fca6ea1SDimitry Andric   bool CheckCoroCall = false;
462*0fca6ea1SDimitry Andric   if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
463*0fca6ea1SDimitry Andric     CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
464*0fca6ea1SDimitry Andric                     RD->hasAttr<CoroReturnTypeAttr>() &&
465*0fca6ea1SDimitry Andric                     !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
466*0fca6ea1SDimitry Andric   }
467*0fca6ea1SDimitry Andric 
468*0fca6ea1SDimitry Andric   if (ObjectArg) {
469*0fca6ea1SDimitry Andric     bool CheckCoroObjArg = CheckCoroCall;
470*0fca6ea1SDimitry Andric     // Coroutine lambda objects with empty capture list are not lifetimebound.
471*0fca6ea1SDimitry Andric     if (auto *LE = dyn_cast<LambdaExpr>(ObjectArg->IgnoreImplicit());
472*0fca6ea1SDimitry Andric         LE && LE->captures().empty())
473*0fca6ea1SDimitry Andric       CheckCoroObjArg = false;
474*0fca6ea1SDimitry Andric     // Allow `get_return_object()` as the object param (__promise) is not
475*0fca6ea1SDimitry Andric     // lifetimebound.
476*0fca6ea1SDimitry Andric     if (Sema::CanBeGetReturnObject(Callee))
477*0fca6ea1SDimitry Andric       CheckCoroObjArg = false;
478*0fca6ea1SDimitry Andric     if (implicitObjectParamIsLifetimeBound(Callee) || CheckCoroObjArg)
479*0fca6ea1SDimitry Andric       VisitLifetimeBoundArg(Callee, ObjectArg);
480*0fca6ea1SDimitry Andric   }
481*0fca6ea1SDimitry Andric 
482*0fca6ea1SDimitry Andric   for (unsigned I = 0,
483*0fca6ea1SDimitry Andric                 N = std::min<unsigned>(Callee->getNumParams(), Args.size());
484*0fca6ea1SDimitry Andric        I != N; ++I) {
485*0fca6ea1SDimitry Andric     if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
486*0fca6ea1SDimitry Andric       VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
487*0fca6ea1SDimitry Andric   }
488*0fca6ea1SDimitry Andric }
489*0fca6ea1SDimitry Andric 
490*0fca6ea1SDimitry Andric /// Visit the locals that would be reachable through a reference bound to the
491*0fca6ea1SDimitry Andric /// glvalue expression \c Init.
492*0fca6ea1SDimitry Andric static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
493*0fca6ea1SDimitry Andric                                                   Expr *Init, ReferenceKind RK,
494*0fca6ea1SDimitry Andric                                                   LocalVisitor Visit,
495*0fca6ea1SDimitry Andric                                                   bool EnableLifetimeWarnings) {
496*0fca6ea1SDimitry Andric   RevertToOldSizeRAII RAII(Path);
497*0fca6ea1SDimitry Andric 
498*0fca6ea1SDimitry Andric   // Walk past any constructs which we can lifetime-extend across.
499*0fca6ea1SDimitry Andric   Expr *Old;
500*0fca6ea1SDimitry Andric   do {
501*0fca6ea1SDimitry Andric     Old = Init;
502*0fca6ea1SDimitry Andric 
503*0fca6ea1SDimitry Andric     if (auto *FE = dyn_cast<FullExpr>(Init))
504*0fca6ea1SDimitry Andric       Init = FE->getSubExpr();
505*0fca6ea1SDimitry Andric 
506*0fca6ea1SDimitry Andric     if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
507*0fca6ea1SDimitry Andric       // If this is just redundant braces around an initializer, step over it.
508*0fca6ea1SDimitry Andric       if (ILE->isTransparent())
509*0fca6ea1SDimitry Andric         Init = ILE->getInit(0);
510*0fca6ea1SDimitry Andric     }
511*0fca6ea1SDimitry Andric 
512*0fca6ea1SDimitry Andric     // Step over any subobject adjustments; we may have a materialized
513*0fca6ea1SDimitry Andric     // temporary inside them.
514*0fca6ea1SDimitry Andric     Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
515*0fca6ea1SDimitry Andric 
516*0fca6ea1SDimitry Andric     // Per current approach for DR1376, look through casts to reference type
517*0fca6ea1SDimitry Andric     // when performing lifetime extension.
518*0fca6ea1SDimitry Andric     if (CastExpr *CE = dyn_cast<CastExpr>(Init))
519*0fca6ea1SDimitry Andric       if (CE->getSubExpr()->isGLValue())
520*0fca6ea1SDimitry Andric         Init = CE->getSubExpr();
521*0fca6ea1SDimitry Andric 
522*0fca6ea1SDimitry Andric     // Per the current approach for DR1299, look through array element access
523*0fca6ea1SDimitry Andric     // on array glvalues when performing lifetime extension.
524*0fca6ea1SDimitry Andric     if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init)) {
525*0fca6ea1SDimitry Andric       Init = ASE->getBase();
526*0fca6ea1SDimitry Andric       auto *ICE = dyn_cast<ImplicitCastExpr>(Init);
527*0fca6ea1SDimitry Andric       if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
528*0fca6ea1SDimitry Andric         Init = ICE->getSubExpr();
529*0fca6ea1SDimitry Andric       else
530*0fca6ea1SDimitry Andric         // We can't lifetime extend through this but we might still find some
531*0fca6ea1SDimitry Andric         // retained temporaries.
532*0fca6ea1SDimitry Andric         return visitLocalsRetainedByInitializer(Path, Init, Visit, true,
533*0fca6ea1SDimitry Andric                                                 EnableLifetimeWarnings);
534*0fca6ea1SDimitry Andric     }
535*0fca6ea1SDimitry Andric 
536*0fca6ea1SDimitry Andric     // Step into CXXDefaultInitExprs so we can diagnose cases where a
537*0fca6ea1SDimitry Andric     // constructor inherits one as an implicit mem-initializer.
538*0fca6ea1SDimitry Andric     if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
539*0fca6ea1SDimitry Andric       Path.push_back(
540*0fca6ea1SDimitry Andric           {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
541*0fca6ea1SDimitry Andric       Init = DIE->getExpr();
542*0fca6ea1SDimitry Andric     }
543*0fca6ea1SDimitry Andric   } while (Init != Old);
544*0fca6ea1SDimitry Andric 
545*0fca6ea1SDimitry Andric   if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
546*0fca6ea1SDimitry Andric     if (Visit(Path, Local(MTE), RK))
547*0fca6ea1SDimitry Andric       visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit, true,
548*0fca6ea1SDimitry Andric                                        EnableLifetimeWarnings);
549*0fca6ea1SDimitry Andric   }
550*0fca6ea1SDimitry Andric 
551*0fca6ea1SDimitry Andric   if (isa<CallExpr>(Init)) {
552*0fca6ea1SDimitry Andric     if (EnableLifetimeWarnings)
553*0fca6ea1SDimitry Andric       handleGslAnnotatedTypes(Path, Init, Visit);
554*0fca6ea1SDimitry Andric     return visitLifetimeBoundArguments(Path, Init, Visit);
555*0fca6ea1SDimitry Andric   }
556*0fca6ea1SDimitry Andric 
557*0fca6ea1SDimitry Andric   switch (Init->getStmtClass()) {
558*0fca6ea1SDimitry Andric   case Stmt::DeclRefExprClass: {
559*0fca6ea1SDimitry Andric     // If we find the name of a local non-reference parameter, we could have a
560*0fca6ea1SDimitry Andric     // lifetime problem.
561*0fca6ea1SDimitry Andric     auto *DRE = cast<DeclRefExpr>(Init);
562*0fca6ea1SDimitry Andric     auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
563*0fca6ea1SDimitry Andric     if (VD && VD->hasLocalStorage() &&
564*0fca6ea1SDimitry Andric         !DRE->refersToEnclosingVariableOrCapture()) {
565*0fca6ea1SDimitry Andric       if (!VD->getType()->isReferenceType()) {
566*0fca6ea1SDimitry Andric         Visit(Path, Local(DRE), RK);
567*0fca6ea1SDimitry Andric       } else if (isa<ParmVarDecl>(DRE->getDecl())) {
568*0fca6ea1SDimitry Andric         // The lifetime of a reference parameter is unknown; assume it's OK
569*0fca6ea1SDimitry Andric         // for now.
570*0fca6ea1SDimitry Andric         break;
571*0fca6ea1SDimitry Andric       } else if (VD->getInit() && !isVarOnPath(Path, VD)) {
572*0fca6ea1SDimitry Andric         Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
573*0fca6ea1SDimitry Andric         visitLocalsRetainedByReferenceBinding(Path, VD->getInit(),
574*0fca6ea1SDimitry Andric                                               RK_ReferenceBinding, Visit,
575*0fca6ea1SDimitry Andric                                               EnableLifetimeWarnings);
576*0fca6ea1SDimitry Andric       }
577*0fca6ea1SDimitry Andric     }
578*0fca6ea1SDimitry Andric     break;
579*0fca6ea1SDimitry Andric   }
580*0fca6ea1SDimitry Andric 
581*0fca6ea1SDimitry Andric   case Stmt::UnaryOperatorClass: {
582*0fca6ea1SDimitry Andric     // The only unary operator that make sense to handle here
583*0fca6ea1SDimitry Andric     // is Deref.  All others don't resolve to a "name."  This includes
584*0fca6ea1SDimitry Andric     // handling all sorts of rvalues passed to a unary operator.
585*0fca6ea1SDimitry Andric     const UnaryOperator *U = cast<UnaryOperator>(Init);
586*0fca6ea1SDimitry Andric     if (U->getOpcode() == UO_Deref)
587*0fca6ea1SDimitry Andric       visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true,
588*0fca6ea1SDimitry Andric                                        EnableLifetimeWarnings);
589*0fca6ea1SDimitry Andric     break;
590*0fca6ea1SDimitry Andric   }
591*0fca6ea1SDimitry Andric 
592*0fca6ea1SDimitry Andric   case Stmt::ArraySectionExprClass: {
593*0fca6ea1SDimitry Andric     visitLocalsRetainedByInitializer(Path,
594*0fca6ea1SDimitry Andric                                      cast<ArraySectionExpr>(Init)->getBase(),
595*0fca6ea1SDimitry Andric                                      Visit, true, EnableLifetimeWarnings);
596*0fca6ea1SDimitry Andric     break;
597*0fca6ea1SDimitry Andric   }
598*0fca6ea1SDimitry Andric 
599*0fca6ea1SDimitry Andric   case Stmt::ConditionalOperatorClass:
600*0fca6ea1SDimitry Andric   case Stmt::BinaryConditionalOperatorClass: {
601*0fca6ea1SDimitry Andric     auto *C = cast<AbstractConditionalOperator>(Init);
602*0fca6ea1SDimitry Andric     if (!C->getTrueExpr()->getType()->isVoidType())
603*0fca6ea1SDimitry Andric       visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit,
604*0fca6ea1SDimitry Andric                                             EnableLifetimeWarnings);
605*0fca6ea1SDimitry Andric     if (!C->getFalseExpr()->getType()->isVoidType())
606*0fca6ea1SDimitry Andric       visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit,
607*0fca6ea1SDimitry Andric                                             EnableLifetimeWarnings);
608*0fca6ea1SDimitry Andric     break;
609*0fca6ea1SDimitry Andric   }
610*0fca6ea1SDimitry Andric 
611*0fca6ea1SDimitry Andric   case Stmt::CompoundLiteralExprClass: {
612*0fca6ea1SDimitry Andric     if (auto *CLE = dyn_cast<CompoundLiteralExpr>(Init)) {
613*0fca6ea1SDimitry Andric       if (!CLE->isFileScope())
614*0fca6ea1SDimitry Andric         Visit(Path, Local(CLE), RK);
615*0fca6ea1SDimitry Andric     }
616*0fca6ea1SDimitry Andric     break;
617*0fca6ea1SDimitry Andric   }
618*0fca6ea1SDimitry Andric 
619*0fca6ea1SDimitry Andric     // FIXME: Visit the left-hand side of an -> or ->*.
620*0fca6ea1SDimitry Andric 
621*0fca6ea1SDimitry Andric   default:
622*0fca6ea1SDimitry Andric     break;
623*0fca6ea1SDimitry Andric   }
624*0fca6ea1SDimitry Andric }
625*0fca6ea1SDimitry Andric 
626*0fca6ea1SDimitry Andric /// Visit the locals that would be reachable through an object initialized by
627*0fca6ea1SDimitry Andric /// the prvalue expression \c Init.
628*0fca6ea1SDimitry Andric static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
629*0fca6ea1SDimitry Andric                                              Expr *Init, LocalVisitor Visit,
630*0fca6ea1SDimitry Andric                                              bool RevisitSubinits,
631*0fca6ea1SDimitry Andric                                              bool EnableLifetimeWarnings) {
632*0fca6ea1SDimitry Andric   RevertToOldSizeRAII RAII(Path);
633*0fca6ea1SDimitry Andric 
634*0fca6ea1SDimitry Andric   Expr *Old;
635*0fca6ea1SDimitry Andric   do {
636*0fca6ea1SDimitry Andric     Old = Init;
637*0fca6ea1SDimitry Andric 
638*0fca6ea1SDimitry Andric     // Step into CXXDefaultInitExprs so we can diagnose cases where a
639*0fca6ea1SDimitry Andric     // constructor inherits one as an implicit mem-initializer.
640*0fca6ea1SDimitry Andric     if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
641*0fca6ea1SDimitry Andric       Path.push_back(
642*0fca6ea1SDimitry Andric           {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
643*0fca6ea1SDimitry Andric       Init = DIE->getExpr();
644*0fca6ea1SDimitry Andric     }
645*0fca6ea1SDimitry Andric 
646*0fca6ea1SDimitry Andric     if (auto *FE = dyn_cast<FullExpr>(Init))
647*0fca6ea1SDimitry Andric       Init = FE->getSubExpr();
648*0fca6ea1SDimitry Andric 
649*0fca6ea1SDimitry Andric     // Dig out the expression which constructs the extended temporary.
650*0fca6ea1SDimitry Andric     Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
651*0fca6ea1SDimitry Andric 
652*0fca6ea1SDimitry Andric     if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
653*0fca6ea1SDimitry Andric       Init = BTE->getSubExpr();
654*0fca6ea1SDimitry Andric 
655*0fca6ea1SDimitry Andric     Init = Init->IgnoreParens();
656*0fca6ea1SDimitry Andric 
657*0fca6ea1SDimitry Andric     // Step over value-preserving rvalue casts.
658*0fca6ea1SDimitry Andric     if (auto *CE = dyn_cast<CastExpr>(Init)) {
659*0fca6ea1SDimitry Andric       switch (CE->getCastKind()) {
660*0fca6ea1SDimitry Andric       case CK_LValueToRValue:
661*0fca6ea1SDimitry Andric         // If we can match the lvalue to a const object, we can look at its
662*0fca6ea1SDimitry Andric         // initializer.
663*0fca6ea1SDimitry Andric         Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
664*0fca6ea1SDimitry Andric         return visitLocalsRetainedByReferenceBinding(
665*0fca6ea1SDimitry Andric             Path, Init, RK_ReferenceBinding,
666*0fca6ea1SDimitry Andric             [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
667*0fca6ea1SDimitry Andric               if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
668*0fca6ea1SDimitry Andric                 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
669*0fca6ea1SDimitry Andric                 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
670*0fca6ea1SDimitry Andric                     !isVarOnPath(Path, VD)) {
671*0fca6ea1SDimitry Andric                   Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
672*0fca6ea1SDimitry Andric                   visitLocalsRetainedByInitializer(
673*0fca6ea1SDimitry Andric                       Path, VD->getInit(), Visit, true, EnableLifetimeWarnings);
674*0fca6ea1SDimitry Andric                 }
675*0fca6ea1SDimitry Andric               } else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
676*0fca6ea1SDimitry Andric                 if (MTE->getType().isConstQualified())
677*0fca6ea1SDimitry Andric                   visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(),
678*0fca6ea1SDimitry Andric                                                    Visit, true,
679*0fca6ea1SDimitry Andric                                                    EnableLifetimeWarnings);
680*0fca6ea1SDimitry Andric               }
681*0fca6ea1SDimitry Andric               return false;
682*0fca6ea1SDimitry Andric             },
683*0fca6ea1SDimitry Andric             EnableLifetimeWarnings);
684*0fca6ea1SDimitry Andric 
685*0fca6ea1SDimitry Andric         // We assume that objects can be retained by pointers cast to integers,
686*0fca6ea1SDimitry Andric         // but not if the integer is cast to floating-point type or to _Complex.
687*0fca6ea1SDimitry Andric         // We assume that casts to 'bool' do not preserve enough information to
688*0fca6ea1SDimitry Andric         // retain a local object.
689*0fca6ea1SDimitry Andric       case CK_NoOp:
690*0fca6ea1SDimitry Andric       case CK_BitCast:
691*0fca6ea1SDimitry Andric       case CK_BaseToDerived:
692*0fca6ea1SDimitry Andric       case CK_DerivedToBase:
693*0fca6ea1SDimitry Andric       case CK_UncheckedDerivedToBase:
694*0fca6ea1SDimitry Andric       case CK_Dynamic:
695*0fca6ea1SDimitry Andric       case CK_ToUnion:
696*0fca6ea1SDimitry Andric       case CK_UserDefinedConversion:
697*0fca6ea1SDimitry Andric       case CK_ConstructorConversion:
698*0fca6ea1SDimitry Andric       case CK_IntegralToPointer:
699*0fca6ea1SDimitry Andric       case CK_PointerToIntegral:
700*0fca6ea1SDimitry Andric       case CK_VectorSplat:
701*0fca6ea1SDimitry Andric       case CK_IntegralCast:
702*0fca6ea1SDimitry Andric       case CK_CPointerToObjCPointerCast:
703*0fca6ea1SDimitry Andric       case CK_BlockPointerToObjCPointerCast:
704*0fca6ea1SDimitry Andric       case CK_AnyPointerToBlockPointerCast:
705*0fca6ea1SDimitry Andric       case CK_AddressSpaceConversion:
706*0fca6ea1SDimitry Andric         break;
707*0fca6ea1SDimitry Andric 
708*0fca6ea1SDimitry Andric       case CK_ArrayToPointerDecay:
709*0fca6ea1SDimitry Andric         // Model array-to-pointer decay as taking the address of the array
710*0fca6ea1SDimitry Andric         // lvalue.
711*0fca6ea1SDimitry Andric         Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
712*0fca6ea1SDimitry Andric         return visitLocalsRetainedByReferenceBinding(Path, CE->getSubExpr(),
713*0fca6ea1SDimitry Andric                                                      RK_ReferenceBinding, Visit,
714*0fca6ea1SDimitry Andric                                                      EnableLifetimeWarnings);
715*0fca6ea1SDimitry Andric 
716*0fca6ea1SDimitry Andric       default:
717*0fca6ea1SDimitry Andric         return;
718*0fca6ea1SDimitry Andric       }
719*0fca6ea1SDimitry Andric 
720*0fca6ea1SDimitry Andric       Init = CE->getSubExpr();
721*0fca6ea1SDimitry Andric     }
722*0fca6ea1SDimitry Andric   } while (Old != Init);
723*0fca6ea1SDimitry Andric 
724*0fca6ea1SDimitry Andric   // C++17 [dcl.init.list]p6:
725*0fca6ea1SDimitry Andric   //   initializing an initializer_list object from the array extends the
726*0fca6ea1SDimitry Andric   //   lifetime of the array exactly like binding a reference to a temporary.
727*0fca6ea1SDimitry Andric   if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init))
728*0fca6ea1SDimitry Andric     return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(),
729*0fca6ea1SDimitry Andric                                                  RK_StdInitializerList, Visit,
730*0fca6ea1SDimitry Andric                                                  EnableLifetimeWarnings);
731*0fca6ea1SDimitry Andric 
732*0fca6ea1SDimitry Andric   if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
733*0fca6ea1SDimitry Andric     // We already visited the elements of this initializer list while
734*0fca6ea1SDimitry Andric     // performing the initialization. Don't visit them again unless we've
735*0fca6ea1SDimitry Andric     // changed the lifetime of the initialized entity.
736*0fca6ea1SDimitry Andric     if (!RevisitSubinits)
737*0fca6ea1SDimitry Andric       return;
738*0fca6ea1SDimitry Andric 
739*0fca6ea1SDimitry Andric     if (ILE->isTransparent())
740*0fca6ea1SDimitry Andric       return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit,
741*0fca6ea1SDimitry Andric                                               RevisitSubinits,
742*0fca6ea1SDimitry Andric                                               EnableLifetimeWarnings);
743*0fca6ea1SDimitry Andric 
744*0fca6ea1SDimitry Andric     if (ILE->getType()->isArrayType()) {
745*0fca6ea1SDimitry Andric       for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
746*0fca6ea1SDimitry Andric         visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit,
747*0fca6ea1SDimitry Andric                                          RevisitSubinits,
748*0fca6ea1SDimitry Andric                                          EnableLifetimeWarnings);
749*0fca6ea1SDimitry Andric       return;
750*0fca6ea1SDimitry Andric     }
751*0fca6ea1SDimitry Andric 
752*0fca6ea1SDimitry Andric     if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
753*0fca6ea1SDimitry Andric       assert(RD->isAggregate() && "aggregate init on non-aggregate");
754*0fca6ea1SDimitry Andric 
755*0fca6ea1SDimitry Andric       // If we lifetime-extend a braced initializer which is initializing an
756*0fca6ea1SDimitry Andric       // aggregate, and that aggregate contains reference members which are
757*0fca6ea1SDimitry Andric       // bound to temporaries, those temporaries are also lifetime-extended.
758*0fca6ea1SDimitry Andric       if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
759*0fca6ea1SDimitry Andric           ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
760*0fca6ea1SDimitry Andric         visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0),
761*0fca6ea1SDimitry Andric                                               RK_ReferenceBinding, Visit,
762*0fca6ea1SDimitry Andric                                               EnableLifetimeWarnings);
763*0fca6ea1SDimitry Andric       else {
764*0fca6ea1SDimitry Andric         unsigned Index = 0;
765*0fca6ea1SDimitry Andric         for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
766*0fca6ea1SDimitry Andric           visitLocalsRetainedByInitializer(Path, ILE->getInit(Index), Visit,
767*0fca6ea1SDimitry Andric                                            RevisitSubinits,
768*0fca6ea1SDimitry Andric                                            EnableLifetimeWarnings);
769*0fca6ea1SDimitry Andric         for (const auto *I : RD->fields()) {
770*0fca6ea1SDimitry Andric           if (Index >= ILE->getNumInits())
771*0fca6ea1SDimitry Andric             break;
772*0fca6ea1SDimitry Andric           if (I->isUnnamedBitField())
773*0fca6ea1SDimitry Andric             continue;
774*0fca6ea1SDimitry Andric           Expr *SubInit = ILE->getInit(Index);
775*0fca6ea1SDimitry Andric           if (I->getType()->isReferenceType())
776*0fca6ea1SDimitry Andric             visitLocalsRetainedByReferenceBinding(Path, SubInit,
777*0fca6ea1SDimitry Andric                                                   RK_ReferenceBinding, Visit,
778*0fca6ea1SDimitry Andric                                                   EnableLifetimeWarnings);
779*0fca6ea1SDimitry Andric           else
780*0fca6ea1SDimitry Andric             // This might be either aggregate-initialization of a member or
781*0fca6ea1SDimitry Andric             // initialization of a std::initializer_list object. Regardless,
782*0fca6ea1SDimitry Andric             // we should recursively lifetime-extend that initializer.
783*0fca6ea1SDimitry Andric             visitLocalsRetainedByInitializer(
784*0fca6ea1SDimitry Andric                 Path, SubInit, Visit, RevisitSubinits, EnableLifetimeWarnings);
785*0fca6ea1SDimitry Andric           ++Index;
786*0fca6ea1SDimitry Andric         }
787*0fca6ea1SDimitry Andric       }
788*0fca6ea1SDimitry Andric     }
789*0fca6ea1SDimitry Andric     return;
790*0fca6ea1SDimitry Andric   }
791*0fca6ea1SDimitry Andric 
792*0fca6ea1SDimitry Andric   // The lifetime of an init-capture is that of the closure object constructed
793*0fca6ea1SDimitry Andric   // by a lambda-expression.
794*0fca6ea1SDimitry Andric   if (auto *LE = dyn_cast<LambdaExpr>(Init)) {
795*0fca6ea1SDimitry Andric     LambdaExpr::capture_iterator CapI = LE->capture_begin();
796*0fca6ea1SDimitry Andric     for (Expr *E : LE->capture_inits()) {
797*0fca6ea1SDimitry Andric       assert(CapI != LE->capture_end());
798*0fca6ea1SDimitry Andric       const LambdaCapture &Cap = *CapI++;
799*0fca6ea1SDimitry Andric       if (!E)
800*0fca6ea1SDimitry Andric         continue;
801*0fca6ea1SDimitry Andric       if (Cap.capturesVariable())
802*0fca6ea1SDimitry Andric         Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
803*0fca6ea1SDimitry Andric       if (E->isGLValue())
804*0fca6ea1SDimitry Andric         visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding,
805*0fca6ea1SDimitry Andric                                               Visit, EnableLifetimeWarnings);
806*0fca6ea1SDimitry Andric       else
807*0fca6ea1SDimitry Andric         visitLocalsRetainedByInitializer(Path, E, Visit, true,
808*0fca6ea1SDimitry Andric                                          EnableLifetimeWarnings);
809*0fca6ea1SDimitry Andric       if (Cap.capturesVariable())
810*0fca6ea1SDimitry Andric         Path.pop_back();
811*0fca6ea1SDimitry Andric     }
812*0fca6ea1SDimitry Andric   }
813*0fca6ea1SDimitry Andric 
814*0fca6ea1SDimitry Andric   // Assume that a copy or move from a temporary references the same objects
815*0fca6ea1SDimitry Andric   // that the temporary does.
816*0fca6ea1SDimitry Andric   if (auto *CCE = dyn_cast<CXXConstructExpr>(Init)) {
817*0fca6ea1SDimitry Andric     if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
818*0fca6ea1SDimitry Andric       if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
819*0fca6ea1SDimitry Andric         // assert(false && "hit temporary copy path");
820*0fca6ea1SDimitry Andric         Expr *Arg = MTE->getSubExpr();
821*0fca6ea1SDimitry Andric         Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
822*0fca6ea1SDimitry Andric                         CCE->getConstructor()});
823*0fca6ea1SDimitry Andric         visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
824*0fca6ea1SDimitry Andric                                          /*EnableLifetimeWarnings*/ false);
825*0fca6ea1SDimitry Andric         Path.pop_back();
826*0fca6ea1SDimitry Andric       }
827*0fca6ea1SDimitry Andric     }
828*0fca6ea1SDimitry Andric   }
829*0fca6ea1SDimitry Andric 
830*0fca6ea1SDimitry Andric   if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init)) {
831*0fca6ea1SDimitry Andric     if (EnableLifetimeWarnings)
832*0fca6ea1SDimitry Andric       handleGslAnnotatedTypes(Path, Init, Visit);
833*0fca6ea1SDimitry Andric     return visitLifetimeBoundArguments(Path, Init, Visit);
834*0fca6ea1SDimitry Andric   }
835*0fca6ea1SDimitry Andric 
836*0fca6ea1SDimitry Andric   switch (Init->getStmtClass()) {
837*0fca6ea1SDimitry Andric   case Stmt::UnaryOperatorClass: {
838*0fca6ea1SDimitry Andric     auto *UO = cast<UnaryOperator>(Init);
839*0fca6ea1SDimitry Andric     // If the initializer is the address of a local, we could have a lifetime
840*0fca6ea1SDimitry Andric     // problem.
841*0fca6ea1SDimitry Andric     if (UO->getOpcode() == UO_AddrOf) {
842*0fca6ea1SDimitry Andric       // If this is &rvalue, then it's ill-formed and we have already diagnosed
843*0fca6ea1SDimitry Andric       // it. Don't produce a redundant warning about the lifetime of the
844*0fca6ea1SDimitry Andric       // temporary.
845*0fca6ea1SDimitry Andric       if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
846*0fca6ea1SDimitry Andric         return;
847*0fca6ea1SDimitry Andric 
848*0fca6ea1SDimitry Andric       Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
849*0fca6ea1SDimitry Andric       visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(),
850*0fca6ea1SDimitry Andric                                             RK_ReferenceBinding, Visit,
851*0fca6ea1SDimitry Andric                                             EnableLifetimeWarnings);
852*0fca6ea1SDimitry Andric     }
853*0fca6ea1SDimitry Andric     break;
854*0fca6ea1SDimitry Andric   }
855*0fca6ea1SDimitry Andric 
856*0fca6ea1SDimitry Andric   case Stmt::BinaryOperatorClass: {
857*0fca6ea1SDimitry Andric     // Handle pointer arithmetic.
858*0fca6ea1SDimitry Andric     auto *BO = cast<BinaryOperator>(Init);
859*0fca6ea1SDimitry Andric     BinaryOperatorKind BOK = BO->getOpcode();
860*0fca6ea1SDimitry Andric     if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
861*0fca6ea1SDimitry Andric       break;
862*0fca6ea1SDimitry Andric 
863*0fca6ea1SDimitry Andric     if (BO->getLHS()->getType()->isPointerType())
864*0fca6ea1SDimitry Andric       visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true,
865*0fca6ea1SDimitry Andric                                        EnableLifetimeWarnings);
866*0fca6ea1SDimitry Andric     else if (BO->getRHS()->getType()->isPointerType())
867*0fca6ea1SDimitry Andric       visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true,
868*0fca6ea1SDimitry Andric                                        EnableLifetimeWarnings);
869*0fca6ea1SDimitry Andric     break;
870*0fca6ea1SDimitry Andric   }
871*0fca6ea1SDimitry Andric 
872*0fca6ea1SDimitry Andric   case Stmt::ConditionalOperatorClass:
873*0fca6ea1SDimitry Andric   case Stmt::BinaryConditionalOperatorClass: {
874*0fca6ea1SDimitry Andric     auto *C = cast<AbstractConditionalOperator>(Init);
875*0fca6ea1SDimitry Andric     // In C++, we can have a throw-expression operand, which has 'void' type
876*0fca6ea1SDimitry Andric     // and isn't interesting from a lifetime perspective.
877*0fca6ea1SDimitry Andric     if (!C->getTrueExpr()->getType()->isVoidType())
878*0fca6ea1SDimitry Andric       visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true,
879*0fca6ea1SDimitry Andric                                        EnableLifetimeWarnings);
880*0fca6ea1SDimitry Andric     if (!C->getFalseExpr()->getType()->isVoidType())
881*0fca6ea1SDimitry Andric       visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true,
882*0fca6ea1SDimitry Andric                                        EnableLifetimeWarnings);
883*0fca6ea1SDimitry Andric     break;
884*0fca6ea1SDimitry Andric   }
885*0fca6ea1SDimitry Andric 
886*0fca6ea1SDimitry Andric   case Stmt::BlockExprClass:
887*0fca6ea1SDimitry Andric     if (cast<BlockExpr>(Init)->getBlockDecl()->hasCaptures()) {
888*0fca6ea1SDimitry Andric       // This is a local block, whose lifetime is that of the function.
889*0fca6ea1SDimitry Andric       Visit(Path, Local(cast<BlockExpr>(Init)), RK_ReferenceBinding);
890*0fca6ea1SDimitry Andric     }
891*0fca6ea1SDimitry Andric     break;
892*0fca6ea1SDimitry Andric 
893*0fca6ea1SDimitry Andric   case Stmt::AddrLabelExprClass:
894*0fca6ea1SDimitry Andric     // We want to warn if the address of a label would escape the function.
895*0fca6ea1SDimitry Andric     Visit(Path, Local(cast<AddrLabelExpr>(Init)), RK_ReferenceBinding);
896*0fca6ea1SDimitry Andric     break;
897*0fca6ea1SDimitry Andric 
898*0fca6ea1SDimitry Andric   default:
899*0fca6ea1SDimitry Andric     break;
900*0fca6ea1SDimitry Andric   }
901*0fca6ea1SDimitry Andric }
902*0fca6ea1SDimitry Andric 
903*0fca6ea1SDimitry Andric /// Whether a path to an object supports lifetime extension.
904*0fca6ea1SDimitry Andric enum PathLifetimeKind {
905*0fca6ea1SDimitry Andric   /// Lifetime-extend along this path.
906*0fca6ea1SDimitry Andric   Extend,
907*0fca6ea1SDimitry Andric   /// We should lifetime-extend, but we don't because (due to technical
908*0fca6ea1SDimitry Andric   /// limitations) we can't. This happens for default member initializers,
909*0fca6ea1SDimitry Andric   /// which we don't clone for every use, so we don't have a unique
910*0fca6ea1SDimitry Andric   /// MaterializeTemporaryExpr to update.
911*0fca6ea1SDimitry Andric   ShouldExtend,
912*0fca6ea1SDimitry Andric   /// Do not lifetime extend along this path.
913*0fca6ea1SDimitry Andric   NoExtend
914*0fca6ea1SDimitry Andric };
915*0fca6ea1SDimitry Andric 
916*0fca6ea1SDimitry Andric /// Determine whether this is an indirect path to a temporary that we are
917*0fca6ea1SDimitry Andric /// supposed to lifetime-extend along.
918*0fca6ea1SDimitry Andric static PathLifetimeKind
919*0fca6ea1SDimitry Andric shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
920*0fca6ea1SDimitry Andric   PathLifetimeKind Kind = PathLifetimeKind::Extend;
921*0fca6ea1SDimitry Andric   for (auto Elem : Path) {
922*0fca6ea1SDimitry Andric     if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)
923*0fca6ea1SDimitry Andric       Kind = PathLifetimeKind::ShouldExtend;
924*0fca6ea1SDimitry Andric     else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
925*0fca6ea1SDimitry Andric       return PathLifetimeKind::NoExtend;
926*0fca6ea1SDimitry Andric   }
927*0fca6ea1SDimitry Andric   return Kind;
928*0fca6ea1SDimitry Andric }
929*0fca6ea1SDimitry Andric 
930*0fca6ea1SDimitry Andric /// Find the range for the first interesting entry in the path at or after I.
931*0fca6ea1SDimitry Andric static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
932*0fca6ea1SDimitry Andric                                       Expr *E) {
933*0fca6ea1SDimitry Andric   for (unsigned N = Path.size(); I != N; ++I) {
934*0fca6ea1SDimitry Andric     switch (Path[I].Kind) {
935*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::AddressOf:
936*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::LValToRVal:
937*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::LifetimeBoundCall:
938*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::TemporaryCopy:
939*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::GslReferenceInit:
940*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::GslPointerInit:
941*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::GslPointerAssignment:
942*0fca6ea1SDimitry Andric       // These exist primarily to mark the path as not permitting or
943*0fca6ea1SDimitry Andric       // supporting lifetime extension.
944*0fca6ea1SDimitry Andric       break;
945*0fca6ea1SDimitry Andric 
946*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::VarInit:
947*0fca6ea1SDimitry Andric       if (cast<VarDecl>(Path[I].D)->isImplicit())
948*0fca6ea1SDimitry Andric         return SourceRange();
949*0fca6ea1SDimitry Andric       [[fallthrough]];
950*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::DefaultInit:
951*0fca6ea1SDimitry Andric       return Path[I].E->getSourceRange();
952*0fca6ea1SDimitry Andric 
953*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::LambdaCaptureInit:
954*0fca6ea1SDimitry Andric       if (!Path[I].Capture->capturesVariable())
955*0fca6ea1SDimitry Andric         continue;
956*0fca6ea1SDimitry Andric       return Path[I].E->getSourceRange();
957*0fca6ea1SDimitry Andric     }
958*0fca6ea1SDimitry Andric   }
959*0fca6ea1SDimitry Andric   return E->getSourceRange();
960*0fca6ea1SDimitry Andric }
961*0fca6ea1SDimitry Andric 
962*0fca6ea1SDimitry Andric static bool pathOnlyHandlesGslPointer(IndirectLocalPath &Path) {
963*0fca6ea1SDimitry Andric   for (const auto &It : llvm::reverse(Path)) {
964*0fca6ea1SDimitry Andric     switch (It.Kind) {
965*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::VarInit:
966*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::AddressOf:
967*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::LifetimeBoundCall:
968*0fca6ea1SDimitry Andric       continue;
969*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::GslPointerInit:
970*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::GslReferenceInit:
971*0fca6ea1SDimitry Andric     case IndirectLocalPathEntry::GslPointerAssignment:
972*0fca6ea1SDimitry Andric       return true;
973*0fca6ea1SDimitry Andric     default:
974*0fca6ea1SDimitry Andric       return false;
975*0fca6ea1SDimitry Andric     }
976*0fca6ea1SDimitry Andric   }
977*0fca6ea1SDimitry Andric   return false;
978*0fca6ea1SDimitry Andric }
979*0fca6ea1SDimitry Andric 
980*0fca6ea1SDimitry Andric static void checkExprLifetimeImpl(Sema &SemaRef,
981*0fca6ea1SDimitry Andric                                   const InitializedEntity *InitEntity,
982*0fca6ea1SDimitry Andric                                   const InitializedEntity *ExtendingEntity,
983*0fca6ea1SDimitry Andric                                   LifetimeKind LK,
984*0fca6ea1SDimitry Andric                                   const AssignedEntity *AEntity, Expr *Init,
985*0fca6ea1SDimitry Andric                                   bool EnableLifetimeWarnings) {
986*0fca6ea1SDimitry Andric   assert((AEntity && LK == LK_Assignment) ||
987*0fca6ea1SDimitry Andric          (InitEntity && LK != LK_Assignment));
988*0fca6ea1SDimitry Andric   // If this entity doesn't have an interesting lifetime, don't bother looking
989*0fca6ea1SDimitry Andric   // for temporaries within its initializer.
990*0fca6ea1SDimitry Andric   if (LK == LK_FullExpression)
991*0fca6ea1SDimitry Andric     return;
992*0fca6ea1SDimitry Andric 
993*0fca6ea1SDimitry Andric   // FIXME: consider moving the TemporaryVisitor and visitLocalsRetained*
994*0fca6ea1SDimitry Andric   // functions to a dedicated class.
995*0fca6ea1SDimitry Andric   auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L,
996*0fca6ea1SDimitry Andric                               ReferenceKind RK) -> bool {
997*0fca6ea1SDimitry Andric     SourceRange DiagRange = nextPathEntryRange(Path, 0, L);
998*0fca6ea1SDimitry Andric     SourceLocation DiagLoc = DiagRange.getBegin();
999*0fca6ea1SDimitry Andric 
1000*0fca6ea1SDimitry Andric     auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1001*0fca6ea1SDimitry Andric 
1002*0fca6ea1SDimitry Andric     bool IsGslPtrValueFromGslTempOwner = false;
1003*0fca6ea1SDimitry Andric     bool IsLocalGslOwner = false;
1004*0fca6ea1SDimitry Andric     if (pathOnlyHandlesGslPointer(Path)) {
1005*0fca6ea1SDimitry Andric       if (isa<DeclRefExpr>(L)) {
1006*0fca6ea1SDimitry Andric         // We do not want to follow the references when returning a pointer
1007*0fca6ea1SDimitry Andric         // originating from a local owner to avoid the following false positive:
1008*0fca6ea1SDimitry Andric         //   int &p = *localUniquePtr;
1009*0fca6ea1SDimitry Andric         //   someContainer.add(std::move(localUniquePtr));
1010*0fca6ea1SDimitry Andric         //   return p;
1011*0fca6ea1SDimitry Andric         IsLocalGslOwner = isRecordWithAttr<OwnerAttr>(L->getType());
1012*0fca6ea1SDimitry Andric         if (pathContainsInit(Path) || !IsLocalGslOwner)
1013*0fca6ea1SDimitry Andric           return false;
1014*0fca6ea1SDimitry Andric       } else {
1015*0fca6ea1SDimitry Andric         IsGslPtrValueFromGslTempOwner =
1016*0fca6ea1SDimitry Andric             MTE && !MTE->getExtendingDecl() &&
1017*0fca6ea1SDimitry Andric             isRecordWithAttr<OwnerAttr>(MTE->getType());
1018*0fca6ea1SDimitry Andric         // Skipping a chain of initializing gsl::Pointer annotated objects.
1019*0fca6ea1SDimitry Andric         // We are looking only for the final source to find out if it was
1020*0fca6ea1SDimitry Andric         // a local or temporary owner or the address of a local variable/param.
1021*0fca6ea1SDimitry Andric         if (!IsGslPtrValueFromGslTempOwner)
1022*0fca6ea1SDimitry Andric           return true;
1023*0fca6ea1SDimitry Andric       }
1024*0fca6ea1SDimitry Andric     }
1025*0fca6ea1SDimitry Andric 
1026*0fca6ea1SDimitry Andric     switch (LK) {
1027*0fca6ea1SDimitry Andric     case LK_FullExpression:
1028*0fca6ea1SDimitry Andric       llvm_unreachable("already handled this");
1029*0fca6ea1SDimitry Andric 
1030*0fca6ea1SDimitry Andric     case LK_Extended: {
1031*0fca6ea1SDimitry Andric       if (!MTE) {
1032*0fca6ea1SDimitry Andric         // The initialized entity has lifetime beyond the full-expression,
1033*0fca6ea1SDimitry Andric         // and the local entity does too, so don't warn.
1034*0fca6ea1SDimitry Andric         //
1035*0fca6ea1SDimitry Andric         // FIXME: We should consider warning if a static / thread storage
1036*0fca6ea1SDimitry Andric         // duration variable retains an automatic storage duration local.
1037*0fca6ea1SDimitry Andric         return false;
1038*0fca6ea1SDimitry Andric       }
1039*0fca6ea1SDimitry Andric 
1040*0fca6ea1SDimitry Andric       if (IsGslPtrValueFromGslTempOwner && DiagLoc.isValid()) {
1041*0fca6ea1SDimitry Andric         SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1042*0fca6ea1SDimitry Andric             << DiagRange;
1043*0fca6ea1SDimitry Andric         return false;
1044*0fca6ea1SDimitry Andric       }
1045*0fca6ea1SDimitry Andric 
1046*0fca6ea1SDimitry Andric       switch (shouldLifetimeExtendThroughPath(Path)) {
1047*0fca6ea1SDimitry Andric       case PathLifetimeKind::Extend:
1048*0fca6ea1SDimitry Andric         // Update the storage duration of the materialized temporary.
1049*0fca6ea1SDimitry Andric         // FIXME: Rebuild the expression instead of mutating it.
1050*0fca6ea1SDimitry Andric         MTE->setExtendingDecl(ExtendingEntity->getDecl(),
1051*0fca6ea1SDimitry Andric                               ExtendingEntity->allocateManglingNumber());
1052*0fca6ea1SDimitry Andric         // Also visit the temporaries lifetime-extended by this initializer.
1053*0fca6ea1SDimitry Andric         return true;
1054*0fca6ea1SDimitry Andric 
1055*0fca6ea1SDimitry Andric       case PathLifetimeKind::ShouldExtend:
1056*0fca6ea1SDimitry Andric         // We're supposed to lifetime-extend the temporary along this path (per
1057*0fca6ea1SDimitry Andric         // the resolution of DR1815), but we don't support that yet.
1058*0fca6ea1SDimitry Andric         //
1059*0fca6ea1SDimitry Andric         // FIXME: Properly handle this situation. Perhaps the easiest approach
1060*0fca6ea1SDimitry Andric         // would be to clone the initializer expression on each use that would
1061*0fca6ea1SDimitry Andric         // lifetime extend its temporaries.
1062*0fca6ea1SDimitry Andric         SemaRef.Diag(DiagLoc, diag::warn_unsupported_lifetime_extension)
1063*0fca6ea1SDimitry Andric             << RK << DiagRange;
1064*0fca6ea1SDimitry Andric         break;
1065*0fca6ea1SDimitry Andric 
1066*0fca6ea1SDimitry Andric       case PathLifetimeKind::NoExtend:
1067*0fca6ea1SDimitry Andric         // If the path goes through the initialization of a variable or field,
1068*0fca6ea1SDimitry Andric         // it can't possibly reach a temporary created in this full-expression.
1069*0fca6ea1SDimitry Andric         // We will have already diagnosed any problems with the initializer.
1070*0fca6ea1SDimitry Andric         if (pathContainsInit(Path))
1071*0fca6ea1SDimitry Andric           return false;
1072*0fca6ea1SDimitry Andric 
1073*0fca6ea1SDimitry Andric         SemaRef.Diag(DiagLoc, diag::warn_dangling_variable)
1074*0fca6ea1SDimitry Andric             << RK << !InitEntity->getParent()
1075*0fca6ea1SDimitry Andric             << ExtendingEntity->getDecl()->isImplicit()
1076*0fca6ea1SDimitry Andric             << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;
1077*0fca6ea1SDimitry Andric         break;
1078*0fca6ea1SDimitry Andric       }
1079*0fca6ea1SDimitry Andric       break;
1080*0fca6ea1SDimitry Andric     }
1081*0fca6ea1SDimitry Andric 
1082*0fca6ea1SDimitry Andric     case LK_Assignment: {
1083*0fca6ea1SDimitry Andric       if (!MTE || pathContainsInit(Path))
1084*0fca6ea1SDimitry Andric         return false;
1085*0fca6ea1SDimitry Andric       assert(shouldLifetimeExtendThroughPath(Path) ==
1086*0fca6ea1SDimitry Andric                  PathLifetimeKind::NoExtend &&
1087*0fca6ea1SDimitry Andric              "No lifetime extension for assignments");
1088*0fca6ea1SDimitry Andric       SemaRef.Diag(DiagLoc,
1089*0fca6ea1SDimitry Andric                    IsGslPtrValueFromGslTempOwner
1090*0fca6ea1SDimitry Andric                        ? diag::warn_dangling_lifetime_pointer_assignment
1091*0fca6ea1SDimitry Andric                        : diag::warn_dangling_pointer_assignment)
1092*0fca6ea1SDimitry Andric           << AEntity->LHS << DiagRange;
1093*0fca6ea1SDimitry Andric       return false;
1094*0fca6ea1SDimitry Andric     }
1095*0fca6ea1SDimitry Andric     case LK_MemInitializer: {
1096*0fca6ea1SDimitry Andric       if (MTE) {
1097*0fca6ea1SDimitry Andric         // Under C++ DR1696, if a mem-initializer (or a default member
1098*0fca6ea1SDimitry Andric         // initializer used by the absence of one) would lifetime-extend a
1099*0fca6ea1SDimitry Andric         // temporary, the program is ill-formed.
1100*0fca6ea1SDimitry Andric         if (auto *ExtendingDecl =
1101*0fca6ea1SDimitry Andric                 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1102*0fca6ea1SDimitry Andric           if (IsGslPtrValueFromGslTempOwner) {
1103*0fca6ea1SDimitry Andric             SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1104*0fca6ea1SDimitry Andric                 << ExtendingDecl << DiagRange;
1105*0fca6ea1SDimitry Andric             SemaRef.Diag(ExtendingDecl->getLocation(),
1106*0fca6ea1SDimitry Andric                          diag::note_ref_or_ptr_member_declared_here)
1107*0fca6ea1SDimitry Andric                 << true;
1108*0fca6ea1SDimitry Andric             return false;
1109*0fca6ea1SDimitry Andric           }
1110*0fca6ea1SDimitry Andric           bool IsSubobjectMember = ExtendingEntity != InitEntity;
1111*0fca6ea1SDimitry Andric           SemaRef.Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) !=
1112*0fca6ea1SDimitry Andric                                         PathLifetimeKind::NoExtend
1113*0fca6ea1SDimitry Andric                                     ? diag::err_dangling_member
1114*0fca6ea1SDimitry Andric                                     : diag::warn_dangling_member)
1115*0fca6ea1SDimitry Andric               << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1116*0fca6ea1SDimitry Andric           // Don't bother adding a note pointing to the field if we're inside
1117*0fca6ea1SDimitry Andric           // its default member initializer; our primary diagnostic points to
1118*0fca6ea1SDimitry Andric           // the same place in that case.
1119*0fca6ea1SDimitry Andric           if (Path.empty() ||
1120*0fca6ea1SDimitry Andric               Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1121*0fca6ea1SDimitry Andric             SemaRef.Diag(ExtendingDecl->getLocation(),
1122*0fca6ea1SDimitry Andric                          diag::note_lifetime_extending_member_declared_here)
1123*0fca6ea1SDimitry Andric                 << RK << IsSubobjectMember;
1124*0fca6ea1SDimitry Andric           }
1125*0fca6ea1SDimitry Andric         } else {
1126*0fca6ea1SDimitry Andric           // We have a mem-initializer but no particular field within it; this
1127*0fca6ea1SDimitry Andric           // is either a base class or a delegating initializer directly
1128*0fca6ea1SDimitry Andric           // initializing the base-class from something that doesn't live long
1129*0fca6ea1SDimitry Andric           // enough.
1130*0fca6ea1SDimitry Andric           //
1131*0fca6ea1SDimitry Andric           // FIXME: Warn on this.
1132*0fca6ea1SDimitry Andric           return false;
1133*0fca6ea1SDimitry Andric         }
1134*0fca6ea1SDimitry Andric       } else {
1135*0fca6ea1SDimitry Andric         // Paths via a default initializer can only occur during error recovery
1136*0fca6ea1SDimitry Andric         // (there's no other way that a default initializer can refer to a
1137*0fca6ea1SDimitry Andric         // local). Don't produce a bogus warning on those cases.
1138*0fca6ea1SDimitry Andric         if (pathContainsInit(Path))
1139*0fca6ea1SDimitry Andric           return false;
1140*0fca6ea1SDimitry Andric 
1141*0fca6ea1SDimitry Andric         // Suppress false positives for code like the one below:
1142*0fca6ea1SDimitry Andric         //   Ctor(unique_ptr<T> up) : member(*up), member2(move(up)) {}
1143*0fca6ea1SDimitry Andric         if (IsLocalGslOwner && pathOnlyHandlesGslPointer(Path))
1144*0fca6ea1SDimitry Andric           return false;
1145*0fca6ea1SDimitry Andric 
1146*0fca6ea1SDimitry Andric         auto *DRE = dyn_cast<DeclRefExpr>(L);
1147*0fca6ea1SDimitry Andric         auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
1148*0fca6ea1SDimitry Andric         if (!VD) {
1149*0fca6ea1SDimitry Andric           // A member was initialized to a local block.
1150*0fca6ea1SDimitry Andric           // FIXME: Warn on this.
1151*0fca6ea1SDimitry Andric           return false;
1152*0fca6ea1SDimitry Andric         }
1153*0fca6ea1SDimitry Andric 
1154*0fca6ea1SDimitry Andric         if (auto *Member =
1155*0fca6ea1SDimitry Andric                 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1156*0fca6ea1SDimitry Andric           bool IsPointer = !Member->getType()->isReferenceType();
1157*0fca6ea1SDimitry Andric           SemaRef.Diag(DiagLoc,
1158*0fca6ea1SDimitry Andric                        IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1159*0fca6ea1SDimitry Andric                                  : diag::warn_bind_ref_member_to_parameter)
1160*0fca6ea1SDimitry Andric               << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
1161*0fca6ea1SDimitry Andric           SemaRef.Diag(Member->getLocation(),
1162*0fca6ea1SDimitry Andric                        diag::note_ref_or_ptr_member_declared_here)
1163*0fca6ea1SDimitry Andric               << (unsigned)IsPointer;
1164*0fca6ea1SDimitry Andric         }
1165*0fca6ea1SDimitry Andric       }
1166*0fca6ea1SDimitry Andric       break;
1167*0fca6ea1SDimitry Andric     }
1168*0fca6ea1SDimitry Andric 
1169*0fca6ea1SDimitry Andric     case LK_New:
1170*0fca6ea1SDimitry Andric       if (isa<MaterializeTemporaryExpr>(L)) {
1171*0fca6ea1SDimitry Andric         if (IsGslPtrValueFromGslTempOwner)
1172*0fca6ea1SDimitry Andric           SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1173*0fca6ea1SDimitry Andric               << DiagRange;
1174*0fca6ea1SDimitry Andric         else
1175*0fca6ea1SDimitry Andric           SemaRef.Diag(DiagLoc, RK == RK_ReferenceBinding
1176*0fca6ea1SDimitry Andric                                     ? diag::warn_new_dangling_reference
1177*0fca6ea1SDimitry Andric                                     : diag::warn_new_dangling_initializer_list)
1178*0fca6ea1SDimitry Andric               << !InitEntity->getParent() << DiagRange;
1179*0fca6ea1SDimitry Andric       } else {
1180*0fca6ea1SDimitry Andric         // We can't determine if the allocation outlives the local declaration.
1181*0fca6ea1SDimitry Andric         return false;
1182*0fca6ea1SDimitry Andric       }
1183*0fca6ea1SDimitry Andric       break;
1184*0fca6ea1SDimitry Andric 
1185*0fca6ea1SDimitry Andric     case LK_Return:
1186*0fca6ea1SDimitry Andric     case LK_StmtExprResult:
1187*0fca6ea1SDimitry Andric       if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1188*0fca6ea1SDimitry Andric         // We can't determine if the local variable outlives the statement
1189*0fca6ea1SDimitry Andric         // expression.
1190*0fca6ea1SDimitry Andric         if (LK == LK_StmtExprResult)
1191*0fca6ea1SDimitry Andric           return false;
1192*0fca6ea1SDimitry Andric         SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1193*0fca6ea1SDimitry Andric             << InitEntity->getType()->isReferenceType() << DRE->getDecl()
1194*0fca6ea1SDimitry Andric             << isa<ParmVarDecl>(DRE->getDecl()) << DiagRange;
1195*0fca6ea1SDimitry Andric       } else if (isa<BlockExpr>(L)) {
1196*0fca6ea1SDimitry Andric         SemaRef.Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1197*0fca6ea1SDimitry Andric       } else if (isa<AddrLabelExpr>(L)) {
1198*0fca6ea1SDimitry Andric         // Don't warn when returning a label from a statement expression.
1199*0fca6ea1SDimitry Andric         // Leaving the scope doesn't end its lifetime.
1200*0fca6ea1SDimitry Andric         if (LK == LK_StmtExprResult)
1201*0fca6ea1SDimitry Andric           return false;
1202*0fca6ea1SDimitry Andric         SemaRef.Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1203*0fca6ea1SDimitry Andric       } else if (auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1204*0fca6ea1SDimitry Andric         SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1205*0fca6ea1SDimitry Andric             << InitEntity->getType()->isReferenceType() << CLE->getInitializer()
1206*0fca6ea1SDimitry Andric             << 2 << DiagRange;
1207*0fca6ea1SDimitry Andric       } else {
1208*0fca6ea1SDimitry Andric         // P2748R5: Disallow Binding a Returned Glvalue to a Temporary.
1209*0fca6ea1SDimitry Andric         // [stmt.return]/p6: In a function whose return type is a reference,
1210*0fca6ea1SDimitry Andric         // other than an invented function for std::is_convertible ([meta.rel]),
1211*0fca6ea1SDimitry Andric         // a return statement that binds the returned reference to a temporary
1212*0fca6ea1SDimitry Andric         // expression ([class.temporary]) is ill-formed.
1213*0fca6ea1SDimitry Andric         if (SemaRef.getLangOpts().CPlusPlus26 &&
1214*0fca6ea1SDimitry Andric             InitEntity->getType()->isReferenceType())
1215*0fca6ea1SDimitry Andric           SemaRef.Diag(DiagLoc, diag::err_ret_local_temp_ref)
1216*0fca6ea1SDimitry Andric               << InitEntity->getType()->isReferenceType() << DiagRange;
1217*0fca6ea1SDimitry Andric         else
1218*0fca6ea1SDimitry Andric           SemaRef.Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1219*0fca6ea1SDimitry Andric               << InitEntity->getType()->isReferenceType() << DiagRange;
1220*0fca6ea1SDimitry Andric       }
1221*0fca6ea1SDimitry Andric       break;
1222*0fca6ea1SDimitry Andric     }
1223*0fca6ea1SDimitry Andric 
1224*0fca6ea1SDimitry Andric     for (unsigned I = 0; I != Path.size(); ++I) {
1225*0fca6ea1SDimitry Andric       auto Elem = Path[I];
1226*0fca6ea1SDimitry Andric 
1227*0fca6ea1SDimitry Andric       switch (Elem.Kind) {
1228*0fca6ea1SDimitry Andric       case IndirectLocalPathEntry::AddressOf:
1229*0fca6ea1SDimitry Andric       case IndirectLocalPathEntry::LValToRVal:
1230*0fca6ea1SDimitry Andric         // These exist primarily to mark the path as not permitting or
1231*0fca6ea1SDimitry Andric         // supporting lifetime extension.
1232*0fca6ea1SDimitry Andric         break;
1233*0fca6ea1SDimitry Andric 
1234*0fca6ea1SDimitry Andric       case IndirectLocalPathEntry::LifetimeBoundCall:
1235*0fca6ea1SDimitry Andric       case IndirectLocalPathEntry::TemporaryCopy:
1236*0fca6ea1SDimitry Andric       case IndirectLocalPathEntry::GslPointerInit:
1237*0fca6ea1SDimitry Andric       case IndirectLocalPathEntry::GslReferenceInit:
1238*0fca6ea1SDimitry Andric       case IndirectLocalPathEntry::GslPointerAssignment:
1239*0fca6ea1SDimitry Andric         // FIXME: Consider adding a note for these.
1240*0fca6ea1SDimitry Andric         break;
1241*0fca6ea1SDimitry Andric 
1242*0fca6ea1SDimitry Andric       case IndirectLocalPathEntry::DefaultInit: {
1243*0fca6ea1SDimitry Andric         auto *FD = cast<FieldDecl>(Elem.D);
1244*0fca6ea1SDimitry Andric         SemaRef.Diag(FD->getLocation(),
1245*0fca6ea1SDimitry Andric                      diag::note_init_with_default_member_initializer)
1246*0fca6ea1SDimitry Andric             << FD << nextPathEntryRange(Path, I + 1, L);
1247*0fca6ea1SDimitry Andric         break;
1248*0fca6ea1SDimitry Andric       }
1249*0fca6ea1SDimitry Andric 
1250*0fca6ea1SDimitry Andric       case IndirectLocalPathEntry::VarInit: {
1251*0fca6ea1SDimitry Andric         const VarDecl *VD = cast<VarDecl>(Elem.D);
1252*0fca6ea1SDimitry Andric         SemaRef.Diag(VD->getLocation(), diag::note_local_var_initializer)
1253*0fca6ea1SDimitry Andric             << VD->getType()->isReferenceType() << VD->isImplicit()
1254*0fca6ea1SDimitry Andric             << VD->getDeclName() << nextPathEntryRange(Path, I + 1, L);
1255*0fca6ea1SDimitry Andric         break;
1256*0fca6ea1SDimitry Andric       }
1257*0fca6ea1SDimitry Andric 
1258*0fca6ea1SDimitry Andric       case IndirectLocalPathEntry::LambdaCaptureInit:
1259*0fca6ea1SDimitry Andric         if (!Elem.Capture->capturesVariable())
1260*0fca6ea1SDimitry Andric           break;
1261*0fca6ea1SDimitry Andric         // FIXME: We can't easily tell apart an init-capture from a nested
1262*0fca6ea1SDimitry Andric         // capture of an init-capture.
1263*0fca6ea1SDimitry Andric         const ValueDecl *VD = Elem.Capture->getCapturedVar();
1264*0fca6ea1SDimitry Andric         SemaRef.Diag(Elem.Capture->getLocation(),
1265*0fca6ea1SDimitry Andric                      diag::note_lambda_capture_initializer)
1266*0fca6ea1SDimitry Andric             << VD << VD->isInitCapture() << Elem.Capture->isExplicit()
1267*0fca6ea1SDimitry Andric             << (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD
1268*0fca6ea1SDimitry Andric             << nextPathEntryRange(Path, I + 1, L);
1269*0fca6ea1SDimitry Andric         break;
1270*0fca6ea1SDimitry Andric       }
1271*0fca6ea1SDimitry Andric     }
1272*0fca6ea1SDimitry Andric 
1273*0fca6ea1SDimitry Andric     // We didn't lifetime-extend, so don't go any further; we don't need more
1274*0fca6ea1SDimitry Andric     // warnings or errors on inner temporaries within this one's initializer.
1275*0fca6ea1SDimitry Andric     return false;
1276*0fca6ea1SDimitry Andric   };
1277*0fca6ea1SDimitry Andric 
1278*0fca6ea1SDimitry Andric   llvm::SmallVector<IndirectLocalPathEntry, 8> Path;
1279*0fca6ea1SDimitry Andric   if (EnableLifetimeWarnings && LK == LK_Assignment &&
1280*0fca6ea1SDimitry Andric       isRecordWithAttr<PointerAttr>(AEntity->LHS->getType()))
1281*0fca6ea1SDimitry Andric     Path.push_back({IndirectLocalPathEntry::GslPointerAssignment, Init});
1282*0fca6ea1SDimitry Andric 
1283*0fca6ea1SDimitry Andric   if (Init->isGLValue())
1284*0fca6ea1SDimitry Andric     visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding,
1285*0fca6ea1SDimitry Andric                                           TemporaryVisitor,
1286*0fca6ea1SDimitry Andric                                           EnableLifetimeWarnings);
1287*0fca6ea1SDimitry Andric   else
1288*0fca6ea1SDimitry Andric     visitLocalsRetainedByInitializer(
1289*0fca6ea1SDimitry Andric         Path, Init, TemporaryVisitor,
1290*0fca6ea1SDimitry Andric         // Don't revisit the sub inits for the intialization case.
1291*0fca6ea1SDimitry Andric         /*RevisitSubinits=*/!InitEntity, EnableLifetimeWarnings);
1292*0fca6ea1SDimitry Andric }
1293*0fca6ea1SDimitry Andric 
1294*0fca6ea1SDimitry Andric void checkExprLifetime(Sema &SemaRef, const InitializedEntity &Entity,
1295*0fca6ea1SDimitry Andric                        Expr *Init) {
1296*0fca6ea1SDimitry Andric   auto LTResult = getEntityLifetime(&Entity);
1297*0fca6ea1SDimitry Andric   LifetimeKind LK = LTResult.getInt();
1298*0fca6ea1SDimitry Andric   const InitializedEntity *ExtendingEntity = LTResult.getPointer();
1299*0fca6ea1SDimitry Andric   bool EnableLifetimeWarnings = !SemaRef.getDiagnostics().isIgnored(
1300*0fca6ea1SDimitry Andric       diag::warn_dangling_lifetime_pointer, SourceLocation());
1301*0fca6ea1SDimitry Andric   checkExprLifetimeImpl(SemaRef, &Entity, ExtendingEntity, LK,
1302*0fca6ea1SDimitry Andric                         /*AEntity*/ nullptr, Init, EnableLifetimeWarnings);
1303*0fca6ea1SDimitry Andric }
1304*0fca6ea1SDimitry Andric 
1305*0fca6ea1SDimitry Andric void checkExprLifetime(Sema &SemaRef, const AssignedEntity &Entity,
1306*0fca6ea1SDimitry Andric                        Expr *Init) {
1307*0fca6ea1SDimitry Andric   bool EnableLifetimeWarnings = !SemaRef.getDiagnostics().isIgnored(
1308*0fca6ea1SDimitry Andric       diag::warn_dangling_lifetime_pointer, SourceLocation());
1309*0fca6ea1SDimitry Andric   bool RunAnalysis = Entity.LHS->getType()->isPointerType() ||
1310*0fca6ea1SDimitry Andric                      (EnableLifetimeWarnings &&
1311*0fca6ea1SDimitry Andric                       isRecordWithAttr<PointerAttr>(Entity.LHS->getType()));
1312*0fca6ea1SDimitry Andric 
1313*0fca6ea1SDimitry Andric   if (!RunAnalysis)
1314*0fca6ea1SDimitry Andric     return;
1315*0fca6ea1SDimitry Andric 
1316*0fca6ea1SDimitry Andric   checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr,
1317*0fca6ea1SDimitry Andric                         /*ExtendingEntity=*/nullptr, LK_Assignment, &Entity,
1318*0fca6ea1SDimitry Andric                         Init, EnableLifetimeWarnings);
1319*0fca6ea1SDimitry Andric }
1320*0fca6ea1SDimitry Andric 
1321*0fca6ea1SDimitry Andric } // namespace clang::sema
1322