Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 2 additions & 2 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ C++ Specific Potentially Breaking Changes
unsigned operator""_udl_name(unsigned long long);

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

.. code-block:: c++

Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -10101,9 +10101,12 @@ def err_lifetimebound_no_object_param : Error<
def err_lifetimebound_ctor_dtor : Error<
"'lifetimebound' attribute cannot be applied to a "
"%select{constructor|destructor}0">;
def err_lifetimebound_void_return_type : Error<
def err_lifetimebound_parameter_void_return_type : Error<
"'lifetimebound' attribute cannot be applied to a parameter of a function "
"that returns void">;
def err_lifetimebound_implicit_object_parameter_void_return_type : Error<
"'lifetimebound' attribute cannot be applied to an implicit object "
"parameter of a function that returns void">;

// CHECK: returning address/reference of stack memory
def warn_ret_stack_addr_ref : Warning<
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6967,6 +6967,11 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
} else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) {
S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor)
<< isa<CXXDestructorDecl>(MD) << A->getRange();
} else if (FD->getReturnType()->isVoidType()) {
S.Diag(
FD->getLocation(),
diag::
err_lifetimebound_implicit_object_parameter_void_return_type);
}
}
}
Expand All @@ -6978,7 +6983,8 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
// only if the function returns a value.
if (auto *A = P->getAttr<LifetimeBoundAttr>()) {
if (!isa<CXXConstructorDecl>(FD) && FD->getReturnType()->isVoidType()) {
S.Diag(A->getLocation(), diag::err_lifetimebound_void_return_type);
S.Diag(A->getLocation(),
diag::err_lifetimebound_parameter_void_return_type);
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions clang/test/SemaCXX/attr-lifetimebound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ namespace usage_invalid {
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}}
// FIXME: Should diagnose a void return type.
void void_return_member() [[clang::lifetimebound]];
void void_return_member() [[clang::lifetimebound]]; // expected-error {{'lifetimebound' attribute cannot be applied to an implicit object parameter of a function that returns void}}
};
int *attr_with_param(int &param [[clang::lifetimebound(42)]]); // expected-error {{takes no arguments}}
}
Expand Down
Loading