[clang] [clang] Output an error when [[lifetimebound]] attribute is applied on a function parameter while the function returns void (PR #113460)
Boaz Brickner via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 25 00:58:04 PDT 2024
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 <brickner at google.com>
Date: Wed, 23 Oct 2024 15:50:43 +0200
Subject: [PATCH 1/5] [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 <brickner at google.com>
Date: Thu, 24 Oct 2024 09:55:01 +0200
Subject: [PATCH 2/5] [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 <brickner at google.com>
Date: Thu, 24 Oct 2024 10:13:14 +0200
Subject: [PATCH 3/5] [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 <brickner at google.com>
Date: Thu, 24 Oct 2024 12:50:54 +0200
Subject: [PATCH 4/5] [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 {
>From 6444de47c6e670f2bc169c1d5058ce9b4558443b Mon Sep 17 00:00:00 2001
From: Boaz Brickner <brickner at google.com>
Date: Fri, 25 Oct 2024 09:57:51 +0200
Subject: [PATCH 5/5] [clang] Add a C++ Specific Potentially Breaking Change
for the new error diagnostics that is generated when a function that returns
void has [[clang::lifetimebound]] applied to one or more of its parameters.
---
clang/docs/ReleaseNotes.rst | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 28bb83a1c9d60f..0b14f312f81562 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -133,6 +133,15 @@ C++ Specific Potentially Breaking Changes
// Fixed version:
unsigned operator""_udl_name(unsigned long long);
+- Clang will now produce an error diagnostic when [[clang::lifetimebound]] is
+ applied on a parameter of a function that returns void. This was previously
+ gnored and had no effect.
+
+ .. code-block:: c++
+
+ // Now diagnoses with an error.
+ void f(int& i [[clang::lifetimebound]]);
+
ABI Changes in This Version
---------------------------
More information about the cfe-commits
mailing list