[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:
parent
ee57ce57d8
commit
150bf637ba
@ -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
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -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<
|
||||
|
@ -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();
|
||||
|
@ -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)));
|
||||
|
@ -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}}
|
||||
|
@ -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}}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user