[Clang][Sema] Disallow applying onwership_returns to functions that return non-pointers (#99564)

`onwership_returns` works only with pointers, since it models
user-defined memory allocation functions. Make semantics more clear and
report an error if attribute is attached to wrong function.

Closes #99501
This commit is contained in:
Pavel Skripkin 2024-07-29 19:43:50 +03:00 committed by GitHub
parent ee57ce57d8
commit 150bf637ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 25 additions and 8 deletions

View File

@ -273,6 +273,10 @@ Crash and bug fixes
Improvements
^^^^^^^^^^^^
- Improved the handling of the ``ownership_returns`` attribute. Now, Clang reports an
error if the attribute is attached to a function that returns a non-pointer value.
Fixes (#GH99501)
Moved checkers
^^^^^^^^^^^^^^

View File

@ -3330,6 +3330,8 @@ def err_attribute_invalid_implicit_this_argument : Error<
"%0 attribute is invalid for the implicit this argument">;
def err_ownership_type : Error<
"%0 attribute only applies to %select{pointer|integer}1 arguments">;
def err_ownership_takes_return_type : Error<
"'ownership_returns' attribute only applies to functions that return a pointer">;
def err_ownership_returns_index_mismatch : Error<
"'ownership_returns' attribute index does not match; here it is %0">;
def note_ownership_returns_index_mismatch : Note<

View File

@ -1481,6 +1481,14 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
break;
}
// Allow only pointers to be return type for functions with ownership_returns
// attribute. This matches with current OwnershipAttr::Takes semantics
if (K == OwnershipAttr::Returns &&
!getFunctionOrMethodResultType(D)->isPointerType()) {
S.Diag(AL.getLoc(), diag::err_ownership_takes_return_type) << AL;
return;
}
IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident;
StringRef ModuleName = Module->getName();

View File

@ -32,8 +32,8 @@ int *aa(int i) __attribute__((alloc_align(1)));
void ownt(int *, int *) __attribute__((ownership_takes(foo, 1, 2)));
// CHECK: void ownh(int *, int *) __attribute__((ownership_holds(foo, 1, 2)));
void ownh(int *, int *) __attribute__((ownership_holds(foo, 1, 2)));
// CHECK: void ownr(int) __attribute__((ownership_returns(foo, 1)));
void ownr(int) __attribute__((ownership_returns(foo, 1)));
// CHECK: void *ownr(int) __attribute__((ownership_returns(foo, 1)));
void *ownr(int) __attribute__((ownership_returns(foo, 1)));
// CHECK: void awtt(int, int, ...) __attribute__((argument_with_type_tag(foo, 3, 2)));
void awtt(int, int, ...) __attribute__((argument_with_type_tag(foo, 3, 2)));
@ -65,8 +65,8 @@ class C {
void ownt(int *, int *) __attribute__((ownership_takes(foo, 2, 3)));
// CHECK: void ownh(int *, int *) __attribute__((ownership_holds(foo, 2, 3)));
void ownh(int *, int *) __attribute__((ownership_holds(foo, 2, 3)));
// CHECK: void ownr(int) __attribute__((ownership_returns(foo, 2)));
void ownr(int) __attribute__((ownership_returns(foo, 2)));
// CHECK: void *ownr(int) __attribute__((ownership_returns(foo, 2)));
void *ownr(int) __attribute__((ownership_returns(foo, 2)));
// CHECK: void awtt(int, int, ...) __attribute__((argument_with_type_tag(foo, 4, 3)));
void awtt(int, int, ...) __attribute__((argument_with_type_tag(foo, 4, 3)));

View File

@ -18,7 +18,7 @@ void *f12(float i, int k, int f, int *j) __attribute__((ownership_returns(foo, 4
void f13(int *i, int *j) __attribute__((ownership_holds(foo, 1))) __attribute__((ownership_takes(foo, 2)));
void f14(int i, int j, int *k) __attribute__((ownership_holds(foo, 3))) __attribute__((ownership_takes(foo, 3))); // expected-error {{'ownership_takes' and 'ownership_holds' attributes are not compatible}}
void f15(int, int)
void *f15(int, int)
__attribute__((ownership_returns(foo, 1))) // expected-error {{'ownership_returns' attribute index does not match; here it is 1}}
__attribute__((ownership_returns(foo, 2))); // expected-note {{declared with index 2 here}}
void f16(int *i, int *j) __attribute__((ownership_holds(foo, 1))) __attribute__((ownership_holds(foo, 1))); // OK, same index
@ -28,3 +28,6 @@ void f18() __attribute__((ownership_takes(foo, 1))); // expected-warning {{'own
int f19(void *)
__attribute__((ownership_takes(foo, 1))) // expected-error {{'ownership_takes' attribute class does not match; here it is 'foo'}}
__attribute__((ownership_takes(foo1, 1))); // expected-note {{declared with class 'foo1' here}}
void f20(void) __attribute__((ownership_returns(foo))); // expected-error {{'ownership_returns' attribute only applies to functions that return a pointer}}
int f21(void) __attribute__((ownership_returns(foo))); // expected-error {{'ownership_returns' attribute only applies to functions that return a pointer}}

View File

@ -1,7 +1,7 @@
// RUN: %clang_cc1 %s -verify -fsyntax-only
class C {
void f(int, int)
__attribute__((ownership_returns(foo, 2))) // expected-error {{'ownership_returns' attribute index does not match; here it is 2}}
__attribute__((ownership_returns(foo, 3))); // expected-note {{declared with index 3 here}}
void *f(int, int)
__attribute__((ownership_returns(foo, 2))) // expected-error {{'ownership_returns' attribute index does not match; here it is 2}}
__attribute__((ownership_returns(foo, 3))); // expected-note {{declared with index 3 here}}
};