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