Skip to content

[clang] Output an error when [[lifetimebound]] attribute is applied on a function parameter while the function returns void #113460

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 7 commits into from
Oct 25, 2024
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -10097,6 +10097,9 @@ 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<
"'lifetimebound' attribute cannot be applied to a parameter of a function "
"that returns void; did you mean 'lifetime_capture_by(X)'">;

// CHECK: returning address/reference of stack memory
def warn_ret_stack_addr_ref : Warning<
Expand Down
14 changes: 13 additions & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6940,7 +6940,7 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
}
}

// Check the attributes on the function type, if any.
// Check the attributes on the function type and function params, if any.
if (const auto *FD = dyn_cast<FunctionDecl>(&ND)) {
// Don't declare this variable in the second operand of the for-statement;
// GCC miscompiles that by ending its lifetime before evaluating the
Expand Down Expand Up @@ -6970,6 +6970,18 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
}
}
}

for (unsigned int I = 0; I < FD->getNumParams(); ++I) {
const ParmVarDecl *P = FD->getParamDecl(I);

// The [[lifetimebound]] attribute can be applied to a function parameter
// 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);
}
}
}
}
}

Expand Down
3 changes: 1 addition & 2 deletions clang/test/SemaCXX/attr-lifetimebound.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// RUN: %clang_cc1 -std=c++23 -verify %s

namespace usage_invalid {
// FIXME: Should we diagnose a void return type?
void voidreturn(int &param [[clang::lifetimebound]]);
void voidreturn(int &param [[clang::lifetimebound]]); // expected-error {{'lifetimebound' attribute cannot be applied to a parameter of a function that returns void; did you mean 'lifetime_capture_by(X)'}}

int *not_class_member() [[clang::lifetimebound]]; // expected-error {{non-member function has no implicit object parameter}}
struct A {
Expand Down
Loading