Skip to content

[clang] Warn [[clang::lifetimebound]] misusages on types #118281

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

Merged
merged 4 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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:

Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
18 changes: 16 additions & 2 deletions clang/test/SemaCXX/attr-lifetimebound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 &param [[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 {
Expand Down
Loading