@@ -535,9 +535,6 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
535535
536536 bool EnableGSLAnalysis = !Callee->getASTContext ().getDiagnostics ().isIgnored (
537537 diag::warn_dangling_lifetime_pointer, SourceLocation ());
538- bool EnableDanglingCapture =
539- !Callee->getASTContext ().getDiagnostics ().isIgnored (
540- diag::warn_dangling_reference_captured, SourceLocation ());
541538 Expr *ObjectArg = nullptr ;
542539 if (isa<CXXOperatorCallExpr>(Call) && Callee->isCXXInstanceMember ()) {
543540 ObjectArg = Args[0 ];
@@ -628,11 +625,23 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
628625 VisitLifetimeBoundArg (Callee->getParamDecl (I), Arg);
629626 else if (const auto *CaptureAttr =
630627 Callee->getParamDecl (I)->getAttr <LifetimeCaptureByAttr>();
631- EnableDanglingCapture && CaptureAttr &&
632- isa<CXXConstructorDecl>(Callee) &&
628+ CaptureAttr && isa<CXXConstructorDecl>(Callee) &&
633629 llvm::any_of (CaptureAttr->params (), [](int ArgIdx) {
634630 return ArgIdx == LifetimeCaptureByAttr::THIS;
635631 }))
632+ // `lifetime_capture_by(this)` in a class constructor has the same
633+ // semantics as `lifetimebound`:
634+ //
635+ // struct Foo {
636+ // const int& a;
637+ // // Equivalent to Foo(const int& t [[clang::lifetimebound]])
638+ // Foo(const int& t [[clang::lifetime_capture_by(this)]]) : a(t) {}
639+ // };
640+ //
641+ // In the implementation, `lifetime_capture_by` is treated as an alias for
642+ // `lifetimebound` and shares the same code path. This implies the emitted
643+ // diagnostics will be emitted under `-Wdangling`, not
644+ // `-Wdangling-capture`.
636645 VisitLifetimeBoundArg (Callee->getParamDecl (I), Arg);
637646 else if (EnableGSLAnalysis && I == 0 ) {
638647 // Perform GSL analysis for the first argument
0 commit comments