[clang] (reland) [clang] Warn [[clang::lifetimebound]] misusages on types (PR #118501)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 3 07:38:58 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Maksim Ivanov (emaxx-google)
<details>
<summary>Changes</summary>
The reland can go in after we fixed downstream codebases that had incorrectly placed attributes.
Original commit description:
Emit the "cannot be applied to types" warning instead of silently ignoring the attribute when it's attempted to be used on a type (instead of a function argument or the function definition).
Before this commit, the warning has been printed when the attribute was (mis)used on a decl-specifier, but not in other places in a declarator.
Examples where the warning starts being emitted with this commit:
```
int * [[clang::lifetimebound]] x;
void f(int * [[clang::lifetimebound]] x);
void g(int * [[clang::lifetimebound]]);
```
Note that the last example is the case of an unnamed function parameter. While in theory Clang could've supported the `[[clang::lifetimebound]]` analysis for unnamed parameters, it doesn't currently, so the commit at least makes the situation better by highlighting this as a warning instead of a silent ignore - which was reported at #<!-- -->96034.
---
Full diff: https://github.com/llvm/llvm-project/pull/118501.diff
3 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+16-1)
- (modified) clang/lib/Sema/SemaType.cpp (+4)
- (modified) clang/test/SemaCXX/attr-lifetimebound.cpp (+16-2)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b9986434d09d24..b7f0012572f880 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -139,7 +139,7 @@ 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
+- Clang will now produce an error diagnostic when ``[[clang::lifetimebound]]`` is
applied on a parameter or an implicit object parameter of a function that
returns void. This was previously ignored and had no effect. (#GH107556)
@@ -148,6 +148,21 @@ C++ Specific Potentially Breaking Changes
// Now diagnoses with an error.
void f(int& i [[clang::lifetimebound]]);
+- Clang will now produce an error diagnostic when ``[[clang::lifetimebound]]``
+ is applied on a type (instead of a function parameter or an implicit object
+ parameter); this includes the case when the attribute is specified for an
+ unnamed function parameter. These were previously ignored and had no effect.
+ (#GH118281)
+
+ .. code-block:: c++
+
+ // Now diagnoses with an error.
+ int* [[clang::lifetimebound]] x;
+ // Now diagnoses with an error.
+ void f(int* [[clang::lifetimebound]] i);
+ // Now diagnoses with an error.
+ void g(int* [[clang::lifetimebound]]);
+
- Clang now rejects all field accesses on null pointers in constant expressions. The following code
used to work but will now be rejected:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index f32edc5ac06440..75130436282fbd 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -8612,7 +8612,11 @@ static void HandleLifetimeBoundAttr(TypeProcessingState &State,
CurType = State.getAttributedType(
createSimpleAttr<LifetimeBoundAttr>(State.getSema().Context, Attr),
CurType, CurType);
+ return;
}
+ State.getSema().Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << Attr.isRegularKeywordAttribute()
+ << "parameters and implicit object parameters";
}
static void HandleLifetimeCaptureByAttr(TypeProcessingState &State,
diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp b/clang/test/SemaCXX/attr-lifetimebound.cpp
index f89b556f5bba08..c7abec61873efb 100644
--- a/clang/test/SemaCXX/attr-lifetimebound.cpp
+++ b/clang/test/SemaCXX/attr-lifetimebound.cpp
@@ -9,11 +9,25 @@ namespace usage_invalid {
~A() [[clang::lifetimebound]]; // expected-error {{cannot be applied to a destructor}}
static int *static_class_member() [[clang::lifetimebound]]; // expected-error {{static member function has no implicit object parameter}}
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}}
+ int attr_on_var [[clang::lifetimebound]]; // expected-error {{only applies to parameters and implicit object parameters}}
+ int [[clang::lifetimebound]] attr_on_int; // expected-error {{cannot be applied to types}}
+ int * [[clang::lifetimebound]] attr_on_int_ptr; // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
+ int * [[clang::lifetimebound]] * attr_on_int_ptr_ptr; // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
+ int (* [[clang::lifetimebound]] attr_on_func_ptr)(); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
void void_return_member() [[clang::lifetimebound]]; // expected-error {{'lifetimebound' attribute cannot be applied to an implicit object parameter of a function that returns void; did you mean 'lifetime_capture_by(X)'}}
};
int *attr_with_param(int ¶m [[clang::lifetimebound(42)]]); // expected-error {{takes no arguments}}
+
+ void attr_on_ptr_arg(int * [[clang::lifetimebound]] ptr); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
+ static_assert((int [[clang::lifetimebound]]) 12); // expected-error {{cannot be applied to types}}
+ int* attr_on_unnamed_arg(const int& [[clang::lifetimebound]]); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
+ template <typename T>
+ int* attr_on_template_ptr_arg(T * [[clang::lifetimebound]] ptr); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
+
+ int (*func_ptr)(int) [[clang::lifetimebound]]; // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
+ int (*(*func_ptr_ptr)(int) [[clang::lifetimebound]])(int); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
+ struct X {};
+ int (X::*member_func_ptr)(int) [[clang::lifetimebound]]; // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
}
namespace usage_ok {
``````````
</details>
https://github.com/llvm/llvm-project/pull/118501
More information about the cfe-commits
mailing list