Skip to content

[cxx-interop] Add SWIFT_RETURNS_RETAINED and SWIFT_RETURNS_UNRETAINED… #75897

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

Conversation

fahadnayyar
Copy link
Contributor

@fahadnayyar fahadnayyar commented Aug 14, 2024

Adding SWIFT_RETURNS_RETAINED and SWIFT_RETURNS_UNRETAINED annotations to specify ownership of FRT returned by a C++ method or function. The default behaviour without these annotations remain unchanged.

rdar://135306908

@fahadnayyar
Copy link
Contributor Author

@swift-ci please smoke test

@fahadnayyar fahadnayyar force-pushed the f-dev-frt-return-ownership-annotations-pr branch from 70d72fe to 1f150a5 Compare August 16, 2024 01:45
@fahadnayyar
Copy link
Contributor Author

@swift-ci please smoke test

@Xazax-hun
Copy link
Contributor

High-level question: do we need both of these? If we have a default behavior, we might be able drop the one that matches that. That being said, I don't have strong feelings about this, since these annotations can also serve as documentation and users can also use it to hedge against the defaults changing.

@Xazax-hun
Copy link
Contributor

Xazax-hun commented Aug 16, 2024

Ah, never mind. So the default might be based on naming conventions, so the user needs to be able to override the defaults in both directions.

Copy link
Contributor

@egorzhdan egorzhdan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The overall approach seems reasonable to me, I have a few comments.

Copy link
Contributor

@Xazax-hun Xazax-hun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me as well, I only mentioned some small nits.

@xedin xedin removed their request for review August 20, 2024 17:33
@fahadnayyar fahadnayyar force-pushed the f-dev-frt-return-ownership-annotations-pr branch from 1f150a5 to b8bc313 Compare August 21, 2024 20:00
@fahadnayyar
Copy link
Contributor Author

@swift-ci please smoke test

@fahadnayyar fahadnayyar force-pushed the f-dev-frt-return-ownership-annotations-pr branch from b8bc313 to 8c34f5a Compare August 21, 2024 20:03
@fahadnayyar
Copy link
Contributor Author

@swift-ci please smoke test

@fahadnayyar
Copy link
Contributor Author

fahadnayyar commented Aug 23, 2024

@rjmccall @DougGregor

In this patch I am adding two new macros SWIFT_RETURNS_RETAINED and SWIFT_RETURNS_UNRETAINED and implementing these as swift_attr attributes with strings "returns_retained" and "returns_unretained" respectively. Some of our clients use these attributes as a public interface because they are unable to use the bridging header defining these marcos. Swift compiler already has some support for clang attributes cf_returns_retained and cf_returns_unretained for C++ functions and methods. But their semantics would be different for C++ as compared to CF. In CF return types cf_returns_unretained means returning the value as autoreleased while for c++ SWIFT_SHARED_REFERENCE types it means returning as unowned. Also using CF_ attributes and macros on C++ types seemed a bit odd to me as we want these attributes to be used by everyone and not just internally. Another source of confusion is that cf_returns_retained has effect on c++ methods and functions but ns_returns_retained has no effect. And in the clang documentation it is not clear if these attributes can be used for C++ methods and functions as well.

I wanted to get your opinion on whether we should use the existing clang attributes cf_returns_retained and cf_returns_unretained as the public interface to specify the ownership of C++ foreign reference types return values or implement new swift_attr("returns_retained") and swift_attr("returns_unretained") as I am doing in this patch?

@egorzhdan
Copy link
Contributor

One important detail there is that we think that the attributes would need to change in the future, regardless of whether we use the existing cf_returns_retained or add a new swift_attr("returns_retained") attribute now.

To provide Clang diagnostics and Clang static analyzer support for these attributes, similarly to the existing support for cf_returns_retained, we would need to make them first-class Clang attributes, since Clang isn't aware of the contents of a swift_attr, and the cf_ attributes have slightly different semantic meaning (they assume usage of CFRetain/CFRelease, which is not something we use for C++ reference types).

@ahatanaka
Copy link
Contributor

ahatanaka commented Aug 23, 2024

Another source of confusion is that cf_returns_retained has effect on c++ methods and functions but ns_returns_retained has no effect.

ns_returns_retained has effect on C++ methods and functions too if the return type is an ObjC object.

@class C;

struct S {
  C *f() __attribute__((ns_returns_retained));
};

https://releases.llvm.org/3.5.0/tools/clang/docs/AutomaticReferenceCounting.html#retained-return-values

@fahadnayyar
Copy link
Contributor Author

fahadnayyar commented Aug 23, 2024

@rjmccall @DougGregor

In this patch I am adding two new macros SWIFT_RETURNS_RETAINED and SWIFT_RETURNS_UNRETAINED and implementing these as swift_attr attributes with strings "returns_retained" and "returns_unretained" respectively. Some of our clients use these attributes as a public interface because they are unable to use the bridging header defining these marcos. Swift compiler already has some support for clang attributes cf_returns_retained and cf_returns_unretained for C++ functions and methods. But their semantics would be different for C++ as compared to CF. In CF return types cf_returns_unretained means returning the value as autoreleased while for c++ SWIFT_SHARED_REFERENCE types it means returning as unowned. Also using CF_ attributes and macros on C++ types seemed a bit odd to me as we want these attributes to be used by everyone and not just internally. Another source of confusion is that cf_returns_retained has effect on c++ methods and functions but ns_returns_retained has no effect. And in the clang documentation it is not clear if these attributes can be used for C++ methods and functions as well.

I wanted to get your opinion on whether we should use the existing clang attributes cf_returns_retained and cf_returns_unretained as the public interface to specify the ownership of C++ foreign reference types return values or implement new swift_attr("returns_retained") and swift_attr("returns_unretained") as I am doing in this patch?

Another reason why CF_ attributes are confusing for C++ methods and functions is that, for CF types there is also a create/copy rule which applied even if the CF_ attributes are not present. CF functions having either create or copy in their name pass the returned value as owned. I feel we should in future deprecate the use of CF_ macros and cf_ attributes for C++ functions and methods to avoid such confusions. Currently the create/copy rule is also applied to C++ function and method which is a bug reported by some of our clients. We are planning to fix the default behavior (in the absence of any attributes) in a follow up patch.

Ref: https://releases.llvm.org/3.5.0/tools/clang/docs/AutomaticReferenceCounting.html#id18

@fahadnayyar fahadnayyar added the c++ interop Feature: Interoperability with C++ label Aug 29, 2024
@fahadnayyar fahadnayyar force-pushed the f-dev-frt-return-ownership-annotations-pr branch from 8c34f5a to a9dbe65 Compare September 3, 2024 20:27
@fahadnayyar
Copy link
Contributor Author

@swift-ci please smoke test

@fahadnayyar fahadnayyar force-pushed the f-dev-frt-return-ownership-annotations-pr branch from a9dbe65 to 493561a Compare September 4, 2024 23:24
Copy link
Contributor

@egorzhdan egorzhdan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks good, I only have one minor comment.

… annotations to specify ownership of FRT returned by a C++ method or function

rdar://135306908
@fahadnayyar fahadnayyar force-pushed the f-dev-frt-return-ownership-annotations-pr branch from 493561a to ea43283 Compare September 5, 2024 18:44
@fahadnayyar
Copy link
Contributor Author

@swift-ci please smoke test

@fahadnayyar
Copy link
Contributor Author

Another source of confusion is that cf_returns_retained has effect on c++ methods and functions but ns_returns_retained has no effect.

ns_returns_retained has effect on C++ methods and functions too if the return type is an ObjC object.

@class C;

struct S {
  C *f() __attribute__((ns_returns_retained));
};

https://releases.llvm.org/3.5.0/tools/clang/docs/AutomaticReferenceCounting.html#retained-return-values

@ahatanaka I feel we should use these classes of annotations CF_ NS_ SWIFT_ as per the return type of C++ functions and/or methods:
See: rdar://135362223

We have 3 class of annotations:
CF_RETURNS_{RETAINED/UNRETAINED} -> handles return type of CF objects
NS_RETURNS_{RETAINED/UNRETAINED} -> handles return type of ObjC objects
SWIFT_RETURNS_{RETAINED/UNRETAINED} -> handles return type of C++ foreign reference type objects

They should have effect on C++ method, functions, etc only if the return type is of their respective category. Otherwise we should warn or error out in the ClangImporter.

We can have additional testing to make sure that behaviour is changed only for C++ functions and methods and not for C, ObjC, CF, etc functions.

Let me know if you have thoughts.

Copy link
Contributor

@egorzhdan egorzhdan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ interop Feature: Interoperability with C++
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants