[clang] [clang] Improve the lifetime_capture_by diagnostic on the constructor. (PR #117792)
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)
@@ -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)
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)
@@ -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)
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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
@@ -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)
@@ -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)
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)
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