Skip to content

Prefix @_cdecl functions with extern "C" in -Swift.h headers #38682

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 1 commit into from
Nov 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/PrintAsObjC/DeclAndTypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,8 @@ class DeclAndTypePrinter::Implementation
auto resultTy = getForeignResultType(
FD, funcTy, asyncConvention, errorConvention);

os << "SWIFT_EXTERN ";

// The result type may be a partial function type we need to close
// up later.
PrintMultiPartType multiPart(*this);
Expand Down
7 changes: 7 additions & 0 deletions lib/PrintAsObjC/PrintAsObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,13 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
"#if !defined(IBSegueAction)\n"
"# define IBSegueAction\n"
"#endif\n"
"#if !defined(SWIFT_EXTERN)\n"
"# if defined(__cplusplus)\n"
"# define SWIFT_EXTERN extern \"C\"\n"
"# else\n"
"# define SWIFT_EXTERN extern\n"
"# endif\n"
"#endif\n"
;
static_assert(SWIFT_MAX_IMPORTED_SIMD_ELEMENTS == 4,
"need to add SIMD typedefs here if max elements is increased");
Expand Down
18 changes: 9 additions & 9 deletions test/PrintAsObjC/cdecl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,51 @@
// REQUIRES: objc_interop

// CHECK: /// What a nightmare!
// CHECK-LABEL: double (^ _Nonnull block_nightmare(SWIFT_NOESCAPE float (^ _Nonnull x)(NSInteger)))(char) SWIFT_WARN_UNUSED_RESULT;
// CHECK-LABEL: SWIFT_EXTERN double (^ _Nonnull block_nightmare(SWIFT_NOESCAPE float (^ _Nonnull x)(NSInteger)))(char) SWIFT_WARN_UNUSED_RESULT;

/// What a nightmare!
@_cdecl("block_nightmare")
public func block_nightmare(x: @convention(block) (Int) -> Float)
-> @convention(block) (CChar) -> Double { return { _ in 0 } }

// CHECK-LABEL: double (^ _Nonnull block_recurring_nightmare(float (^ _Nonnull x)(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(double))))(SWIFT_NOESCAPE char (^ _Nonnull)(unsigned char)) SWIFT_WARN_UNUSED_RESULT;
// CHECK-LABEL: SWIFT_EXTERN double (^ _Nonnull block_recurring_nightmare(float (^ _Nonnull x)(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(double))))(SWIFT_NOESCAPE char (^ _Nonnull)(unsigned char)) SWIFT_WARN_UNUSED_RESULT;
@_cdecl("block_recurring_nightmare")
public func block_recurring_nightmare(x: @escaping @convention(block) (@convention(block) (Double) -> Int) -> Float)
-> @convention(block) (_ asdfasdf: @convention(block) (CUnsignedChar) -> CChar) -> Double {
fatalError()
}

// CHECK-LABEL: void foo_bar(NSInteger x, NSInteger y);
// CHECK-LABEL: SWIFT_EXTERN void foo_bar(NSInteger x, NSInteger y);
@_cdecl("foo_bar")
func foo(x: Int, bar y: Int) {}

// CHECK-LABEL: double (* _Nonnull function_pointer_nightmare(SWIFT_NOESCAPE float (* _Nonnull x)(NSInteger)))(char) SWIFT_WARN_UNUSED_RESULT;
// CHECK-LABEL: SWIFT_EXTERN double (* _Nonnull function_pointer_nightmare(SWIFT_NOESCAPE float (* _Nonnull x)(NSInteger)))(char) SWIFT_WARN_UNUSED_RESULT;
@_cdecl("function_pointer_nightmare")
func function_pointer_nightmare(x: @convention(c) (Int) -> Float)
-> @convention(c) (CChar) -> Double { return { _ in 0 } }

// CHECK-LABEL: double (* _Nonnull function_pointer_recurring_nightmare(float (* _Nonnull x)(SWIFT_NOESCAPE NSInteger (* _Nonnull)(double))))(SWIFT_NOESCAPE char (* _Nonnull)(unsigned char)) SWIFT_WARN_UNUSED_RESULT;
// CHECK-LABEL: SWIFT_EXTERN double (* _Nonnull function_pointer_recurring_nightmare(float (* _Nonnull x)(SWIFT_NOESCAPE NSInteger (* _Nonnull)(double))))(SWIFT_NOESCAPE char (* _Nonnull)(unsigned char)) SWIFT_WARN_UNUSED_RESULT;
@_cdecl("function_pointer_recurring_nightmare")
public func function_pointer_recurring_nightmare(x: @escaping @convention(c) (@convention(c) (Double) -> Int) -> Float)
-> @convention(c) (@convention(c) (CUnsignedChar) -> CChar) -> Double {
fatalError()
}

// CHECK-LABEL: void has_keyword_arg_names(NSInteger auto_, NSInteger union_);
// CHECK-LABEL: SWIFT_EXTERN void has_keyword_arg_names(NSInteger auto_, NSInteger union_);
@_cdecl("has_keyword_arg_names")
func keywordArgNames(auto: Int, union: Int) {}

@objc
class C {}

// CHECK-LABEL: C * _Null_unspecified return_iuo(void) SWIFT_WARN_UNUSED_RESULT;
// CHECK-LABEL: SWIFT_EXTERN C * _Null_unspecified return_iuo(void) SWIFT_WARN_UNUSED_RESULT;
@_cdecl("return_iuo")
func returnIUO() -> C! { return C() }

// CHECK-LABEL: void return_never(void) SWIFT_NORETURN;
// CHECK-LABEL: SWIFT_EXTERN void return_never(void) SWIFT_NORETURN;
@_cdecl("return_never")
func returnNever() -> Never { fatalError() }

// CHECK-LABEL: void takes_iuo(C * _Null_unspecified c);
// CHECK-LABEL: SWIFT_EXTERN void takes_iuo(C * _Null_unspecified c);
@_cdecl("takes_iuo")
func takesIUO(c: C!) {}