[clang] [clang] Output an error when [[lifetimebound]] attribute is applied on a function implicit object parameter while the function returns void (PR #114203)
Boaz Brickner via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 5 06:47:58 PST 2024
https://github.com/bricknerb updated https://github.com/llvm/llvm-project/pull/114203
>From 82d89b8b5d1e5faebefed57f3289eb43ad9f8d65 Mon Sep 17 00:00:00 2001
From: Boaz Brickner <brickner at google.com>
Date: Wed, 30 Oct 2024 11:24:07 +0100
Subject: [PATCH 1/3] [clang] Output an error when [[lifetimebound]] attribute
is applied on a function implicit object parameter while the function returns
void Fixes: #107556
---
clang/docs/ReleaseNotes.rst | 4 ++--
clang/include/clang/Basic/DiagnosticSemaKinds.td | 5 ++++-
clang/lib/Sema/SemaDecl.cpp | 8 +++++++-
clang/test/SemaCXX/attr-lifetimebound.cpp | 3 +--
4 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 920a2369f96435..5559875c0ebb7c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -134,8 +134,8 @@ C++ Specific Potentially Breaking Changes
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
- ignored and had no effect. (#GH107556)
+ applied on a parameter or an implicit object parameter of a function that
+ returns void. This was previously ignored and had no effect. (#GH107556)
.. code-block:: c++
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9b9bdd7c800e37..681c2757b7c76d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10097,9 +10097,12 @@ 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<
+def err_lifetimebound_parameter_void_return_type : Error<
"'lifetimebound' attribute cannot be applied to a parameter of a function "
"that returns void">;
+def err_lifetimebound_implicit_object_parameter_void_return_type : Error<
+ "'lifetimebound' attribute cannot be applied to an implicit object "
+ "parameter of a function that returns void">;
// 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 f8e5f3c6d309d6..c09ff4d1975e24 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6967,6 +6967,11 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
} else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) {
S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor)
<< isa<CXXDestructorDecl>(MD) << A->getRange();
+ } else if (FD->getReturnType()->isVoidType()) {
+ S.Diag(
+ FD->getLocation(),
+ diag::
+ err_lifetimebound_implicit_object_parameter_void_return_type);
}
}
}
@@ -6978,7 +6983,8 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
// 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);
+ S.Diag(A->getLocation(),
+ diag::err_lifetimebound_parameter_void_return_type);
}
}
}
diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp b/clang/test/SemaCXX/attr-lifetimebound.cpp
index 804d61fb62ca40..81e9193cf76a04 100644
--- a/clang/test/SemaCXX/attr-lifetimebound.cpp
+++ b/clang/test/SemaCXX/attr-lifetimebound.cpp
@@ -11,8 +11,7 @@ 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]];
+ void void_return_member() [[clang::lifetimebound]]; // expected-error {{'lifetimebound' attribute cannot be applied to an implicit object parameter of a function that returns void}}
};
int *attr_with_param(int ¶m [[clang::lifetimebound(42)]]); // expected-error {{takes no arguments}}
}
>From ae34279079f482c22eaa6c128c7e4df96ae11f5d Mon Sep 17 00:00:00 2001
From: Boaz Brickner <brickner at google.com>
Date: Wed, 30 Oct 2024 11:24:07 +0100
Subject: [PATCH 2/3] [clang] Output an error when [[lifetimebound]] attribute
is applied on a function implicit object parameter while the function returns
void Fixes: #107556
---
clang/docs/ReleaseNotes.rst | 4 ++--
clang/include/clang/Basic/DiagnosticSemaKinds.td | 5 ++++-
clang/lib/Sema/SemaDecl.cpp | 8 +++++++-
clang/test/SemaCXX/attr-lifetimebound.cpp | 3 +--
4 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6085352dfafe6b..61fc2ff5a9aeed 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -140,8 +140,8 @@ C++ Specific Potentially Breaking Changes
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
- ignored and had no effect. (#GH107556)
+ applied on a parameter or an implicit object parameter of a function that
+ returns void. This was previously ignored and had no effect. (#GH107556)
.. code-block:: c++
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 34ff49d7238a7f..3168337acb621f 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10101,9 +10101,12 @@ 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<
+def err_lifetimebound_parameter_void_return_type : Error<
"'lifetimebound' attribute cannot be applied to a parameter of a function "
"that returns void">;
+def err_lifetimebound_implicit_object_parameter_void_return_type : Error<
+ "'lifetimebound' attribute cannot be applied to an implicit object "
+ "parameter of a function that returns void">;
// 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 f8e5f3c6d309d6..c09ff4d1975e24 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6967,6 +6967,11 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
} else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) {
S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor)
<< isa<CXXDestructorDecl>(MD) << A->getRange();
+ } else if (FD->getReturnType()->isVoidType()) {
+ S.Diag(
+ FD->getLocation(),
+ diag::
+ err_lifetimebound_implicit_object_parameter_void_return_type);
}
}
}
@@ -6978,7 +6983,8 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
// 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);
+ S.Diag(A->getLocation(),
+ diag::err_lifetimebound_parameter_void_return_type);
}
}
}
diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp b/clang/test/SemaCXX/attr-lifetimebound.cpp
index 804d61fb62ca40..81e9193cf76a04 100644
--- a/clang/test/SemaCXX/attr-lifetimebound.cpp
+++ b/clang/test/SemaCXX/attr-lifetimebound.cpp
@@ -11,8 +11,7 @@ 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]];
+ void void_return_member() [[clang::lifetimebound]]; // expected-error {{'lifetimebound' attribute cannot be applied to an implicit object parameter of a function that returns void}}
};
int *attr_with_param(int ¶m [[clang::lifetimebound(42)]]); // expected-error {{takes no arguments}}
}
>From 519317ec9e6694d079386d4006606139ac98a684 Mon Sep 17 00:00:00 2001
From: Boaz Brickner <brickner at google.com>
Date: Tue, 5 Nov 2024 15:47:40 +0100
Subject: [PATCH 3/3] [clang] Use the more specific MD
---
clang/lib/Sema/SemaDecl.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c09ff4d1975e24..94544d9ab3ba8b 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6967,9 +6967,9 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
} else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) {
S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor)
<< isa<CXXDestructorDecl>(MD) << A->getRange();
- } else if (FD->getReturnType()->isVoidType()) {
+ } else if (MD->getReturnType()->isVoidType()) {
S.Diag(
- FD->getLocation(),
+ MD->getLocation(),
diag::
err_lifetimebound_implicit_object_parameter_void_return_type);
}
More information about the cfe-commits
mailing list