Skip to content

Commit 4f69f45

Browse files
authored
(reland) [clang] Warn [[clang::lifetimebound]] misusages on types (#118501)
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: > 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.
1 parent e9e7b2a commit 4f69f45

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ C++ Specific Potentially Breaking Changes
147147
// Fixed version:
148148
unsigned operator""_udl_name(unsigned long long);
149149

150-
- Clang will now produce an error diagnostic when [[clang::lifetimebound]] is
150+
- Clang will now produce an error diagnostic when ``[[clang::lifetimebound]]`` is
151151
applied on a parameter or an implicit object parameter of a function that
152152
returns void. This was previously ignored and had no effect. (#GH107556)
153153

@@ -156,6 +156,21 @@ C++ Specific Potentially Breaking Changes
156156
// Now diagnoses with an error.
157157
void f(int& i [[clang::lifetimebound]]);
158158

159+
- Clang will now produce an error diagnostic when ``[[clang::lifetimebound]]``
160+
is applied on a type (instead of a function parameter or an implicit object
161+
parameter); this includes the case when the attribute is specified for an
162+
unnamed function parameter. These were previously ignored and had no effect.
163+
(#GH118281)
164+
165+
.. code-block:: c++
166+
167+
// Now diagnoses with an error.
168+
int* [[clang::lifetimebound]] x;
169+
// Now diagnoses with an error.
170+
void f(int* [[clang::lifetimebound]] i);
171+
// Now diagnoses with an error.
172+
void g(int* [[clang::lifetimebound]]);
173+
159174
- Clang now rejects all field accesses on null pointers in constant expressions. The following code
160175
used to work but will now be rejected:
161176

clang/lib/Sema/SemaType.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8628,7 +8628,11 @@ static void HandleLifetimeBoundAttr(TypeProcessingState &State,
86288628
CurType = State.getAttributedType(
86298629
createSimpleAttr<LifetimeBoundAttr>(State.getSema().Context, Attr),
86308630
CurType, CurType);
8631+
return;
86318632
}
8633+
State.getSema().Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
8634+
<< Attr << Attr.isRegularKeywordAttribute()
8635+
<< "parameters and implicit object parameters";
86328636
}
86338637

86348638
static void HandleLifetimeCaptureByAttr(TypeProcessingState &State,

clang/test/SemaCXX/attr-lifetimebound.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,25 @@ namespace usage_invalid {
99
~A() [[clang::lifetimebound]]; // expected-error {{cannot be applied to a destructor}}
1010
static int *static_class_member() [[clang::lifetimebound]]; // expected-error {{static member function has no implicit object parameter}}
1111
int *explicit_object(this A&) [[clang::lifetimebound]]; // expected-error {{explicit object member function has no implicit object parameter}}
12-
int not_function [[clang::lifetimebound]]; // expected-error {{only applies to parameters and implicit object parameters}}
13-
int [[clang::lifetimebound]] also_not_function; // expected-error {{cannot be applied to types}}
12+
int attr_on_var [[clang::lifetimebound]]; // expected-error {{only applies to parameters and implicit object parameters}}
13+
int [[clang::lifetimebound]] attr_on_int; // expected-error {{cannot be applied to types}}
14+
int * [[clang::lifetimebound]] attr_on_int_ptr; // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
15+
int * [[clang::lifetimebound]] * attr_on_int_ptr_ptr; // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
16+
int (* [[clang::lifetimebound]] attr_on_func_ptr)(); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
1417
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)'}}
1518
};
1619
int *attr_with_param(int &param [[clang::lifetimebound(42)]]); // expected-error {{takes no arguments}}
20+
21+
void attr_on_ptr_arg(int * [[clang::lifetimebound]] ptr); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
22+
static_assert((int [[clang::lifetimebound]]) 12); // expected-error {{cannot be applied to types}}
23+
int* attr_on_unnamed_arg(const int& [[clang::lifetimebound]]); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
24+
template <typename T>
25+
int* attr_on_template_ptr_arg(T * [[clang::lifetimebound]] ptr); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
26+
27+
int (*func_ptr)(int) [[clang::lifetimebound]]; // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
28+
int (*(*func_ptr_ptr)(int) [[clang::lifetimebound]])(int); // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
29+
struct X {};
30+
int (X::*member_func_ptr)(int) [[clang::lifetimebound]]; // expected-error {{'lifetimebound' attribute only applies to parameters and implicit object parameters}}
1731
}
1832

1933
namespace usage_ok {

0 commit comments

Comments
 (0)