[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-28 Thread Haojian Wu via cfe-commits

https://github.com/hokein closed 
https://github.com/llvm/llvm-project/pull/117792
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-28 Thread Haojian Wu via cfe-commits


@@ -623,6 +623,26 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 }
 if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr())
   VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
+else if (const auto *CaptureAttr =
+ Callee->getParamDecl(I)->getAttr();
+ CaptureAttr && isa(Callee) &&
+ llvm::any_of(CaptureAttr->params(), [](int ArgIdx) {
+   return ArgIdx == LifetimeCaptureByAttr::THIS;
+ }))
+  // `lifetime_capture_by(this)` in a class constructor has the same
+  // semantics as `lifetimebound`:
+  //
+  // struct Foo {
+  //   const int& a;
+  //   // Equivalent to Foo(const int& t [[clang::lifetimebound]])
+  //   Foo(const int& t [[clang::lifetime_capture_by(this)]]) : a(t) {}
+  // };
+  //
+  // In the implementation, `lifetime_capture_by` is treated as an alias 
for
+  // `lifetimebound` and shares the same code path. This implies the 
emitted
+  // diagnostics will be emitted under `-Wdangling`, not
+  // `-Wdangling-capture`.
+  VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);

hokein wrote:

Done.

https://github.com/llvm/llvm-project/pull/117792
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-28 Thread Haojian Wu via cfe-commits

https://github.com/hokein updated 
https://github.com/llvm/llvm-project/pull/117792

>From edd8e7354c4ff96446d32830f4cd5e6c3c333a84 Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Tue, 26 Nov 2024 21:42:45 +0100
Subject: [PATCH 1/3] [clang] Improve the lifetime_capture_by diagnostic on the
 constructor.

---
 clang/lib/Sema/CheckExprLifetime.cpp  | 11 +++
 clang/lib/Sema/SemaChecking.cpp   |  6 ++
 .../warn-lifetime-analysis-capture-by.cpp | 19 +++
 3 files changed, 36 insertions(+)

diff --git a/clang/lib/Sema/CheckExprLifetime.cpp 
b/clang/lib/Sema/CheckExprLifetime.cpp
index 6cdd4dc629e50a..c4fa73127410b5 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -535,6 +535,9 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 
   bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
   diag::warn_dangling_lifetime_pointer, SourceLocation());
+  bool EnableDanglingCapture =
+  !Callee->getASTContext().getDiagnostics().isIgnored(
+  diag::warn_dangling_reference_captured, SourceLocation());
   Expr *ObjectArg = nullptr;
   if (isa(Call) && Callee->isCXXInstanceMember()) {
 ObjectArg = Args[0];
@@ -623,6 +626,14 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 }
 if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr())
   VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
+else if (const auto *CaptureAttr =
+ Callee->getParamDecl(I)->getAttr();
+ EnableDanglingCapture && CaptureAttr &&
+ isa(Callee) &&
+ llvm::any_of(CaptureAttr->params(), [](int ArgIdx) {
+   return ArgIdx == LifetimeCaptureByAttr::THIS;
+ }))
+  VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
 else if (EnableGSLAnalysis && I == 0) {
   // Perform GSL analysis for the first argument
   if (shouldTrackFirstArgument(Callee)) {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index a49605e4867651..1605523097a6b1 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3240,8 +3240,14 @@ void Sema::checkLifetimeCaptureBy(FunctionDecl *FD, bool 
IsMemberFunction,
  unsigned ArgIdx) {
 if (!Attr)
   return;
+
 Expr *Captured = const_cast(GetArgAt(ArgIdx));
 for (int CapturingParamIdx : Attr->params()) {
+  // lifetime_capture_by(this) case is handled in the lifetimebound expr
+  // initialization codepath.
+  if (CapturingParamIdx == LifetimeCaptureByAttr::THIS &&
+  isa(FD))
+continue;
   Expr *Capturing = const_cast(GetArgAt(CapturingParamIdx));
   CapturingEntity CE{Capturing};
   // Ensure that 'Captured' outlives the 'Capturing' entity.
diff --git a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp 
b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
index 4d562bac1e305b..77523210e50203 100644
--- a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
@@ -411,3 +411,22 @@ void use() {
 }
 } // namespace with_span
 } // namespace inferred_capture_by
+
+namespace on_constructor {
+struct T {
+  T(const int& t [[clang::lifetime_capture_by(this)]]);
+};
+struct T2 {
+  T2(const int& t [[clang::lifetime_capture_by(x)]], int& x);
+};
+int foo(const T& t);
+
+void test() {
+  auto x = foo(T(1)); // OK. no diagnosic
+  T(1); // OK. no diagnostic
+  T t(1); // expected-warning {{temporary whose address is used}}
+
+  int a;
+  T2(1, a); // expected-warning {{object whose reference is captured by}}
+}
+} // namespace on_constructor

>From 48487a5b1f9b87c295ce1d6df7d0fc60a7db6695 Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Thu, 28 Nov 2024 10:12:40 +0100
Subject: [PATCH 2/3] Address comments

---
 clang/lib/Sema/CheckExprLifetime.cpp  | 19 ++-
 .../warn-lifetime-analysis-capture-by.cpp |  7 +++
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/CheckExprLifetime.cpp 
b/clang/lib/Sema/CheckExprLifetime.cpp
index c4fa73127410b5..607b7daf878e17 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -535,9 +535,6 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 
   bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
   diag::warn_dangling_lifetime_pointer, SourceLocation());
-  bool EnableDanglingCapture =
-  !Callee->getASTContext().getDiagnostics().isIgnored(
-  diag::warn_dangling_reference_captured, SourceLocation());
   Expr *ObjectArg = nullptr;
   if (isa(Call) && Callee->isCXXInstanceMember()) {
 ObjectArg = Args[0];
@@ -628,11 +625,23 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
   VisitLifetimeBoundAr

[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-28 Thread Utkarsh Saxena via cfe-commits


@@ -535,6 +535,9 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 
   bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
   diag::warn_dangling_lifetime_pointer, SourceLocation());
+  bool EnableDanglingCapture =
+  !Callee->getASTContext().getDiagnostics().isIgnored(
+  diag::warn_dangling_reference_captured, SourceLocation());

usx95 wrote:

Thanks.

https://github.com/llvm/llvm-project/pull/117792
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-28 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 approved this pull request.


https://github.com/llvm/llvm-project/pull/117792
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-28 Thread Utkarsh Saxena via cfe-commits


@@ -623,6 +623,26 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 }
 if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr())
   VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
+else if (const auto *CaptureAttr =
+ Callee->getParamDecl(I)->getAttr();
+ CaptureAttr && isa(Callee) &&
+ llvm::any_of(CaptureAttr->params(), [](int ArgIdx) {
+   return ArgIdx == LifetimeCaptureByAttr::THIS;
+ }))
+  // `lifetime_capture_by(this)` in a class constructor has the same
+  // semantics as `lifetimebound`:
+  //
+  // struct Foo {
+  //   const int& a;
+  //   // Equivalent to Foo(const int& t [[clang::lifetimebound]])
+  //   Foo(const int& t [[clang::lifetime_capture_by(this)]]) : a(t) {}
+  // };
+  //
+  // In the implementation, `lifetime_capture_by` is treated as an alias 
for
+  // `lifetimebound` and shares the same code path. This implies the 
emitted
+  // diagnostics will be emitted under `-Wdangling`, not
+  // `-Wdangling-capture`.
+  VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);

usx95 wrote:

Thanks. Can you also add a one line description to the capture by docs as well.

https://github.com/llvm/llvm-project/pull/117792
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-28 Thread Haojian Wu via cfe-commits


@@ -535,6 +535,9 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 
   bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
   diag::warn_dangling_lifetime_pointer, SourceLocation());
+  bool EnableDanglingCapture =
+  !Callee->getASTContext().getDiagnostics().isIgnored(
+  diag::warn_dangling_reference_captured, SourceLocation());

hokein wrote:

Done. I added some comments to clarify the behavior.

https://github.com/llvm/llvm-project/pull/117792
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-28 Thread Haojian Wu via cfe-commits


@@ -411,3 +411,22 @@ void use() {
 }
 } // namespace with_span
 } // namespace inferred_capture_by
+
+namespace on_constructor {
+struct T {
+  T(const int& t [[clang::lifetime_capture_by(this)]]);
+};
+struct T2 {
+  T2(const int& t [[clang::lifetime_capture_by(x)]], int& x);
+};
+int foo(const T& t);

hokein wrote:

Done.

https://github.com/llvm/llvm-project/pull/117792
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-28 Thread Haojian Wu via cfe-commits

https://github.com/hokein updated 
https://github.com/llvm/llvm-project/pull/117792

>From edd8e7354c4ff96446d32830f4cd5e6c3c333a84 Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Tue, 26 Nov 2024 21:42:45 +0100
Subject: [PATCH 1/2] [clang] Improve the lifetime_capture_by diagnostic on the
 constructor.

---
 clang/lib/Sema/CheckExprLifetime.cpp  | 11 +++
 clang/lib/Sema/SemaChecking.cpp   |  6 ++
 .../warn-lifetime-analysis-capture-by.cpp | 19 +++
 3 files changed, 36 insertions(+)

diff --git a/clang/lib/Sema/CheckExprLifetime.cpp 
b/clang/lib/Sema/CheckExprLifetime.cpp
index 6cdd4dc629e50a..c4fa73127410b5 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -535,6 +535,9 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 
   bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
   diag::warn_dangling_lifetime_pointer, SourceLocation());
+  bool EnableDanglingCapture =
+  !Callee->getASTContext().getDiagnostics().isIgnored(
+  diag::warn_dangling_reference_captured, SourceLocation());
   Expr *ObjectArg = nullptr;
   if (isa(Call) && Callee->isCXXInstanceMember()) {
 ObjectArg = Args[0];
@@ -623,6 +626,14 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 }
 if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr())
   VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
+else if (const auto *CaptureAttr =
+ Callee->getParamDecl(I)->getAttr();
+ EnableDanglingCapture && CaptureAttr &&
+ isa(Callee) &&
+ llvm::any_of(CaptureAttr->params(), [](int ArgIdx) {
+   return ArgIdx == LifetimeCaptureByAttr::THIS;
+ }))
+  VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
 else if (EnableGSLAnalysis && I == 0) {
   // Perform GSL analysis for the first argument
   if (shouldTrackFirstArgument(Callee)) {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index a49605e4867651..1605523097a6b1 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3240,8 +3240,14 @@ void Sema::checkLifetimeCaptureBy(FunctionDecl *FD, bool 
IsMemberFunction,
  unsigned ArgIdx) {
 if (!Attr)
   return;
+
 Expr *Captured = const_cast(GetArgAt(ArgIdx));
 for (int CapturingParamIdx : Attr->params()) {
+  // lifetime_capture_by(this) case is handled in the lifetimebound expr
+  // initialization codepath.
+  if (CapturingParamIdx == LifetimeCaptureByAttr::THIS &&
+  isa(FD))
+continue;
   Expr *Capturing = const_cast(GetArgAt(CapturingParamIdx));
   CapturingEntity CE{Capturing};
   // Ensure that 'Captured' outlives the 'Capturing' entity.
diff --git a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp 
b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
index 4d562bac1e305b..77523210e50203 100644
--- a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
@@ -411,3 +411,22 @@ void use() {
 }
 } // namespace with_span
 } // namespace inferred_capture_by
+
+namespace on_constructor {
+struct T {
+  T(const int& t [[clang::lifetime_capture_by(this)]]);
+};
+struct T2 {
+  T2(const int& t [[clang::lifetime_capture_by(x)]], int& x);
+};
+int foo(const T& t);
+
+void test() {
+  auto x = foo(T(1)); // OK. no diagnosic
+  T(1); // OK. no diagnostic
+  T t(1); // expected-warning {{temporary whose address is used}}
+
+  int a;
+  T2(1, a); // expected-warning {{object whose reference is captured by}}
+}
+} // namespace on_constructor

>From 48487a5b1f9b87c295ce1d6df7d0fc60a7db6695 Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Thu, 28 Nov 2024 10:12:40 +0100
Subject: [PATCH 2/2] Address comments

---
 clang/lib/Sema/CheckExprLifetime.cpp  | 19 ++-
 .../warn-lifetime-analysis-capture-by.cpp |  7 +++
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/CheckExprLifetime.cpp 
b/clang/lib/Sema/CheckExprLifetime.cpp
index c4fa73127410b5..607b7daf878e17 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -535,9 +535,6 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 
   bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
   diag::warn_dangling_lifetime_pointer, SourceLocation());
-  bool EnableDanglingCapture =
-  !Callee->getASTContext().getDiagnostics().isIgnored(
-  diag::warn_dangling_reference_captured, SourceLocation());
   Expr *ObjectArg = nullptr;
   if (isa(Call) && Callee->isCXXInstanceMember()) {
 ObjectArg = Args[0];
@@ -628,11 +625,23 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
   VisitLifetimeBoundAr

[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-28 Thread Haojian Wu via cfe-commits

https://github.com/hokein updated 
https://github.com/llvm/llvm-project/pull/117792

>From edd8e7354c4ff96446d32830f4cd5e6c3c333a84 Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Tue, 26 Nov 2024 21:42:45 +0100
Subject: [PATCH 1/2] [clang] Improve the lifetime_capture_by diagnostic on the
 constructor.

---
 clang/lib/Sema/CheckExprLifetime.cpp  | 11 +++
 clang/lib/Sema/SemaChecking.cpp   |  6 ++
 .../warn-lifetime-analysis-capture-by.cpp | 19 +++
 3 files changed, 36 insertions(+)

diff --git a/clang/lib/Sema/CheckExprLifetime.cpp 
b/clang/lib/Sema/CheckExprLifetime.cpp
index 6cdd4dc629e50a..c4fa73127410b5 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -535,6 +535,9 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 
   bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
   diag::warn_dangling_lifetime_pointer, SourceLocation());
+  bool EnableDanglingCapture =
+  !Callee->getASTContext().getDiagnostics().isIgnored(
+  diag::warn_dangling_reference_captured, SourceLocation());
   Expr *ObjectArg = nullptr;
   if (isa(Call) && Callee->isCXXInstanceMember()) {
 ObjectArg = Args[0];
@@ -623,6 +626,14 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 }
 if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr())
   VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
+else if (const auto *CaptureAttr =
+ Callee->getParamDecl(I)->getAttr();
+ EnableDanglingCapture && CaptureAttr &&
+ isa(Callee) &&
+ llvm::any_of(CaptureAttr->params(), [](int ArgIdx) {
+   return ArgIdx == LifetimeCaptureByAttr::THIS;
+ }))
+  VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
 else if (EnableGSLAnalysis && I == 0) {
   // Perform GSL analysis for the first argument
   if (shouldTrackFirstArgument(Callee)) {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index a49605e4867651..1605523097a6b1 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3240,8 +3240,14 @@ void Sema::checkLifetimeCaptureBy(FunctionDecl *FD, bool 
IsMemberFunction,
  unsigned ArgIdx) {
 if (!Attr)
   return;
+
 Expr *Captured = const_cast(GetArgAt(ArgIdx));
 for (int CapturingParamIdx : Attr->params()) {
+  // lifetime_capture_by(this) case is handled in the lifetimebound expr
+  // initialization codepath.
+  if (CapturingParamIdx == LifetimeCaptureByAttr::THIS &&
+  isa(FD))
+continue;
   Expr *Capturing = const_cast(GetArgAt(CapturingParamIdx));
   CapturingEntity CE{Capturing};
   // Ensure that 'Captured' outlives the 'Capturing' entity.
diff --git a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp 
b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
index 4d562bac1e305b..77523210e50203 100644
--- a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
@@ -411,3 +411,22 @@ void use() {
 }
 } // namespace with_span
 } // namespace inferred_capture_by
+
+namespace on_constructor {
+struct T {
+  T(const int& t [[clang::lifetime_capture_by(this)]]);
+};
+struct T2 {
+  T2(const int& t [[clang::lifetime_capture_by(x)]], int& x);
+};
+int foo(const T& t);
+
+void test() {
+  auto x = foo(T(1)); // OK. no diagnosic
+  T(1); // OK. no diagnostic
+  T t(1); // expected-warning {{temporary whose address is used}}
+
+  int a;
+  T2(1, a); // expected-warning {{object whose reference is captured by}}
+}
+} // namespace on_constructor

>From da5e551cc486880896ebfbe8b6e7e5e51de71f8b Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Thu, 28 Nov 2024 10:12:40 +0100
Subject: [PATCH 2/2] Address comments

---
 clang/lib/Sema/CheckExprLifetime.cpp  | 19 ++-
 .../warn-lifetime-analysis-capture-by.cpp |  2 ++
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/CheckExprLifetime.cpp 
b/clang/lib/Sema/CheckExprLifetime.cpp
index c4fa73127410b5..607b7daf878e17 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -535,9 +535,6 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 
   bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
   diag::warn_dangling_lifetime_pointer, SourceLocation());
-  bool EnableDanglingCapture =
-  !Callee->getASTContext().getDiagnostics().isIgnored(
-  diag::warn_dangling_reference_captured, SourceLocation());
   Expr *ObjectArg = nullptr;
   if (isa(Call) && Callee->isCXXInstanceMember()) {
 ObjectArg = Args[0];
@@ -628,11 +625,23 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
   VisitLifetimeBoundArg(Cal

[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-27 Thread Utkarsh Saxena via cfe-commits


@@ -411,3 +411,22 @@ void use() {
 }
 } // namespace with_span
 } // namespace inferred_capture_by
+
+namespace on_constructor {
+struct T {
+  T(const int& t [[clang::lifetime_capture_by(this)]]);
+};
+struct T2 {
+  T2(const int& t [[clang::lifetime_capture_by(x)]], int& x);
+};
+int foo(const T& t);

usx95 wrote:

could you also add
```cpp
int bar(const T& t[[clang::lifetimebound]]);
auto y = bar(T(1));
```
```cpp
struct T3 {
T3(const T& t [[clang::lifetime_capture_by(this));
};
T3 t3(T(1));
```

https://github.com/llvm/llvm-project/pull/117792
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-27 Thread Utkarsh Saxena via cfe-commits


@@ -535,6 +535,9 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 
   bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
   diag::warn_dangling_lifetime_pointer, SourceLocation());
+  bool EnableDanglingCapture =
+  !Callee->getASTContext().getDiagnostics().isIgnored(
+  diag::warn_dangling_reference_captured, SourceLocation());

usx95 wrote:

I would not disable this based on new warning because:
1. This is not the warning that is triggered in this path.
2. We are considering both annotations as aliases in case of constructors. It 
would be better to do this unconditionally.

https://github.com/llvm/llvm-project/pull/117792
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-26 Thread Haojian Wu via cfe-commits

https://github.com/hokein created 
https://github.com/llvm/llvm-project/pull/117792

With this change, the lifetime_capture_by code path will not handle the 
constructor decl to avoid bogus diagnostics (see the testcase).

Instead, we reuse the lifetimebound code as the lifetime_capture_by(this) has 
the same semantic as lifetimebound in constructor. The downside is that the 
lifetimebound diagnostic is reused  for the capture case (I think it is not a 
big issue).


Fixes #117680

>From edd8e7354c4ff96446d32830f4cd5e6c3c333a84 Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Tue, 26 Nov 2024 21:42:45 +0100
Subject: [PATCH] [clang] Improve the lifetime_capture_by diagnostic on the
 constructor.

---
 clang/lib/Sema/CheckExprLifetime.cpp  | 11 +++
 clang/lib/Sema/SemaChecking.cpp   |  6 ++
 .../warn-lifetime-analysis-capture-by.cpp | 19 +++
 3 files changed, 36 insertions(+)

diff --git a/clang/lib/Sema/CheckExprLifetime.cpp 
b/clang/lib/Sema/CheckExprLifetime.cpp
index 6cdd4dc629e50a..c4fa73127410b5 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -535,6 +535,9 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 
   bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
   diag::warn_dangling_lifetime_pointer, SourceLocation());
+  bool EnableDanglingCapture =
+  !Callee->getASTContext().getDiagnostics().isIgnored(
+  diag::warn_dangling_reference_captured, SourceLocation());
   Expr *ObjectArg = nullptr;
   if (isa(Call) && Callee->isCXXInstanceMember()) {
 ObjectArg = Args[0];
@@ -623,6 +626,14 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 }
 if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr())
   VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
+else if (const auto *CaptureAttr =
+ Callee->getParamDecl(I)->getAttr();
+ EnableDanglingCapture && CaptureAttr &&
+ isa(Callee) &&
+ llvm::any_of(CaptureAttr->params(), [](int ArgIdx) {
+   return ArgIdx == LifetimeCaptureByAttr::THIS;
+ }))
+  VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
 else if (EnableGSLAnalysis && I == 0) {
   // Perform GSL analysis for the first argument
   if (shouldTrackFirstArgument(Callee)) {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index a49605e4867651..1605523097a6b1 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3240,8 +3240,14 @@ void Sema::checkLifetimeCaptureBy(FunctionDecl *FD, bool 
IsMemberFunction,
  unsigned ArgIdx) {
 if (!Attr)
   return;
+
 Expr *Captured = const_cast(GetArgAt(ArgIdx));
 for (int CapturingParamIdx : Attr->params()) {
+  // lifetime_capture_by(this) case is handled in the lifetimebound expr
+  // initialization codepath.
+  if (CapturingParamIdx == LifetimeCaptureByAttr::THIS &&
+  isa(FD))
+continue;
   Expr *Capturing = const_cast(GetArgAt(CapturingParamIdx));
   CapturingEntity CE{Capturing};
   // Ensure that 'Captured' outlives the 'Capturing' entity.
diff --git a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp 
b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
index 4d562bac1e305b..77523210e50203 100644
--- a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
@@ -411,3 +411,22 @@ void use() {
 }
 } // namespace with_span
 } // namespace inferred_capture_by
+
+namespace on_constructor {
+struct T {
+  T(const int& t [[clang::lifetime_capture_by(this)]]);
+};
+struct T2 {
+  T2(const int& t [[clang::lifetime_capture_by(x)]], int& x);
+};
+int foo(const T& t);
+
+void test() {
+  auto x = foo(T(1)); // OK. no diagnosic
+  T(1); // OK. no diagnostic
+  T t(1); // expected-warning {{temporary whose address is used}}
+
+  int a;
+  T2(1, a); // expected-warning {{object whose reference is captured by}}
+}
+} // namespace on_constructor

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)

2024-11-26 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Haojian Wu (hokein)


Changes

With this change, the lifetime_capture_by code path will not handle the 
constructor decl to avoid bogus diagnostics (see the testcase).

Instead, we reuse the lifetimebound code as the lifetime_capture_by(this) has 
the same semantic as lifetimebound in constructor. The downside is that the 
lifetimebound diagnostic is reused  for the capture case (I think it is not a 
big issue).


Fixes #117680

---
Full diff: https://github.com/llvm/llvm-project/pull/117792.diff


3 Files Affected:

- (modified) clang/lib/Sema/CheckExprLifetime.cpp (+11) 
- (modified) clang/lib/Sema/SemaChecking.cpp (+6) 
- (modified) clang/test/Sema/warn-lifetime-analysis-capture-by.cpp (+19) 


``diff
diff --git a/clang/lib/Sema/CheckExprLifetime.cpp 
b/clang/lib/Sema/CheckExprLifetime.cpp
index 6cdd4dc629e50a..c4fa73127410b5 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -535,6 +535,9 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 
   bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
   diag::warn_dangling_lifetime_pointer, SourceLocation());
+  bool EnableDanglingCapture =
+  !Callee->getASTContext().getDiagnostics().isIgnored(
+  diag::warn_dangling_reference_captured, SourceLocation());
   Expr *ObjectArg = nullptr;
   if (isa(Call) && Callee->isCXXInstanceMember()) {
 ObjectArg = Args[0];
@@ -623,6 +626,14 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
 }
 if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr())
   VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
+else if (const auto *CaptureAttr =
+ Callee->getParamDecl(I)->getAttr();
+ EnableDanglingCapture && CaptureAttr &&
+ isa(Callee) &&
+ llvm::any_of(CaptureAttr->params(), [](int ArgIdx) {
+   return ArgIdx == LifetimeCaptureByAttr::THIS;
+ }))
+  VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
 else if (EnableGSLAnalysis && I == 0) {
   // Perform GSL analysis for the first argument
   if (shouldTrackFirstArgument(Callee)) {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index a49605e4867651..1605523097a6b1 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3240,8 +3240,14 @@ void Sema::checkLifetimeCaptureBy(FunctionDecl *FD, bool 
IsMemberFunction,
  unsigned ArgIdx) {
 if (!Attr)
   return;
+
 Expr *Captured = const_cast(GetArgAt(ArgIdx));
 for (int CapturingParamIdx : Attr->params()) {
+  // lifetime_capture_by(this) case is handled in the lifetimebound expr
+  // initialization codepath.
+  if (CapturingParamIdx == LifetimeCaptureByAttr::THIS &&
+  isa(FD))
+continue;
   Expr *Capturing = const_cast(GetArgAt(CapturingParamIdx));
   CapturingEntity CE{Capturing};
   // Ensure that 'Captured' outlives the 'Capturing' entity.
diff --git a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp 
b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
index 4d562bac1e305b..77523210e50203 100644
--- a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
@@ -411,3 +411,22 @@ void use() {
 }
 } // namespace with_span
 } // namespace inferred_capture_by
+
+namespace on_constructor {
+struct T {
+  T(const int& t [[clang::lifetime_capture_by(this)]]);
+};
+struct T2 {
+  T2(const int& t [[clang::lifetime_capture_by(x)]], int& x);
+};
+int foo(const T& t);
+
+void test() {
+  auto x = foo(T(1)); // OK. no diagnosic
+  T(1); // OK. no diagnostic
+  T t(1); // expected-warning {{temporary whose address is used}}
+
+  int a;
+  T2(1, a); // expected-warning {{object whose reference is captured by}}
+}
+} // namespace on_constructor

``




https://github.com/llvm/llvm-project/pull/117792
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits