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