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/AST/Type.h" 13 #include "clang/Basic/DiagnosticSema.h" 14 #include "clang/Sema/Initialization.h" 15 #include "clang/Sema/Sema.h" 16 #include "llvm/ADT/PointerIntPair.h" 17 18 namespace clang::sema { 19 namespace { 20 enum LifetimeKind { 21 /// The lifetime of a temporary bound to this entity ends at the end of the 22 /// full-expression, and that's (probably) fine. 23 LK_FullExpression, 24 25 /// The lifetime of a temporary bound to this entity is extended to the 26 /// lifeitme of the entity itself. 27 LK_Extended, 28 29 /// The lifetime of a temporary bound to this entity probably ends too soon, 30 /// because the entity is allocated in a new-expression. 31 LK_New, 32 33 /// The lifetime of a temporary bound to this entity ends too soon, because 34 /// the entity is a return object. 35 LK_Return, 36 37 /// The lifetime of a temporary bound to this entity ends too soon, because 38 /// the entity passed to a musttail function call. 39 LK_MustTail, 40 41 /// The lifetime of a temporary bound to this entity ends too soon, because 42 /// the entity is the result of a statement expression. 43 LK_StmtExprResult, 44 45 /// This is a mem-initializer: if it would extend a temporary (other than via 46 /// a default member initializer), the program is ill-formed. 47 LK_MemInitializer, 48 49 /// The lifetime of a temporary bound to this entity may end too soon, 50 /// because the entity is a pointer and we assign the address of a temporary 51 /// object to it. 52 LK_Assignment, 53 54 /// The lifetime of a temporary bound to this entity may end too soon, 55 /// because the entity may capture the reference to a temporary object. 56 LK_LifetimeCapture, 57 }; 58 using LifetimeResult = 59 llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>; 60 } // namespace 61 62 /// Determine the declaration which an initialized entity ultimately refers to, 63 /// for the purpose of lifetime-extending a temporary bound to a reference in 64 /// the initialization of \p Entity. 65 static LifetimeResult 66 getEntityLifetime(const InitializedEntity *Entity, 67 const InitializedEntity *InitField = nullptr) { 68 // C++11 [class.temporary]p5: 69 switch (Entity->getKind()) { 70 case InitializedEntity::EK_Variable: 71 // The temporary [...] persists for the lifetime of the reference 72 return {Entity, LK_Extended}; 73 74 case InitializedEntity::EK_Member: 75 // For subobjects, we look at the complete object. 76 if (Entity->getParent()) 77 return getEntityLifetime(Entity->getParent(), Entity); 78 79 // except: 80 // C++17 [class.base.init]p8: 81 // A temporary expression bound to a reference member in a 82 // mem-initializer is ill-formed. 83 // C++17 [class.base.init]p11: 84 // A temporary expression bound to a reference member from a 85 // default member initializer is ill-formed. 86 // 87 // The context of p11 and its example suggest that it's only the use of a 88 // default member initializer from a constructor that makes the program 89 // ill-formed, not its mere existence, and that it can even be used by 90 // aggregate initialization. 91 return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended 92 : LK_MemInitializer}; 93 94 case InitializedEntity::EK_Binding: 95 // Per [dcl.decomp]p3, the binding is treated as a variable of reference 96 // type. 97 return {Entity, LK_Extended}; 98 99 case InitializedEntity::EK_Parameter: 100 case InitializedEntity::EK_Parameter_CF_Audited: 101 // -- A temporary bound to a reference parameter in a function call 102 // persists until the completion of the full-expression containing 103 // the call. 104 return {nullptr, LK_FullExpression}; 105 106 case InitializedEntity::EK_TemplateParameter: 107 // FIXME: This will always be ill-formed; should we eagerly diagnose it 108 // here? 109 return {nullptr, LK_FullExpression}; 110 111 case InitializedEntity::EK_Result: 112 // -- The lifetime of a temporary bound to the returned value in a 113 // function return statement is not extended; the temporary is 114 // destroyed at the end of the full-expression in the return statement. 115 return {nullptr, LK_Return}; 116 117 case InitializedEntity::EK_StmtExprResult: 118 // FIXME: Should we lifetime-extend through the result of a statement 119 // expression? 120 return {nullptr, LK_StmtExprResult}; 121 122 case InitializedEntity::EK_New: 123 // -- A temporary bound to a reference in a new-initializer persists 124 // until the completion of the full-expression containing the 125 // new-initializer. 126 return {nullptr, LK_New}; 127 128 case InitializedEntity::EK_Temporary: 129 case InitializedEntity::EK_CompoundLiteralInit: 130 case InitializedEntity::EK_RelatedResult: 131 // We don't yet know the storage duration of the surrounding temporary. 132 // Assume it's got full-expression duration for now, it will patch up our 133 // storage duration if that's not correct. 134 return {nullptr, LK_FullExpression}; 135 136 case InitializedEntity::EK_ArrayElement: 137 // For subobjects, we look at the complete object. 138 return getEntityLifetime(Entity->getParent(), InitField); 139 140 case InitializedEntity::EK_Base: 141 // For subobjects, we look at the complete object. 142 if (Entity->getParent()) 143 return getEntityLifetime(Entity->getParent(), InitField); 144 return {InitField, LK_MemInitializer}; 145 146 case InitializedEntity::EK_Delegating: 147 // We can reach this case for aggregate initialization in a constructor: 148 // struct A { int &&r; }; 149 // struct B : A { B() : A{0} {} }; 150 // In this case, use the outermost field decl as the context. 151 return {InitField, LK_MemInitializer}; 152 153 case InitializedEntity::EK_BlockElement: 154 case InitializedEntity::EK_LambdaToBlockConversionBlockElement: 155 case InitializedEntity::EK_LambdaCapture: 156 case InitializedEntity::EK_VectorElement: 157 case InitializedEntity::EK_ComplexElement: 158 return {nullptr, LK_FullExpression}; 159 160 case InitializedEntity::EK_Exception: 161 // FIXME: Can we diagnose lifetime problems with exceptions? 162 return {nullptr, LK_FullExpression}; 163 164 case InitializedEntity::EK_ParenAggInitMember: 165 // -- A temporary object bound to a reference element of an aggregate of 166 // class type initialized from a parenthesized expression-list 167 // [dcl.init, 9.3] persists until the completion of the full-expression 168 // containing the expression-list. 169 return {nullptr, LK_FullExpression}; 170 } 171 172 llvm_unreachable("unknown entity kind"); 173 } 174 175 namespace { 176 enum ReferenceKind { 177 /// Lifetime would be extended by a reference binding to a temporary. 178 RK_ReferenceBinding, 179 /// Lifetime would be extended by a std::initializer_list object binding to 180 /// its backing array. 181 RK_StdInitializerList, 182 }; 183 184 /// A temporary or local variable. This will be one of: 185 /// * A MaterializeTemporaryExpr. 186 /// * A DeclRefExpr whose declaration is a local. 187 /// * An AddrLabelExpr. 188 /// * A BlockExpr for a block with captures. 189 using Local = Expr *; 190 191 /// Expressions we stepped over when looking for the local state. Any steps 192 /// that would inhibit lifetime extension or take us out of subexpressions of 193 /// the initializer are included. 194 struct IndirectLocalPathEntry { 195 enum EntryKind { 196 DefaultInit, 197 AddressOf, 198 VarInit, 199 LValToRVal, 200 LifetimeBoundCall, 201 TemporaryCopy, 202 LambdaCaptureInit, 203 MemberExpr, 204 GslReferenceInit, 205 GslPointerInit, 206 GslPointerAssignment, 207 DefaultArg, 208 ParenAggInit, 209 } Kind; 210 Expr *E; 211 union { 212 const Decl *D = nullptr; 213 const LambdaCapture *Capture; 214 }; 215 IndirectLocalPathEntry() {} 216 IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {} 217 IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D) 218 : Kind(K), E(E), D(D) {} 219 IndirectLocalPathEntry(EntryKind K, Expr *E, const LambdaCapture *Capture) 220 : Kind(K), E(E), Capture(Capture) {} 221 }; 222 223 using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>; 224 225 struct RevertToOldSizeRAII { 226 IndirectLocalPath &Path; 227 unsigned OldSize = Path.size(); 228 RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {} 229 ~RevertToOldSizeRAII() { Path.resize(OldSize); } 230 }; 231 232 using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L, 233 ReferenceKind RK)>; 234 } // namespace 235 236 static bool isVarOnPath(const IndirectLocalPath &Path, VarDecl *VD) { 237 for (auto E : Path) 238 if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD) 239 return true; 240 return false; 241 } 242 243 static bool pathContainsInit(const IndirectLocalPath &Path) { 244 return llvm::any_of(Path, [=](IndirectLocalPathEntry E) { 245 return E.Kind == IndirectLocalPathEntry::DefaultInit || 246 E.Kind == IndirectLocalPathEntry::VarInit; 247 }); 248 } 249 250 static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, 251 Expr *Init, LocalVisitor Visit, 252 bool RevisitSubinits); 253 254 static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, 255 Expr *Init, ReferenceKind RK, 256 LocalVisitor Visit); 257 258 template <typename T> static bool isRecordWithAttr(QualType Type) { 259 auto *RD = Type->getAsCXXRecordDecl(); 260 if (!RD) 261 return false; 262 // Generally, if a primary template class declaration is annotated with an 263 // attribute, all its specializations generated from template instantiations 264 // should inherit the attribute. 265 // 266 // However, since lifetime analysis occurs during parsing, we may encounter 267 // cases where a full definition of the specialization is not required. In 268 // such cases, the specialization declaration remains incomplete and lacks the 269 // attribute. Therefore, we fall back to checking the primary template class. 270 // 271 // Note: it is possible for a specialization declaration to have an attribute 272 // even if the primary template does not. 273 // 274 // FIXME: What if the primary template and explicit specialization 275 // declarations have conflicting attributes? We should consider diagnosing 276 // this scenario. 277 bool Result = RD->hasAttr<T>(); 278 279 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) 280 Result |= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<T>(); 281 282 return Result; 283 } 284 285 // Tells whether the type is annotated with [[gsl::Pointer]]. 286 bool isGLSPointerType(QualType QT) { return isRecordWithAttr<PointerAttr>(QT); } 287 288 static bool isPointerLikeType(QualType QT) { 289 return isGLSPointerType(QT) || QT->isPointerType() || QT->isNullPtrType(); 290 } 291 292 // Decl::isInStdNamespace will return false for iterators in some STL 293 // implementations due to them being defined in a namespace outside of the std 294 // namespace. 295 static bool isInStlNamespace(const Decl *D) { 296 const DeclContext *DC = D->getDeclContext(); 297 if (!DC) 298 return false; 299 if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) 300 if (const IdentifierInfo *II = ND->getIdentifier()) { 301 StringRef Name = II->getName(); 302 if (Name.size() >= 2 && Name.front() == '_' && 303 (Name[1] == '_' || isUppercase(Name[1]))) 304 return true; 305 } 306 307 return DC->isStdNamespace(); 308 } 309 310 // Returns true if the given Record decl is a form of `GSLOwner<Pointer>` 311 // type, e.g. std::vector<string_view>, std::optional<string_view>. 312 static bool isContainerOfPointer(const RecordDecl *Container) { 313 if (const auto *CTSD = 314 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container)) { 315 if (!CTSD->hasAttr<OwnerAttr>()) // Container must be a GSL owner type. 316 return false; 317 const auto &TAs = CTSD->getTemplateArgs(); 318 return TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type && 319 isPointerLikeType(TAs[0].getAsType()); 320 } 321 return false; 322 } 323 static bool isContainerOfOwner(const RecordDecl *Container) { 324 const auto *CTSD = 325 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container); 326 if (!CTSD) 327 return false; 328 if (!CTSD->hasAttr<OwnerAttr>()) // Container must be a GSL owner type. 329 return false; 330 const auto &TAs = CTSD->getTemplateArgs(); 331 return TAs.size() > 0 && TAs[0].getKind() == TemplateArgument::Type && 332 isRecordWithAttr<OwnerAttr>(TAs[0].getAsType()); 333 } 334 335 // Returns true if the given Record is `std::initializer_list<pointer>`. 336 static bool isStdInitializerListOfPointer(const RecordDecl *RD) { 337 if (const auto *CTSD = 338 dyn_cast_if_present<ClassTemplateSpecializationDecl>(RD)) { 339 const auto &TAs = CTSD->getTemplateArgs(); 340 return isInStlNamespace(RD) && RD->getIdentifier() && 341 RD->getName() == "initializer_list" && TAs.size() > 0 && 342 TAs[0].getKind() == TemplateArgument::Type && 343 isPointerLikeType(TAs[0].getAsType()); 344 } 345 return false; 346 } 347 348 static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) { 349 if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee)) 350 if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()) && 351 Callee->getParent()->hasAttr<OwnerAttr>()) 352 return true; 353 if (!isInStlNamespace(Callee->getParent())) 354 return false; 355 if (!isRecordWithAttr<PointerAttr>( 356 Callee->getFunctionObjectParameterType()) && 357 !isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType())) 358 return false; 359 if (isPointerLikeType(Callee->getReturnType())) { 360 if (!Callee->getIdentifier()) 361 return false; 362 return llvm::StringSwitch<bool>(Callee->getName()) 363 .Cases("begin", "rbegin", "cbegin", "crbegin", true) 364 .Cases("end", "rend", "cend", "crend", true) 365 .Cases("c_str", "data", "get", true) 366 // Map and set types. 367 .Cases("find", "equal_range", "lower_bound", "upper_bound", true) 368 .Default(false); 369 } 370 if (Callee->getReturnType()->isReferenceType()) { 371 if (!Callee->getIdentifier()) { 372 auto OO = Callee->getOverloadedOperator(); 373 if (!Callee->getParent()->hasAttr<OwnerAttr>()) 374 return false; 375 return OO == OverloadedOperatorKind::OO_Subscript || 376 OO == OverloadedOperatorKind::OO_Star; 377 } 378 return llvm::StringSwitch<bool>(Callee->getName()) 379 .Cases("front", "back", "at", "top", "value", true) 380 .Default(false); 381 } 382 return false; 383 } 384 385 static bool shouldTrackFirstArgument(const FunctionDecl *FD) { 386 if (!FD->getIdentifier() || FD->getNumParams() != 1) 387 return false; 388 const auto *RD = FD->getParamDecl(0)->getType()->getPointeeCXXRecordDecl(); 389 if (!FD->isInStdNamespace() || !RD || !RD->isInStdNamespace()) 390 return false; 391 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>()) 392 return false; 393 if (FD->getReturnType()->isPointerType() || 394 isRecordWithAttr<PointerAttr>(FD->getReturnType())) { 395 return llvm::StringSwitch<bool>(FD->getName()) 396 .Cases("begin", "rbegin", "cbegin", "crbegin", true) 397 .Cases("end", "rend", "cend", "crend", true) 398 .Case("data", true) 399 .Default(false); 400 } 401 if (FD->getReturnType()->isReferenceType()) { 402 return llvm::StringSwitch<bool>(FD->getName()) 403 .Cases("get", "any_cast", true) 404 .Default(false); 405 } 406 return false; 407 } 408 409 // Returns true if the given constructor is a copy-like constructor, such as 410 // `Ctor(Owner<U>&&)` or `Ctor(const Owner<U>&)`. 411 static bool isCopyLikeConstructor(const CXXConstructorDecl *Ctor) { 412 if (!Ctor || Ctor->param_size() != 1) 413 return false; 414 const auto *ParamRefType = 415 Ctor->getParamDecl(0)->getType()->getAs<ReferenceType>(); 416 if (!ParamRefType) 417 return false; 418 419 // Check if the first parameter type is "Owner<U>". 420 if (const auto *TST = 421 ParamRefType->getPointeeType()->getAs<TemplateSpecializationType>()) 422 return TST->getTemplateName() 423 .getAsTemplateDecl() 424 ->getTemplatedDecl() 425 ->hasAttr<OwnerAttr>(); 426 return false; 427 } 428 429 // Returns true if we should perform the GSL analysis on the first argument for 430 // the given constructor. 431 static bool 432 shouldTrackFirstArgumentForConstructor(const CXXConstructExpr *Ctor) { 433 const auto *LHSRecordDecl = Ctor->getConstructor()->getParent(); 434 435 // Case 1, construct a GSL pointer, e.g. std::string_view 436 // Always inspect when LHS is a pointer. 437 if (LHSRecordDecl->hasAttr<PointerAttr>()) 438 return true; 439 440 if (Ctor->getConstructor()->param_empty() || 441 !isContainerOfPointer(LHSRecordDecl)) 442 return false; 443 444 // Now, the LHS is an Owner<Pointer> type, e.g., std::vector<string_view>. 445 // 446 // At a high level, we cannot precisely determine what the nested pointer 447 // owns. However, by analyzing the RHS owner type, we can use heuristics to 448 // infer ownership information. These heuristics are designed to be 449 // conservative, minimizing false positives while still providing meaningful 450 // diagnostics. 451 // 452 // While this inference isn't perfect, it helps catch common use-after-free 453 // patterns. 454 auto RHSArgType = Ctor->getArg(0)->getType(); 455 const auto *RHSRD = RHSArgType->getAsRecordDecl(); 456 // LHS is constructed from an intializer_list. 457 // 458 // std::initializer_list is a proxy object that provides access to the backing 459 // array. We perform analysis on it to determine if there are any dangling 460 // temporaries in the backing array. 461 // E.g. std::vector<string_view> abc = {string()}; 462 if (isStdInitializerListOfPointer(RHSRD)) 463 return true; 464 465 // RHS must be an owner. 466 if (!isRecordWithAttr<OwnerAttr>(RHSArgType)) 467 return false; 468 469 // Bail out if the RHS is Owner<Pointer>. 470 // 471 // We cannot reliably determine what the LHS nested pointer owns -- it could 472 // be the entire RHS or the nested pointer in RHS. To avoid false positives, 473 // we skip this case, such as: 474 // std::stack<std::string_view> s(std::deque<std::string_view>{}); 475 // 476 // TODO: this also has a false negative, it doesn't catch the case like: 477 // std::optional<span<int*>> os = std::vector<int*>{} 478 if (isContainerOfPointer(RHSRD)) 479 return false; 480 481 // Assume that the nested Pointer is constructed from the nested Owner. 482 // E.g. std::optional<string_view> sv = std::optional<string>(s); 483 if (isContainerOfOwner(RHSRD)) 484 return true; 485 486 // Now, the LHS is an Owner<Pointer> and the RHS is an Owner<X>, where X is 487 // neither an `Owner` nor a `Pointer`. 488 // 489 // Use the constructor's signature as a hint. If it is a copy-like constructor 490 // `Owner1<Pointer>(Owner2<X>&&)`, we assume that the nested pointer is 491 // constructed from X. In such cases, we do not diagnose, as `X` is not an 492 // owner, e.g. 493 // std::optional<string_view> sv = std::optional<Foo>(); 494 if (const auto *PrimaryCtorTemplate = 495 Ctor->getConstructor()->getPrimaryTemplate(); 496 PrimaryCtorTemplate && 497 isCopyLikeConstructor(dyn_cast_if_present<CXXConstructorDecl>( 498 PrimaryCtorTemplate->getTemplatedDecl()))) { 499 return false; 500 } 501 // Assume that the nested pointer is constructed from the whole RHS. 502 // E.g. optional<string_view> s = std::string(); 503 return true; 504 } 505 506 // Return true if this is an "normal" assignment operator. 507 // We assume that a normal assignment operator always returns *this, that is, 508 // an lvalue reference that is the same type as the implicit object parameter 509 // (or the LHS for a non-member operator$=). 510 static bool isNormalAssignmentOperator(const FunctionDecl *FD) { 511 OverloadedOperatorKind OO = FD->getDeclName().getCXXOverloadedOperator(); 512 if (OO == OO_Equal || isCompoundAssignmentOperator(OO)) { 513 QualType RetT = FD->getReturnType(); 514 if (RetT->isLValueReferenceType()) { 515 ASTContext &Ctx = FD->getASTContext(); 516 QualType LHST; 517 auto *MD = dyn_cast<CXXMethodDecl>(FD); 518 if (MD && MD->isCXXInstanceMember()) 519 LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType()); 520 else 521 LHST = FD->getParamDecl(0)->getType(); 522 if (Ctx.hasSameType(RetT, LHST)) 523 return true; 524 } 525 } 526 return false; 527 } 528 529 static const FunctionDecl * 530 getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD) { 531 return FD != nullptr ? FD->getMostRecentDecl() : nullptr; 532 } 533 534 static const CXXMethodDecl * 535 getDeclWithMergedLifetimeBoundAttrs(const CXXMethodDecl *CMD) { 536 const FunctionDecl *FD = CMD; 537 return cast_if_present<CXXMethodDecl>( 538 getDeclWithMergedLifetimeBoundAttrs(FD)); 539 } 540 541 bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) { 542 FD = getDeclWithMergedLifetimeBoundAttrs(FD); 543 const TypeSourceInfo *TSI = FD->getTypeSourceInfo(); 544 if (!TSI) 545 return false; 546 // Don't declare this variable in the second operand of the for-statement; 547 // GCC miscompiles that by ending its lifetime before evaluating the 548 // third operand. See gcc.gnu.org/PR86769. 549 AttributedTypeLoc ATL; 550 for (TypeLoc TL = TSI->getTypeLoc(); 551 (ATL = TL.getAsAdjusted<AttributedTypeLoc>()); 552 TL = ATL.getModifiedLoc()) { 553 if (ATL.getAttrAs<LifetimeBoundAttr>()) 554 return true; 555 } 556 557 return isNormalAssignmentOperator(FD); 558 } 559 560 // Visit lifetimebound or gsl-pointer arguments. 561 static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call, 562 LocalVisitor Visit) { 563 const FunctionDecl *Callee; 564 ArrayRef<Expr *> Args; 565 566 if (auto *CE = dyn_cast<CallExpr>(Call)) { 567 Callee = CE->getDirectCallee(); 568 Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs()); 569 } else { 570 auto *CCE = cast<CXXConstructExpr>(Call); 571 Callee = CCE->getConstructor(); 572 Args = llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs()); 573 } 574 if (!Callee) 575 return; 576 577 bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored( 578 diag::warn_dangling_lifetime_pointer, SourceLocation()); 579 Expr *ObjectArg = nullptr; 580 if (isa<CXXOperatorCallExpr>(Call) && Callee->isCXXInstanceMember()) { 581 ObjectArg = Args[0]; 582 Args = Args.slice(1); 583 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) { 584 ObjectArg = MCE->getImplicitObjectArgument(); 585 } 586 587 auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) { 588 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D}); 589 if (Arg->isGLValue()) 590 visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding, 591 Visit); 592 else 593 visitLocalsRetainedByInitializer(Path, Arg, Visit, true); 594 Path.pop_back(); 595 }; 596 auto VisitGSLPointerArg = [&](const FunctionDecl *Callee, Expr *Arg) { 597 auto ReturnType = Callee->getReturnType(); 598 599 // Once we initialized a value with a non gsl-owner reference, it can no 600 // longer dangle. 601 if (ReturnType->isReferenceType() && 602 !isRecordWithAttr<OwnerAttr>(ReturnType->getPointeeType())) { 603 for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) { 604 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit || 605 PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall) 606 continue; 607 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit || 608 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment) 609 return; 610 break; 611 } 612 } 613 Path.push_back({ReturnType->isReferenceType() 614 ? IndirectLocalPathEntry::GslReferenceInit 615 : IndirectLocalPathEntry::GslPointerInit, 616 Arg, Callee}); 617 if (Arg->isGLValue()) 618 visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding, 619 Visit); 620 else 621 visitLocalsRetainedByInitializer(Path, Arg, Visit, true); 622 Path.pop_back(); 623 }; 624 625 bool CheckCoroCall = false; 626 if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) { 627 CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() && 628 RD->hasAttr<CoroReturnTypeAttr>() && 629 !Callee->hasAttr<CoroDisableLifetimeBoundAttr>(); 630 } 631 632 if (ObjectArg) { 633 bool CheckCoroObjArg = CheckCoroCall; 634 // Coroutine lambda objects with empty capture list are not lifetimebound. 635 if (auto *LE = dyn_cast<LambdaExpr>(ObjectArg->IgnoreImplicit()); 636 LE && LE->captures().empty()) 637 CheckCoroObjArg = false; 638 // Allow `get_return_object()` as the object param (__promise) is not 639 // lifetimebound. 640 if (Sema::CanBeGetReturnObject(Callee)) 641 CheckCoroObjArg = false; 642 if (implicitObjectParamIsLifetimeBound(Callee) || CheckCoroObjArg) 643 VisitLifetimeBoundArg(Callee, ObjectArg); 644 else if (EnableGSLAnalysis) { 645 if (auto *CME = dyn_cast<CXXMethodDecl>(Callee); 646 CME && shouldTrackImplicitObjectArg(CME)) 647 VisitGSLPointerArg(Callee, ObjectArg); 648 } 649 } 650 651 const FunctionDecl *CanonCallee = getDeclWithMergedLifetimeBoundAttrs(Callee); 652 unsigned NP = std::min(Callee->getNumParams(), CanonCallee->getNumParams()); 653 for (unsigned I = 0, N = std::min<unsigned>(NP, Args.size()); I != N; ++I) { 654 Expr *Arg = Args[I]; 655 RevertToOldSizeRAII RAII(Path); 656 if (auto *DAE = dyn_cast<CXXDefaultArgExpr>(Arg)) { 657 Path.push_back( 658 {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()}); 659 Arg = DAE->getExpr(); 660 } 661 if (CheckCoroCall || 662 CanonCallee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>()) 663 VisitLifetimeBoundArg(CanonCallee->getParamDecl(I), Arg); 664 else if (const auto *CaptureAttr = 665 CanonCallee->getParamDecl(I)->getAttr<LifetimeCaptureByAttr>(); 666 CaptureAttr && isa<CXXConstructorDecl>(CanonCallee) && 667 llvm::any_of(CaptureAttr->params(), [](int ArgIdx) { 668 return ArgIdx == LifetimeCaptureByAttr::THIS; 669 })) 670 // `lifetime_capture_by(this)` in a class constructor has the same 671 // semantics as `lifetimebound`: 672 // 673 // struct Foo { 674 // const int& a; 675 // // Equivalent to Foo(const int& t [[clang::lifetimebound]]) 676 // Foo(const int& t [[clang::lifetime_capture_by(this)]]) : a(t) {} 677 // }; 678 // 679 // In the implementation, `lifetime_capture_by` is treated as an alias for 680 // `lifetimebound` and shares the same code path. This implies the emitted 681 // diagnostics will be emitted under `-Wdangling`, not 682 // `-Wdangling-capture`. 683 VisitLifetimeBoundArg(CanonCallee->getParamDecl(I), Arg); 684 else if (EnableGSLAnalysis && I == 0) { 685 // Perform GSL analysis for the first argument 686 if (shouldTrackFirstArgument(CanonCallee)) { 687 VisitGSLPointerArg(CanonCallee, Arg); 688 } else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Call); 689 Ctor && shouldTrackFirstArgumentForConstructor(Ctor)) { 690 VisitGSLPointerArg(Ctor->getConstructor(), Arg); 691 } 692 } 693 } 694 } 695 696 /// Visit the locals that would be reachable through a reference bound to the 697 /// glvalue expression \c Init. 698 static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, 699 Expr *Init, ReferenceKind RK, 700 LocalVisitor Visit) { 701 RevertToOldSizeRAII RAII(Path); 702 703 // Walk past any constructs which we can lifetime-extend across. 704 Expr *Old; 705 do { 706 Old = Init; 707 708 if (auto *FE = dyn_cast<FullExpr>(Init)) 709 Init = FE->getSubExpr(); 710 711 if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { 712 // If this is just redundant braces around an initializer, step over it. 713 if (ILE->isTransparent()) 714 Init = ILE->getInit(0); 715 } 716 717 if (MemberExpr *ME = dyn_cast<MemberExpr>(Init->IgnoreImpCasts())) 718 Path.push_back( 719 {IndirectLocalPathEntry::MemberExpr, ME, ME->getMemberDecl()}); 720 // Step over any subobject adjustments; we may have a materialized 721 // temporary inside them. 722 Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments()); 723 724 // Per current approach for DR1376, look through casts to reference type 725 // when performing lifetime extension. 726 if (CastExpr *CE = dyn_cast<CastExpr>(Init)) 727 if (CE->getSubExpr()->isGLValue()) 728 Init = CE->getSubExpr(); 729 730 // Per the current approach for DR1299, look through array element access 731 // on array glvalues when performing lifetime extension. 732 if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init)) { 733 Init = ASE->getBase(); 734 auto *ICE = dyn_cast<ImplicitCastExpr>(Init); 735 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay) 736 Init = ICE->getSubExpr(); 737 else 738 // We can't lifetime extend through this but we might still find some 739 // retained temporaries. 740 return visitLocalsRetainedByInitializer(Path, Init, Visit, true); 741 } 742 743 // Step into CXXDefaultInitExprs so we can diagnose cases where a 744 // constructor inherits one as an implicit mem-initializer. 745 if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) { 746 Path.push_back( 747 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()}); 748 Init = DIE->getExpr(); 749 } 750 } while (Init != Old); 751 752 if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) { 753 if (Visit(Path, Local(MTE), RK)) 754 visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), Visit, true); 755 } 756 757 if (auto *M = dyn_cast<MemberExpr>(Init)) { 758 // Lifetime of a non-reference type field is same as base object. 759 if (auto *F = dyn_cast<FieldDecl>(M->getMemberDecl()); 760 F && !F->getType()->isReferenceType()) 761 visitLocalsRetainedByInitializer(Path, M->getBase(), Visit, true); 762 } 763 764 if (isa<CallExpr>(Init)) 765 return visitFunctionCallArguments(Path, Init, Visit); 766 767 switch (Init->getStmtClass()) { 768 case Stmt::DeclRefExprClass: { 769 // If we find the name of a local non-reference parameter, we could have a 770 // lifetime problem. 771 auto *DRE = cast<DeclRefExpr>(Init); 772 auto *VD = dyn_cast<VarDecl>(DRE->getDecl()); 773 if (VD && VD->hasLocalStorage() && 774 !DRE->refersToEnclosingVariableOrCapture()) { 775 if (!VD->getType()->isReferenceType()) { 776 Visit(Path, Local(DRE), RK); 777 } else if (isa<ParmVarDecl>(DRE->getDecl())) { 778 // The lifetime of a reference parameter is unknown; assume it's OK 779 // for now. 780 break; 781 } else if (VD->getInit() && !isVarOnPath(Path, VD)) { 782 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD}); 783 visitLocalsRetainedByReferenceBinding(Path, VD->getInit(), 784 RK_ReferenceBinding, Visit); 785 } 786 } 787 break; 788 } 789 790 case Stmt::UnaryOperatorClass: { 791 // The only unary operator that make sense to handle here 792 // is Deref. All others don't resolve to a "name." This includes 793 // handling all sorts of rvalues passed to a unary operator. 794 const UnaryOperator *U = cast<UnaryOperator>(Init); 795 if (U->getOpcode() == UO_Deref) 796 visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true); 797 break; 798 } 799 800 case Stmt::ArraySectionExprClass: { 801 visitLocalsRetainedByInitializer( 802 Path, cast<ArraySectionExpr>(Init)->getBase(), Visit, true); 803 break; 804 } 805 806 case Stmt::ConditionalOperatorClass: 807 case Stmt::BinaryConditionalOperatorClass: { 808 auto *C = cast<AbstractConditionalOperator>(Init); 809 if (!C->getTrueExpr()->getType()->isVoidType()) 810 visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit); 811 if (!C->getFalseExpr()->getType()->isVoidType()) 812 visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit); 813 break; 814 } 815 816 case Stmt::CompoundLiteralExprClass: { 817 if (auto *CLE = dyn_cast<CompoundLiteralExpr>(Init)) { 818 if (!CLE->isFileScope()) 819 Visit(Path, Local(CLE), RK); 820 } 821 break; 822 } 823 824 // FIXME: Visit the left-hand side of an -> or ->*. 825 826 default: 827 break; 828 } 829 } 830 831 /// Visit the locals that would be reachable through an object initialized by 832 /// the prvalue expression \c Init. 833 static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, 834 Expr *Init, LocalVisitor Visit, 835 bool RevisitSubinits) { 836 RevertToOldSizeRAII RAII(Path); 837 838 Expr *Old; 839 do { 840 Old = Init; 841 842 // Step into CXXDefaultInitExprs so we can diagnose cases where a 843 // constructor inherits one as an implicit mem-initializer. 844 if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) { 845 Path.push_back( 846 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()}); 847 Init = DIE->getExpr(); 848 } 849 850 if (auto *FE = dyn_cast<FullExpr>(Init)) 851 Init = FE->getSubExpr(); 852 853 // Dig out the expression which constructs the extended temporary. 854 Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments()); 855 856 if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init)) 857 Init = BTE->getSubExpr(); 858 859 Init = Init->IgnoreParens(); 860 861 // Step over value-preserving rvalue casts. 862 if (auto *CE = dyn_cast<CastExpr>(Init)) { 863 switch (CE->getCastKind()) { 864 case CK_LValueToRValue: 865 // If we can match the lvalue to a const object, we can look at its 866 // initializer. 867 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE}); 868 return visitLocalsRetainedByReferenceBinding( 869 Path, Init, RK_ReferenceBinding, 870 [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool { 871 if (auto *DRE = dyn_cast<DeclRefExpr>(L)) { 872 auto *VD = dyn_cast<VarDecl>(DRE->getDecl()); 873 if (VD && VD->getType().isConstQualified() && VD->getInit() && 874 !isVarOnPath(Path, VD)) { 875 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD}); 876 visitLocalsRetainedByInitializer(Path, VD->getInit(), Visit, 877 true); 878 } 879 } else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) { 880 if (MTE->getType().isConstQualified()) 881 visitLocalsRetainedByInitializer(Path, MTE->getSubExpr(), 882 Visit, true); 883 } 884 return false; 885 }); 886 887 // We assume that objects can be retained by pointers cast to integers, 888 // but not if the integer is cast to floating-point type or to _Complex. 889 // We assume that casts to 'bool' do not preserve enough information to 890 // retain a local object. 891 case CK_NoOp: 892 case CK_BitCast: 893 case CK_BaseToDerived: 894 case CK_DerivedToBase: 895 case CK_UncheckedDerivedToBase: 896 case CK_Dynamic: 897 case CK_ToUnion: 898 case CK_UserDefinedConversion: 899 case CK_ConstructorConversion: 900 case CK_IntegralToPointer: 901 case CK_PointerToIntegral: 902 case CK_VectorSplat: 903 case CK_IntegralCast: 904 case CK_CPointerToObjCPointerCast: 905 case CK_BlockPointerToObjCPointerCast: 906 case CK_AnyPointerToBlockPointerCast: 907 case CK_AddressSpaceConversion: 908 break; 909 910 case CK_ArrayToPointerDecay: 911 // Model array-to-pointer decay as taking the address of the array 912 // lvalue. 913 Path.push_back({IndirectLocalPathEntry::AddressOf, CE}); 914 return visitLocalsRetainedByReferenceBinding( 915 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit); 916 917 default: 918 return; 919 } 920 921 Init = CE->getSubExpr(); 922 } 923 } while (Old != Init); 924 925 // C++17 [dcl.init.list]p6: 926 // initializing an initializer_list object from the array extends the 927 // lifetime of the array exactly like binding a reference to a temporary. 928 if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init)) 929 return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(), 930 RK_StdInitializerList, Visit); 931 932 if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { 933 // We already visited the elements of this initializer list while 934 // performing the initialization. Don't visit them again unless we've 935 // changed the lifetime of the initialized entity. 936 if (!RevisitSubinits) 937 return; 938 939 if (ILE->isTransparent()) 940 return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit, 941 RevisitSubinits); 942 943 if (ILE->getType()->isArrayType()) { 944 for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I) 945 visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit, 946 RevisitSubinits); 947 return; 948 } 949 950 if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) { 951 assert(RD->isAggregate() && "aggregate init on non-aggregate"); 952 953 // If we lifetime-extend a braced initializer which is initializing an 954 // aggregate, and that aggregate contains reference members which are 955 // bound to temporaries, those temporaries are also lifetime-extended. 956 if (RD->isUnion() && ILE->getInitializedFieldInUnion() && 957 ILE->getInitializedFieldInUnion()->getType()->isReferenceType()) 958 visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0), 959 RK_ReferenceBinding, Visit); 960 else { 961 unsigned Index = 0; 962 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index) 963 visitLocalsRetainedByInitializer(Path, ILE->getInit(Index), Visit, 964 RevisitSubinits); 965 for (const auto *I : RD->fields()) { 966 if (Index >= ILE->getNumInits()) 967 break; 968 if (I->isUnnamedBitField()) 969 continue; 970 Expr *SubInit = ILE->getInit(Index); 971 if (I->getType()->isReferenceType()) 972 visitLocalsRetainedByReferenceBinding(Path, SubInit, 973 RK_ReferenceBinding, Visit); 974 else 975 // This might be either aggregate-initialization of a member or 976 // initialization of a std::initializer_list object. Regardless, 977 // we should recursively lifetime-extend that initializer. 978 visitLocalsRetainedByInitializer(Path, SubInit, Visit, 979 RevisitSubinits); 980 ++Index; 981 } 982 } 983 } 984 return; 985 } 986 987 // The lifetime of an init-capture is that of the closure object constructed 988 // by a lambda-expression. 989 if (auto *LE = dyn_cast<LambdaExpr>(Init)) { 990 LambdaExpr::capture_iterator CapI = LE->capture_begin(); 991 for (Expr *E : LE->capture_inits()) { 992 assert(CapI != LE->capture_end()); 993 const LambdaCapture &Cap = *CapI++; 994 if (!E) 995 continue; 996 if (Cap.capturesVariable()) 997 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap}); 998 if (E->isGLValue()) 999 visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding, 1000 Visit); 1001 else 1002 visitLocalsRetainedByInitializer(Path, E, Visit, true); 1003 if (Cap.capturesVariable()) 1004 Path.pop_back(); 1005 } 1006 } 1007 1008 // Assume that a copy or move from a temporary references the same objects 1009 // that the temporary does. 1010 if (auto *CCE = dyn_cast<CXXConstructExpr>(Init)) { 1011 if (CCE->getConstructor()->isCopyOrMoveConstructor()) { 1012 if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) { 1013 Expr *Arg = MTE->getSubExpr(); 1014 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg, 1015 CCE->getConstructor()}); 1016 visitLocalsRetainedByInitializer(Path, Arg, Visit, true); 1017 Path.pop_back(); 1018 } 1019 } 1020 } 1021 1022 if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init)) 1023 return visitFunctionCallArguments(Path, Init, Visit); 1024 1025 if (auto *CPE = dyn_cast<CXXParenListInitExpr>(Init)) { 1026 RevertToOldSizeRAII RAII(Path); 1027 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE}); 1028 for (auto *I : CPE->getInitExprs()) { 1029 if (I->isGLValue()) 1030 visitLocalsRetainedByReferenceBinding(Path, I, RK_ReferenceBinding, 1031 Visit); 1032 else 1033 visitLocalsRetainedByInitializer(Path, I, Visit, true); 1034 } 1035 } 1036 switch (Init->getStmtClass()) { 1037 case Stmt::UnaryOperatorClass: { 1038 auto *UO = cast<UnaryOperator>(Init); 1039 // If the initializer is the address of a local, we could have a lifetime 1040 // problem. 1041 if (UO->getOpcode() == UO_AddrOf) { 1042 // If this is &rvalue, then it's ill-formed and we have already diagnosed 1043 // it. Don't produce a redundant warning about the lifetime of the 1044 // temporary. 1045 if (isa<MaterializeTemporaryExpr>(UO->getSubExpr())) 1046 return; 1047 1048 Path.push_back({IndirectLocalPathEntry::AddressOf, UO}); 1049 visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(), 1050 RK_ReferenceBinding, Visit); 1051 } 1052 break; 1053 } 1054 1055 case Stmt::BinaryOperatorClass: { 1056 // Handle pointer arithmetic. 1057 auto *BO = cast<BinaryOperator>(Init); 1058 BinaryOperatorKind BOK = BO->getOpcode(); 1059 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub)) 1060 break; 1061 1062 if (BO->getLHS()->getType()->isPointerType()) 1063 visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true); 1064 else if (BO->getRHS()->getType()->isPointerType()) 1065 visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true); 1066 break; 1067 } 1068 1069 case Stmt::ConditionalOperatorClass: 1070 case Stmt::BinaryConditionalOperatorClass: { 1071 auto *C = cast<AbstractConditionalOperator>(Init); 1072 // In C++, we can have a throw-expression operand, which has 'void' type 1073 // and isn't interesting from a lifetime perspective. 1074 if (!C->getTrueExpr()->getType()->isVoidType()) 1075 visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true); 1076 if (!C->getFalseExpr()->getType()->isVoidType()) 1077 visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true); 1078 break; 1079 } 1080 1081 case Stmt::BlockExprClass: 1082 if (cast<BlockExpr>(Init)->getBlockDecl()->hasCaptures()) { 1083 // This is a local block, whose lifetime is that of the function. 1084 Visit(Path, Local(cast<BlockExpr>(Init)), RK_ReferenceBinding); 1085 } 1086 break; 1087 1088 case Stmt::AddrLabelExprClass: 1089 // We want to warn if the address of a label would escape the function. 1090 Visit(Path, Local(cast<AddrLabelExpr>(Init)), RK_ReferenceBinding); 1091 break; 1092 1093 default: 1094 break; 1095 } 1096 } 1097 1098 /// Whether a path to an object supports lifetime extension. 1099 enum PathLifetimeKind { 1100 /// Lifetime-extend along this path. 1101 Extend, 1102 /// Do not lifetime extend along this path. 1103 NoExtend 1104 }; 1105 1106 /// Determine whether this is an indirect path to a temporary that we are 1107 /// supposed to lifetime-extend along. 1108 static PathLifetimeKind 1109 shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { 1110 for (auto Elem : Path) { 1111 if (Elem.Kind == IndirectLocalPathEntry::MemberExpr || 1112 Elem.Kind == IndirectLocalPathEntry::LambdaCaptureInit) 1113 continue; 1114 return Elem.Kind == IndirectLocalPathEntry::DefaultInit 1115 ? PathLifetimeKind::Extend 1116 : PathLifetimeKind::NoExtend; 1117 } 1118 return PathLifetimeKind::Extend; 1119 } 1120 1121 /// Find the range for the first interesting entry in the path at or after I. 1122 static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I, 1123 Expr *E) { 1124 for (unsigned N = Path.size(); I != N; ++I) { 1125 switch (Path[I].Kind) { 1126 case IndirectLocalPathEntry::AddressOf: 1127 case IndirectLocalPathEntry::LValToRVal: 1128 case IndirectLocalPathEntry::LifetimeBoundCall: 1129 case IndirectLocalPathEntry::TemporaryCopy: 1130 case IndirectLocalPathEntry::GslReferenceInit: 1131 case IndirectLocalPathEntry::GslPointerInit: 1132 case IndirectLocalPathEntry::GslPointerAssignment: 1133 case IndirectLocalPathEntry::ParenAggInit: 1134 case IndirectLocalPathEntry::MemberExpr: 1135 // These exist primarily to mark the path as not permitting or 1136 // supporting lifetime extension. 1137 break; 1138 1139 case IndirectLocalPathEntry::VarInit: 1140 if (cast<VarDecl>(Path[I].D)->isImplicit()) 1141 return SourceRange(); 1142 [[fallthrough]]; 1143 case IndirectLocalPathEntry::DefaultInit: 1144 return Path[I].E->getSourceRange(); 1145 1146 case IndirectLocalPathEntry::LambdaCaptureInit: 1147 if (!Path[I].Capture->capturesVariable()) 1148 continue; 1149 return Path[I].E->getSourceRange(); 1150 1151 case IndirectLocalPathEntry::DefaultArg: 1152 return cast<CXXDefaultArgExpr>(Path[I].E)->getUsedLocation(); 1153 } 1154 } 1155 return E->getSourceRange(); 1156 } 1157 1158 static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path) { 1159 for (const auto &It : llvm::reverse(Path)) { 1160 switch (It.Kind) { 1161 case IndirectLocalPathEntry::VarInit: 1162 case IndirectLocalPathEntry::AddressOf: 1163 case IndirectLocalPathEntry::LifetimeBoundCall: 1164 case IndirectLocalPathEntry::MemberExpr: 1165 continue; 1166 case IndirectLocalPathEntry::GslPointerInit: 1167 case IndirectLocalPathEntry::GslReferenceInit: 1168 case IndirectLocalPathEntry::GslPointerAssignment: 1169 return true; 1170 default: 1171 return false; 1172 } 1173 } 1174 return false; 1175 } 1176 // Result of analyzing the Path for GSLPointer. 1177 enum AnalysisResult { 1178 // Path does not correspond to a GSLPointer. 1179 NotGSLPointer, 1180 1181 // A relevant case was identified. 1182 Report, 1183 // Stop the entire traversal. 1184 Abandon, 1185 // Skip this step and continue traversing inner AST nodes. 1186 Skip, 1187 }; 1188 // Analyze cases where a GSLPointer is initialized or assigned from a 1189 // temporary owner object. 1190 static AnalysisResult analyzePathForGSLPointer(const IndirectLocalPath &Path, 1191 Local L, LifetimeKind LK) { 1192 if (!pathOnlyHandlesGslPointer(Path)) 1193 return NotGSLPointer; 1194 1195 // At this point, Path represents a series of operations involving a 1196 // GSLPointer, either in the process of initialization or assignment. 1197 1198 // Process temporary base objects for MemberExpr cases, e.g. Temp().field. 1199 for (const auto &E : Path) { 1200 if (E.Kind == IndirectLocalPathEntry::MemberExpr) { 1201 // Avoid interfering with the local base object. 1202 if (pathContainsInit(Path)) 1203 return Abandon; 1204 1205 // We are not interested in the temporary base objects of gsl Pointers: 1206 // auto p1 = Temp().ptr; // Here p1 might not dangle. 1207 // However, we want to diagnose for gsl owner fields: 1208 // auto p2 = Temp().owner; // Here p2 is dangling. 1209 if (const auto *FD = llvm::dyn_cast_or_null<FieldDecl>(E.D); 1210 FD && !FD->getType()->isReferenceType() && 1211 isRecordWithAttr<OwnerAttr>(FD->getType()) && 1212 LK != LK_MemInitializer) { 1213 return Report; 1214 } 1215 return Abandon; 1216 } 1217 } 1218 1219 // Note: A LifetimeBoundCall can appear interleaved in this sequence. 1220 // For example: 1221 // const std::string& Ref(const std::string& a [[clang::lifetimebound]]); 1222 // string_view abc = Ref(std::string()); 1223 // The "Path" is [GSLPointerInit, LifetimeboundCall], where "L" is the 1224 // temporary "std::string()" object. We need to check the return type of the 1225 // function with the lifetimebound attribute. 1226 if (Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) { 1227 // The lifetimebound applies to the implicit object parameter of a method. 1228 const FunctionDecl *FD = 1229 llvm::dyn_cast_or_null<FunctionDecl>(Path.back().D); 1230 // The lifetimebound applies to a function parameter. 1231 if (const auto *PD = llvm::dyn_cast<ParmVarDecl>(Path.back().D)) 1232 FD = llvm::dyn_cast<FunctionDecl>(PD->getDeclContext()); 1233 1234 if (isa_and_present<CXXConstructorDecl>(FD)) { 1235 // Constructor case: the parameter is annotated with lifetimebound 1236 // e.g., GSLPointer(const S& s [[clang::lifetimebound]]) 1237 // We still respect this case even the type S is not an owner. 1238 return Report; 1239 } 1240 // Check the return type, e.g. 1241 // const GSLOwner& func(const Foo& foo [[clang::lifetimebound]]) 1242 // GSLPointer func(const Foo& foo [[clang::lifetimebound]]) 1243 if (FD && 1244 ((FD->getReturnType()->isReferenceType() && 1245 isRecordWithAttr<OwnerAttr>(FD->getReturnType()->getPointeeType())) || 1246 isPointerLikeType(FD->getReturnType()))) 1247 return Report; 1248 1249 return Abandon; 1250 } 1251 1252 if (isa<DeclRefExpr>(L)) { 1253 // We do not want to follow the references when returning a pointer 1254 // originating from a local owner to avoid the following false positive: 1255 // int &p = *localUniquePtr; 1256 // someContainer.add(std::move(localUniquePtr)); 1257 // return p; 1258 if (!pathContainsInit(Path) && isRecordWithAttr<OwnerAttr>(L->getType())) 1259 return Report; 1260 return Abandon; 1261 } 1262 1263 // The GSLPointer is from a temporary object. 1264 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L); 1265 1266 bool IsGslPtrValueFromGslTempOwner = 1267 MTE && !MTE->getExtendingDecl() && 1268 isRecordWithAttr<OwnerAttr>(MTE->getType()); 1269 // Skipping a chain of initializing gsl::Pointer annotated objects. 1270 // We are looking only for the final source to find out if it was 1271 // a local or temporary owner or the address of a local 1272 // variable/param. 1273 if (!IsGslPtrValueFromGslTempOwner) 1274 return Skip; 1275 return Report; 1276 } 1277 1278 static bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD) { 1279 CMD = getDeclWithMergedLifetimeBoundAttrs(CMD); 1280 return CMD && isNormalAssignmentOperator(CMD) && CMD->param_size() == 1 && 1281 CMD->getParamDecl(0)->hasAttr<LifetimeBoundAttr>(); 1282 } 1283 1284 static bool shouldRunGSLAssignmentAnalysis(const Sema &SemaRef, 1285 const AssignedEntity &Entity) { 1286 bool EnableGSLAssignmentWarnings = !SemaRef.getDiagnostics().isIgnored( 1287 diag::warn_dangling_lifetime_pointer_assignment, SourceLocation()); 1288 return (EnableGSLAssignmentWarnings && 1289 (isRecordWithAttr<PointerAttr>(Entity.LHS->getType()) || 1290 isAssignmentOperatorLifetimeBound(Entity.AssignmentOperator))); 1291 } 1292 1293 static void 1294 checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, 1295 const InitializedEntity *ExtendingEntity, LifetimeKind LK, 1296 const AssignedEntity *AEntity, 1297 const CapturingEntity *CapEntity, Expr *Init) { 1298 assert(!AEntity || LK == LK_Assignment); 1299 assert(!CapEntity || LK == LK_LifetimeCapture); 1300 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture)); 1301 // If this entity doesn't have an interesting lifetime, don't bother looking 1302 // for temporaries within its initializer. 1303 if (LK == LK_FullExpression) 1304 return; 1305 1306 // FIXME: consider moving the TemporaryVisitor and visitLocalsRetained* 1307 // functions to a dedicated class. 1308 auto TemporaryVisitor = [&](const IndirectLocalPath &Path, Local L, 1309 ReferenceKind RK) -> bool { 1310 SourceRange DiagRange = nextPathEntryRange(Path, 0, L); 1311 SourceLocation DiagLoc = DiagRange.getBegin(); 1312 1313 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L); 1314 1315 bool IsGslPtrValueFromGslTempOwner = true; 1316 switch (analyzePathForGSLPointer(Path, L, LK)) { 1317 case Abandon: 1318 return false; 1319 case Skip: 1320 return true; 1321 case NotGSLPointer: 1322 IsGslPtrValueFromGslTempOwner = false; 1323 LLVM_FALLTHROUGH; 1324 case Report: 1325 break; 1326 } 1327 1328 switch (LK) { 1329 case LK_FullExpression: 1330 llvm_unreachable("already handled this"); 1331 1332 case LK_Extended: { 1333 if (!MTE) { 1334 // The initialized entity has lifetime beyond the full-expression, 1335 // and the local entity does too, so don't warn. 1336 // 1337 // FIXME: We should consider warning if a static / thread storage 1338 // duration variable retains an automatic storage duration local. 1339 return false; 1340 } 1341 1342 if (IsGslPtrValueFromGslTempOwner && DiagLoc.isValid()) { 1343 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer) 1344 << DiagRange; 1345 return false; 1346 } 1347 1348 switch (shouldLifetimeExtendThroughPath(Path)) { 1349 case PathLifetimeKind::Extend: 1350 // Update the storage duration of the materialized temporary. 1351 // FIXME: Rebuild the expression instead of mutating it. 1352 MTE->setExtendingDecl(ExtendingEntity->getDecl(), 1353 ExtendingEntity->allocateManglingNumber()); 1354 // Also visit the temporaries lifetime-extended by this initializer. 1355 return true; 1356 1357 case PathLifetimeKind::NoExtend: 1358 // If the path goes through the initialization of a variable or field, 1359 // it can't possibly reach a temporary created in this full-expression. 1360 // We will have already diagnosed any problems with the initializer. 1361 if (pathContainsInit(Path)) 1362 return false; 1363 1364 SemaRef.Diag(DiagLoc, diag::warn_dangling_variable) 1365 << RK << !InitEntity->getParent() 1366 << ExtendingEntity->getDecl()->isImplicit() 1367 << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange; 1368 break; 1369 } 1370 break; 1371 } 1372 1373 case LK_LifetimeCapture: { 1374 // The captured entity has lifetime beyond the full-expression, 1375 // and the capturing entity does too, so don't warn. 1376 if (!MTE) 1377 return false; 1378 if (CapEntity->Entity) 1379 SemaRef.Diag(DiagLoc, diag::warn_dangling_reference_captured) 1380 << CapEntity->Entity << DiagRange; 1381 else 1382 SemaRef.Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown) 1383 << DiagRange; 1384 return false; 1385 } 1386 1387 case LK_Assignment: { 1388 if (!MTE || pathContainsInit(Path)) 1389 return false; 1390 if (IsGslPtrValueFromGslTempOwner) 1391 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment) 1392 << AEntity->LHS << DiagRange; 1393 else 1394 SemaRef.Diag(DiagLoc, diag::warn_dangling_pointer_assignment) 1395 << AEntity->LHS->getType()->isPointerType() << AEntity->LHS 1396 << DiagRange; 1397 return false; 1398 } 1399 case LK_MemInitializer: { 1400 if (MTE) { 1401 // Under C++ DR1696, if a mem-initializer (or a default member 1402 // initializer used by the absence of one) would lifetime-extend a 1403 // temporary, the program is ill-formed. 1404 if (auto *ExtendingDecl = 1405 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { 1406 if (IsGslPtrValueFromGslTempOwner) { 1407 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member) 1408 << ExtendingDecl << DiagRange; 1409 SemaRef.Diag(ExtendingDecl->getLocation(), 1410 diag::note_ref_or_ptr_member_declared_here) 1411 << true; 1412 return false; 1413 } 1414 bool IsSubobjectMember = ExtendingEntity != InitEntity; 1415 SemaRef.Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) != 1416 PathLifetimeKind::NoExtend 1417 ? diag::err_dangling_member 1418 : diag::warn_dangling_member) 1419 << ExtendingDecl << IsSubobjectMember << RK << DiagRange; 1420 // Don't bother adding a note pointing to the field if we're inside 1421 // its default member initializer; our primary diagnostic points to 1422 // the same place in that case. 1423 if (Path.empty() || 1424 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) { 1425 SemaRef.Diag(ExtendingDecl->getLocation(), 1426 diag::note_lifetime_extending_member_declared_here) 1427 << RK << IsSubobjectMember; 1428 } 1429 } else { 1430 // We have a mem-initializer but no particular field within it; this 1431 // is either a base class or a delegating initializer directly 1432 // initializing the base-class from something that doesn't live long 1433 // enough. 1434 // 1435 // FIXME: Warn on this. 1436 return false; 1437 } 1438 } else { 1439 // Paths via a default initializer can only occur during error recovery 1440 // (there's no other way that a default initializer can refer to a 1441 // local). Don't produce a bogus warning on those cases. 1442 if (pathContainsInit(Path)) 1443 return false; 1444 1445 auto *DRE = dyn_cast<DeclRefExpr>(L); 1446 // Suppress false positives for code like the one below: 1447 // Ctor(unique_ptr<T> up) : pointer(up.get()), owner(move(up)) {} 1448 // FIXME: move this logic to analyzePathForGSLPointer. 1449 if (DRE && isRecordWithAttr<OwnerAttr>(DRE->getType())) 1450 return false; 1451 1452 auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr; 1453 if (!VD) { 1454 // A member was initialized to a local block. 1455 // FIXME: Warn on this. 1456 return false; 1457 } 1458 1459 if (auto *Member = 1460 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { 1461 bool IsPointer = !Member->getType()->isReferenceType(); 1462 SemaRef.Diag(DiagLoc, 1463 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr 1464 : diag::warn_bind_ref_member_to_parameter) 1465 << Member << VD << isa<ParmVarDecl>(VD) << DiagRange; 1466 SemaRef.Diag(Member->getLocation(), 1467 diag::note_ref_or_ptr_member_declared_here) 1468 << (unsigned)IsPointer; 1469 } 1470 } 1471 break; 1472 } 1473 1474 case LK_New: 1475 if (isa<MaterializeTemporaryExpr>(L)) { 1476 if (IsGslPtrValueFromGslTempOwner) 1477 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer) 1478 << DiagRange; 1479 else 1480 SemaRef.Diag(DiagLoc, RK == RK_ReferenceBinding 1481 ? diag::warn_new_dangling_reference 1482 : diag::warn_new_dangling_initializer_list) 1483 << !InitEntity->getParent() << DiagRange; 1484 } else { 1485 // We can't determine if the allocation outlives the local declaration. 1486 return false; 1487 } 1488 break; 1489 1490 case LK_Return: 1491 case LK_MustTail: 1492 case LK_StmtExprResult: 1493 if (auto *DRE = dyn_cast<DeclRefExpr>(L)) { 1494 // We can't determine if the local variable outlives the statement 1495 // expression. 1496 if (LK == LK_StmtExprResult) 1497 return false; 1498 SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref) 1499 << InitEntity->getType()->isReferenceType() << DRE->getDecl() 1500 << isa<ParmVarDecl>(DRE->getDecl()) << (LK == LK_MustTail) 1501 << DiagRange; 1502 } else if (isa<BlockExpr>(L)) { 1503 SemaRef.Diag(DiagLoc, diag::err_ret_local_block) << DiagRange; 1504 } else if (isa<AddrLabelExpr>(L)) { 1505 // Don't warn when returning a label from a statement expression. 1506 // Leaving the scope doesn't end its lifetime. 1507 if (LK == LK_StmtExprResult) 1508 return false; 1509 SemaRef.Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange; 1510 } else if (auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) { 1511 SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref) 1512 << InitEntity->getType()->isReferenceType() << CLE->getInitializer() 1513 << 2 << (LK == LK_MustTail) << DiagRange; 1514 } else { 1515 // P2748R5: Disallow Binding a Returned Glvalue to a Temporary. 1516 // [stmt.return]/p6: In a function whose return type is a reference, 1517 // other than an invented function for std::is_convertible ([meta.rel]), 1518 // a return statement that binds the returned reference to a temporary 1519 // expression ([class.temporary]) is ill-formed. 1520 if (SemaRef.getLangOpts().CPlusPlus26 && 1521 InitEntity->getType()->isReferenceType()) 1522 SemaRef.Diag(DiagLoc, diag::err_ret_local_temp_ref) 1523 << InitEntity->getType()->isReferenceType() << DiagRange; 1524 else if (LK == LK_MustTail) 1525 SemaRef.Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref) 1526 << InitEntity->getType()->isReferenceType() << DiagRange; 1527 else 1528 SemaRef.Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref) 1529 << InitEntity->getType()->isReferenceType() << DiagRange; 1530 } 1531 break; 1532 } 1533 1534 for (unsigned I = 0; I != Path.size(); ++I) { 1535 auto Elem = Path[I]; 1536 1537 switch (Elem.Kind) { 1538 case IndirectLocalPathEntry::AddressOf: 1539 case IndirectLocalPathEntry::LValToRVal: 1540 case IndirectLocalPathEntry::ParenAggInit: 1541 // These exist primarily to mark the path as not permitting or 1542 // supporting lifetime extension. 1543 break; 1544 1545 case IndirectLocalPathEntry::LifetimeBoundCall: 1546 case IndirectLocalPathEntry::TemporaryCopy: 1547 case IndirectLocalPathEntry::MemberExpr: 1548 case IndirectLocalPathEntry::GslPointerInit: 1549 case IndirectLocalPathEntry::GslReferenceInit: 1550 case IndirectLocalPathEntry::GslPointerAssignment: 1551 // FIXME: Consider adding a note for these. 1552 break; 1553 1554 case IndirectLocalPathEntry::DefaultInit: { 1555 auto *FD = cast<FieldDecl>(Elem.D); 1556 SemaRef.Diag(FD->getLocation(), 1557 diag::note_init_with_default_member_initializer) 1558 << FD << nextPathEntryRange(Path, I + 1, L); 1559 break; 1560 } 1561 1562 case IndirectLocalPathEntry::VarInit: { 1563 const VarDecl *VD = cast<VarDecl>(Elem.D); 1564 SemaRef.Diag(VD->getLocation(), diag::note_local_var_initializer) 1565 << VD->getType()->isReferenceType() << VD->isImplicit() 1566 << VD->getDeclName() << nextPathEntryRange(Path, I + 1, L); 1567 break; 1568 } 1569 1570 case IndirectLocalPathEntry::LambdaCaptureInit: { 1571 if (!Elem.Capture->capturesVariable()) 1572 break; 1573 // FIXME: We can't easily tell apart an init-capture from a nested 1574 // capture of an init-capture. 1575 const ValueDecl *VD = Elem.Capture->getCapturedVar(); 1576 SemaRef.Diag(Elem.Capture->getLocation(), 1577 diag::note_lambda_capture_initializer) 1578 << VD << VD->isInitCapture() << Elem.Capture->isExplicit() 1579 << (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD 1580 << nextPathEntryRange(Path, I + 1, L); 1581 break; 1582 } 1583 1584 case IndirectLocalPathEntry::DefaultArg: { 1585 const auto *DAE = cast<CXXDefaultArgExpr>(Elem.E); 1586 const ParmVarDecl *Param = DAE->getParam(); 1587 SemaRef.Diag(Param->getDefaultArgRange().getBegin(), 1588 diag::note_init_with_default_argument) 1589 << Param << nextPathEntryRange(Path, I + 1, L); 1590 break; 1591 } 1592 } 1593 } 1594 1595 // We didn't lifetime-extend, so don't go any further; we don't need more 1596 // warnings or errors on inner temporaries within this one's initializer. 1597 return false; 1598 }; 1599 1600 llvm::SmallVector<IndirectLocalPathEntry, 8> Path; 1601 switch (LK) { 1602 case LK_Assignment: { 1603 if (shouldRunGSLAssignmentAnalysis(SemaRef, *AEntity)) 1604 Path.push_back( 1605 {isAssignmentOperatorLifetimeBound(AEntity->AssignmentOperator) 1606 ? IndirectLocalPathEntry::LifetimeBoundCall 1607 : IndirectLocalPathEntry::GslPointerAssignment, 1608 Init}); 1609 break; 1610 } 1611 case LK_LifetimeCapture: { 1612 if (isPointerLikeType(Init->getType())) 1613 Path.push_back({IndirectLocalPathEntry::GslPointerInit, Init}); 1614 break; 1615 } 1616 default: 1617 break; 1618 } 1619 1620 if (Init->isGLValue()) 1621 visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding, 1622 TemporaryVisitor); 1623 else 1624 visitLocalsRetainedByInitializer( 1625 Path, Init, TemporaryVisitor, 1626 // Don't revisit the sub inits for the intialization case. 1627 /*RevisitSubinits=*/!InitEntity); 1628 } 1629 1630 void checkInitLifetime(Sema &SemaRef, const InitializedEntity &Entity, 1631 Expr *Init) { 1632 auto LTResult = getEntityLifetime(&Entity); 1633 LifetimeKind LK = LTResult.getInt(); 1634 const InitializedEntity *ExtendingEntity = LTResult.getPointer(); 1635 checkExprLifetimeImpl(SemaRef, &Entity, ExtendingEntity, LK, 1636 /*AEntity=*/nullptr, /*CapEntity=*/nullptr, Init); 1637 } 1638 1639 void checkExprLifetimeMustTailArg(Sema &SemaRef, 1640 const InitializedEntity &Entity, Expr *Init) { 1641 checkExprLifetimeImpl(SemaRef, &Entity, nullptr, LK_MustTail, 1642 /*AEntity=*/nullptr, /*CapEntity=*/nullptr, Init); 1643 } 1644 1645 void checkAssignmentLifetime(Sema &SemaRef, const AssignedEntity &Entity, 1646 Expr *Init) { 1647 bool EnableDanglingPointerAssignment = !SemaRef.getDiagnostics().isIgnored( 1648 diag::warn_dangling_pointer_assignment, SourceLocation()); 1649 bool RunAnalysis = (EnableDanglingPointerAssignment && 1650 Entity.LHS->getType()->isPointerType()) || 1651 shouldRunGSLAssignmentAnalysis(SemaRef, Entity); 1652 1653 if (!RunAnalysis) 1654 return; 1655 1656 checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr, 1657 /*ExtendingEntity=*/nullptr, LK_Assignment, &Entity, 1658 /*CapEntity=*/nullptr, Init); 1659 } 1660 1661 void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity, 1662 Expr *Init) { 1663 if (SemaRef.getDiagnostics().isIgnored(diag::warn_dangling_reference_captured, 1664 SourceLocation()) && 1665 SemaRef.getDiagnostics().isIgnored( 1666 diag::warn_dangling_reference_captured_by_unknown, SourceLocation())) 1667 return; 1668 return checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr, 1669 /*ExtendingEntity=*/nullptr, LK_LifetimeCapture, 1670 /*AEntity=*/nullptr, 1671 /*CapEntity=*/&Entity, Init); 1672 } 1673 1674 } // namespace clang::sema 1675