Skip to content

[6.2] Accept @cdecl global functions and enums, behind experimental feature flags #82791

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

Open
wants to merge 39 commits into
base: release/6.2
Choose a base branch
from

Conversation

xymus
Copy link
Contributor

@xymus xymus commented Jul 3, 2025

Add support for the @cdecl attribute on global functions and enums. This is gated on the experimental feature CDecl.

Global functions marked @cdecl are type-checked to ensure the parameter and return types are compatible with the C language. The equivalent C functions are printed to the compatibility header in a new section for C clients. In this section we also print the required #include when the signatures reference types imported from C.

@cdecl enums must declare an integer raw type representable in C. The equivalent C enums are printed to the compatibility header relying on macros to declare the raw type in a way that supports different C language variants.

The existing CImplementation experimental feature is already compatible with the new attribute @cdecl attribute. It allows to implement in Swift a C function declared in a C header by marking the implementation with @cdecl @implementation.

Note that using @objc on global functions is still not accepted by the parser.

xymus added 30 commits July 3, 2025 13:45
This implements basic checks on the validity of the @cdecl attribute and
ensures the parameters and result types are representable in C. Many
more diagnostics will need to be updated to verify full representability
in C.
Add a block for C clients in the compatibility header. This block
contains only the `@cdecl` functions that are printed using only C
types.

This C block is printed above the Objective-C and C++ blocks as if we
add support for `@cdecl` types other languages should be able to
reference them in function signatures. Other languages block don't
duplicate printing the `@cdecl` functions either as they are already
accessible to them.
In C mode we still print nullability attributes. Don't let clang warn on
them and ignore the attribute if the C compiler doesn't know them.
Start printing `#include` for headers referenced from `@cdecl` function
signatures. This adds on top of the existing tiered imports. We already
print each module referenced from decls printed in the compatibility
header. Previously we printed mostly `@import` with an option to
fallback on a `#import`. This change adds a third fallback to `#include`
when the module is referenced from a `@cdecl` function signature. The
bridging header can also be imported in a similar way.
Begin accepting the attribute in the form of `@cdecl(cName)`, using an
identifier instead of a string.

For ease of landing this change we still accept the string form. We
should stop accepting it before making this feature available in
production.
@cdecl enums are Swift enums representable in C. These enums must have
an integer raw type. They can be referenced from @cdecl functions and
@objc methods. @objc enums are still rejected from @cdecl functions.
Print @cdecl enums in the C section of the compatibility header. Use and
extend the macros to support C compiler clients.

The macro is adapted to the features supported by the client compiler.
It uses an Objective-C style macro with raw type when available and
fallbacks to a simple typedef for C compatibility.
xymus added 8 commits July 3, 2025 14:11
There are two main scenarios when printing a compatibility header that
references a @cdecl enum defined in Swift code. (1) When defined in the
same module as it's used we can print the definition normally and then
reference it. (2) When used in a different mode we need to print a
forward declaration before we can reference it.

This change adds printing the forward declaration and fix an issue where
the compiler would instead print an @include of the Swift module. The
import of the Swift module would work only in a local scenario where a
compatibility header and module would be generated under the same name.
However for a distributed frameworks we do not distribute the
compatibility header so this strategy doesn't work. Relying on a forward
declaration should be more reliable in all cases but clients may need to
import the other compatibility header explicitly.
Accept `@cdecl` enums without an explicit C name. The C name defaults to
the Swift one. It is printed using the `SWIFT_ENUM` macro instead of
`SWIFT_ENUM_NAMED`.
@xymus xymus requested a review from a team as a code owner July 3, 2025 23:19
@xymus xymus added the 🍒 release cherry pick Flag: Release branch cherry picks label Jul 3, 2025
Copy link
Contributor

@nkcsgexi nkcsgexi left a comment

Choose a reason for hiding this comment

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

Per discussion with @DougGregor , we've decided to cherry-pick the cdecl implementation to the release/6.2 branch.

@xymus
Copy link
Contributor Author

xymus commented Jul 3, 2025

@swift-ci Please test

@DougGregor
Copy link
Member

Linux failure is something I haven't seen before:

17:20:59  error: include location '/usr/local/include' is unsafe for cross-compilation [-Werror,-Wpoison-system-directories]
17:20:59  error: include location '/usr/include/x86_64-linux-gnu' is unsafe for cross-compilation [-Werror,-Wpoison-system-directories]
17:20:59  error: include location '/usr/include' is unsafe for cross-compilation [-Werror,-Wpoison-system-directories]
17:20:59  3 errors generated.

@xymus
Copy link
Contributor Author

xymus commented Jul 7, 2025

@swift-ci Please smoke test

I missed a commit in the cherry-pick. The use of -sysroot triggers a cross-compilation sanity check that is likely right but shouldn't matter for these tests.

@xymus
Copy link
Contributor Author

xymus commented Jul 7, 2025

@swift-ci Please test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🍒 release cherry pick Flag: Release branch cherry picks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants