Skip to content

Commit

Permalink
[clang] Warn [[clang::lifetimebound]] misusages on types (llvm#118281)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
emaxx-google authored Dec 3, 2024
1 parent bfb2620 commit 4849d59
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
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

0 comments on commit 4849d59

Please sign in to comment.