-
Notifications
You must be signed in to change notification settings - Fork 14.3k
(reland) [clang] Warn [[clang::lifetimebound]] misusages on types #118501
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Maksim Ivanov (emaxx-google) ChangesThe 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:
Note that the last example is the case of an unnamed function parameter. While in theory Clang could've supported the Full diff: https://github.com/llvm/llvm-project/pull/118501.diff 3 Files Affected:
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 {
|
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]], it doesn't currently, so the commit at least makes the situation better by highlighting this as a warning instead of a silent ignore.
b8daefa
to
7cdbb1e
Compare
Also: I didn't proceed with this PR because internal cleanup in Google's internal code base took time, but as this is finished now the PR could be merged. |
#122473 is the promised follow-up for the diag. |
…vm#118501) This relands llvm#118281 as-is, after it got reverted in commit 356df2d. The reland can go in after we fixed some 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 llvm#96034.
A cleanup follow-up to llvm#118501 and llvm#118567.
This relands #118281 as-is, after it got reverted in commit 356df2d. The reland can go in after we fixed some downstream codebases that had incorrectly placed attributes.
Original commit description: