Skip to content

Commit 5bb9ccf

Browse files
author
Gabor Horvath
committed
[cxx-interop] Fix exporing cdecl Swift functions to Obj-C++
We export cdecl function declarations twice: for Objective-C and for C++. When the code is compiled in Objective-C++ both of the declarations are visible to the compiler. The generated header did not compile, because only one of the declarations were noexcept. There are multiple possible ways to fix this issue, one of them would make only C++ declarations visible in Objective-C++ mode. However, for this particular problem I decided to also make the Objective-C functions SWIFT_NOEXCEPT. This approach resolves the inconsistency that broke the code when compiled in Objective-C++ mode. Moreover, Swift guarantees that those cdecl declarations cannot raise errors, so in case we only generate the C declarations and consume them from C++ or Objective-C++, those are the correct declarations. rdar://129550313
1 parent 85c0555 commit 5bb9ccf

File tree

4 files changed

+17
-12
lines changed

4 files changed

+17
-12
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,7 @@ class DeclAndTypePrinter::Implementation
14401440
os << "SWIFT_EXTERN ";
14411441
printFunctionDeclAsCFunctionDecl(FD, FD->getCDeclName(), resultTy);
14421442
printFunctionClangAttributes(FD, funcTy);
1443+
os << " SWIFT_NOEXCEPT";
14431444
printAvailability(FD);
14441445
os << ";\n";
14451446
}

test/Interop/SwiftToCxx/functions/swift-functions.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import CxxStdlib
66

77
// RUN: %check-interop-cxx-header-in-clang(%t/functions.h)
88

9+
@_cdecl("cdeclFunction") public func cdeclFunction(_ x: CInt) {}
10+
11+
// CHECK: SWIFT_EXTERN void cdeclFunction(int x) SWIFT_NOEXCEPT;
12+
913
// CHECK-LABEL: namespace Functions SWIFT_PRIVATE_ATTR SWIFT_SYMBOL_MODULE("Functions") {
1014

1115
// CHECK-LABEL: namespace _impl {

test/PrintAsObjC/cdecl-imports.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,19 @@ import Foundation
1212
// CHECK-NOT: @import Foundation;
1313

1414
// CHECK: @class Bee;
15-
// CHECK-LABEL: Bee * _Nonnull fwd_declares_bee(void) SWIFT_WARN_UNUSED_RESULT;
15+
// CHECK-LABEL: Bee * _Nonnull fwd_declares_bee(void) SWIFT_WARN_UNUSED_RESULT SWIFT_NOEXCEPT;
1616

1717
@_cdecl("fwd_declares_bee")
1818
public func fwdDeclaresBee() -> Bee { fatalError() }
1919

2020
// CHECK: @class Hive;
21-
// CHECK-LABEL: void fwd_declares_hive(Hive * _Nonnull (* _Nonnull bzzz)(Bee * _Nonnull));
21+
// CHECK-LABEL: void fwd_declares_hive(Hive * _Nonnull (* _Nonnull bzzz)(Bee * _Nonnull)) SWIFT_NOEXCEPT;
2222

2323
@_cdecl("fwd_declares_hive")
2424
public func fwdDeclaresHive(bzzz: @convention(c) (Bee) -> Hive) { fatalError() }
2525

2626
// CHECK: @protocol NSWobbling;
27-
// CHECK-LABEL: void fwd_declares_wobble(id <NSWobbling> _Nonnull wobbler);
27+
// CHECK-LABEL: void fwd_declares_wobble(id <NSWobbling> _Nonnull wobbler) SWIFT_NOEXCEPT;
2828

2929
@_cdecl("fwd_declares_wobble")
3030
public func fwdDeclaresWobble(wobbler: NSWobbling) { fatalError() }

test/PrintAsObjC/cdecl.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,51 +8,51 @@
88
// REQUIRES: objc_interop
99

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

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

18-
// 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;
18+
// 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 SWIFT_NOEXCEPT;
1919
@_cdecl("block_recurring_nightmare")
2020
public func block_recurring_nightmare(x: @escaping @convention(block) (@convention(block) (Double) -> Int) -> Float)
2121
-> @convention(block) (_ asdfasdf: @convention(block) (CUnsignedChar) -> CChar) -> Double {
2222
fatalError()
2323
}
2424

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

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

34-
// CHECK-LABEL: SWIFT_EXTERN double (* _Nonnull function_pointer_recurring_nightmare(float (* _Nonnull x)(NSInteger (* _Nonnull)(double))))(char (* _Nonnull)(unsigned char)) SWIFT_WARN_UNUSED_RESULT;
34+
// CHECK-LABEL: SWIFT_EXTERN double (* _Nonnull function_pointer_recurring_nightmare(float (* _Nonnull x)(NSInteger (* _Nonnull)(double))))(char (* _Nonnull)(unsigned char)) SWIFT_WARN_UNUSED_RESULT SWIFT_NOEXCEPT;
3535
@_cdecl("function_pointer_recurring_nightmare")
3636
public func function_pointer_recurring_nightmare(x: @escaping @convention(c) (@convention(c) (Double) -> Int) -> Float)
3737
-> @convention(c) (@convention(c) (CUnsignedChar) -> CChar) -> Double {
3838
fatalError()
3939
}
4040

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

4545
@objc
4646
class C {}
4747

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

52-
// CHECK-LABEL: SWIFT_EXTERN void return_never(void) SWIFT_NORETURN;
52+
// CHECK-LABEL: SWIFT_EXTERN void return_never(void) SWIFT_NORETURN SWIFT_NOEXCEPT;
5353
@_cdecl("return_never")
5454
func returnNever() -> Never { fatalError() }
5555

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

0 commit comments

Comments
 (0)