https://github.com/bricknerb updated https://github.com/llvm/llvm-project/pull/113460
>From 4405d652029081cd63094e9a81dfa31e8611aad4 Mon Sep 17 00:00:00 2001 From: Boaz Brickner <brick...@google.com> Date: Wed, 23 Oct 2024 15:50:43 +0200 Subject: [PATCH 1/4] [clang] Output a warning when [[lifetimebound]] attribute is applied on a function parameter while the function returns void. --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 +++ clang/lib/Sema/SemaDecl.cpp | 14 +++++++++++++- clang/test/SemaCXX/attr-lifetimebound.cpp | 3 +-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8e4718008ece72..a1c20b22e736ed 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10097,6 +10097,9 @@ def err_lifetimebound_no_object_param : Error< def err_lifetimebound_ctor_dtor : Error< "'lifetimebound' attribute cannot be applied to a " "%select{constructor|destructor}0">; +def err_lifetimebound_void_return_type : Error< + "'lifetimebound' attribute cannot be applied to a parameter of a function " + "that returns void; did you mean 'lifetime_capture_by(X)'">; // CHECK: returning address/reference of stack memory def warn_ret_stack_addr_ref : Warning< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 229c9080d558ec..e611bf60718bc5 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6940,7 +6940,7 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { } } - // Check the attributes on the function type, if any. + // Check the attributes on the function type and function params, if any. if (const auto *FD = dyn_cast<FunctionDecl>(&ND)) { // Don't declare this variable in the second operand of the for-statement; // GCC miscompiles that by ending its lifetime before evaluating the @@ -6970,6 +6970,18 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { } } } + + for (unsigned int I = 0; I < FD->getNumParams(); ++I) { + const ParmVarDecl *P = FD->getParamDecl(I); + + // The [[lifetimebound]] attribute can be applied to a function parameter + // only if the function returns a value. + if (auto *A = P->getAttr<LifetimeBoundAttr>()) { + if (!isa<CXXConstructorDecl>(FD) && FD->getReturnType()->isVoidType()) { + S.Diag(A->getLocation(), diag::err_lifetimebound_void_return_type); + } + } + } } } diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp b/clang/test/SemaCXX/attr-lifetimebound.cpp index 1c5c79777c71c8..f790559b6b4769 100644 --- a/clang/test/SemaCXX/attr-lifetimebound.cpp +++ b/clang/test/SemaCXX/attr-lifetimebound.cpp @@ -1,8 +1,7 @@ // RUN: %clang_cc1 -std=c++23 -verify %s namespace usage_invalid { - // FIXME: Should we diagnose a void return type? - void voidreturn(int ¶m [[clang::lifetimebound]]); + void voidreturn(int ¶m [[clang::lifetimebound]]); // expected-error {{'lifetimebound' attribute cannot be applied to a parameter of a function that returns void; did you mean 'lifetime_capture_by(X)'}} int *not_class_member() [[clang::lifetimebound]]; // expected-error {{non-member function has no implicit object parameter}} struct A { >From 0a9a8629f5d188b1c1d648dc83438c33c14cc8cc Mon Sep 17 00:00:00 2001 From: Boaz Brickner <brick...@google.com> Date: Thu, 24 Oct 2024 09:55:01 +0200 Subject: [PATCH 2/4] [clang] Add a test for lifetimebound on a parameter when the return type is dependent on template argument but actually void. --- clang/test/SemaCXX/attr-lifetimebound.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp b/clang/test/SemaCXX/attr-lifetimebound.cpp index f790559b6b4769..33cce02936dda1 100644 --- a/clang/test/SemaCXX/attr-lifetimebound.cpp +++ b/clang/test/SemaCXX/attr-lifetimebound.cpp @@ -30,6 +30,11 @@ namespace usage_ok { return *(int*)param; } + template <class T, class R = void> R dependent_void(const T& t [[clang::lifetimebound]]); + void dependent_void_instantiation() { + dependent_void<int>(1); + } + struct A { A(); A(int); >From aab99080ba2b6d990d3b56f78ffec0ea2aaea948 Mon Sep 17 00:00:00 2001 From: Boaz Brickner <brick...@google.com> Date: Thu, 24 Oct 2024 10:13:14 +0200 Subject: [PATCH 3/4] [clang] Test a member method marked with lifetimebound that returns a void. This should diagnose but currently isn't. Added a FIXME comment. --- clang/test/SemaCXX/attr-lifetimebound.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp b/clang/test/SemaCXX/attr-lifetimebound.cpp index 33cce02936dda1..a0005ec1ccf4b4 100644 --- a/clang/test/SemaCXX/attr-lifetimebound.cpp +++ b/clang/test/SemaCXX/attr-lifetimebound.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++23 -verify %s namespace usage_invalid { - void voidreturn(int ¶m [[clang::lifetimebound]]); // expected-error {{'lifetimebound' attribute cannot be applied to a parameter of a function that returns void; did you mean 'lifetime_capture_by(X)'}} + void void_return(int ¶m [[clang::lifetimebound]]); // expected-error {{'lifetimebound' attribute cannot be applied to a parameter of a function that returns void; did you mean 'lifetime_capture_by(X)'}} int *not_class_member() [[clang::lifetimebound]]; // expected-error {{non-member function has no implicit object parameter}} struct A { @@ -11,6 +11,8 @@ namespace usage_invalid { int *explicit_object(this A&) [[clang::lifetimebound]]; // expected-error {{explicit object member function has no implicit object parameter}} int not_function [[clang::lifetimebound]]; // expected-error {{only applies to parameters and implicit object parameters}} int [[clang::lifetimebound]] also_not_function; // expected-error {{cannot be applied to types}} + // FIXME: Should diagnose a void return type. + void void_return_member() [[clang::lifetimebound]]; }; int *attr_with_param(int ¶m [[clang::lifetimebound(42)]]); // expected-error {{takes no arguments}} } >From 808d799f4b2b3c446c62e2985d30cc75138622b1 Mon Sep 17 00:00:00 2001 From: Boaz Brickner <brick...@google.com> Date: Thu, 24 Oct 2024 12:50:54 +0200 Subject: [PATCH 4/4] [clang] Remove the reference to lifetime_capture_by as it is not yet available. --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/test/SemaCXX/attr-lifetimebound.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a1c20b22e736ed..9b9bdd7c800e37 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10099,7 +10099,7 @@ def err_lifetimebound_ctor_dtor : Error< "%select{constructor|destructor}0">; def err_lifetimebound_void_return_type : Error< "'lifetimebound' attribute cannot be applied to a parameter of a function " - "that returns void; did you mean 'lifetime_capture_by(X)'">; + "that returns void">; // CHECK: returning address/reference of stack memory def warn_ret_stack_addr_ref : Warning< diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp b/clang/test/SemaCXX/attr-lifetimebound.cpp index a0005ec1ccf4b4..dee133b24fc0b8 100644 --- a/clang/test/SemaCXX/attr-lifetimebound.cpp +++ b/clang/test/SemaCXX/attr-lifetimebound.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++23 -verify %s namespace usage_invalid { - void void_return(int ¶m [[clang::lifetimebound]]); // expected-error {{'lifetimebound' attribute cannot be applied to a parameter of a function that returns void; did you mean 'lifetime_capture_by(X)'}} + void void_return(int ¶m [[clang::lifetimebound]]); // expected-error {{'lifetimebound' attribute cannot be applied to a parameter of a function that returns void}} int *not_class_member() [[clang::lifetimebound]]; // expected-error {{non-member function has no implicit object parameter}} struct A { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits