@@ -535,9 +535,6 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
535
535
536
536
bool EnableGSLAnalysis = !Callee->getASTContext ().getDiagnostics ().isIgnored (
537
537
diag::warn_dangling_lifetime_pointer, SourceLocation ());
538
- bool EnableDanglingCapture =
539
- !Callee->getASTContext ().getDiagnostics ().isIgnored (
540
- diag::warn_dangling_reference_captured, SourceLocation ());
541
538
Expr *ObjectArg = nullptr ;
542
539
if (isa<CXXOperatorCallExpr>(Call) && Callee->isCXXInstanceMember ()) {
543
540
ObjectArg = Args[0 ];
@@ -628,11 +625,23 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
628
625
VisitLifetimeBoundArg (Callee->getParamDecl (I), Arg);
629
626
else if (const auto *CaptureAttr =
630
627
Callee->getParamDecl (I)->getAttr <LifetimeCaptureByAttr>();
631
- EnableDanglingCapture && CaptureAttr &&
632
- isa<CXXConstructorDecl>(Callee) &&
628
+ CaptureAttr && isa<CXXConstructorDecl>(Callee) &&
633
629
llvm::any_of (CaptureAttr->params (), [](int ArgIdx) {
634
630
return ArgIdx == LifetimeCaptureByAttr::THIS;
635
631
}))
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`.
636
645
VisitLifetimeBoundArg (Callee->getParamDecl (I), Arg);
637
646
else if (EnableGSLAnalysis && I == 0 ) {
638
647
// Perform GSL analysis for the first argument
0 commit comments