Skip to content

Commit 89d0d62

Browse files
jtbandesjrose-apple
authored andcommitted
[PrintAsObjC] print __attribute__((noescape)) in Obj-C headers (#4438)
https://bugs.swift.org/browse/SR-2406
1 parent 7b3b0e2 commit 89d0d62

File tree

12 files changed

+202
-53
lines changed

12 files changed

+202
-53
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,7 @@ namespace {
492492
// FIXME: If we were walking TypeLocs, we could actually get parameter
493493
// names. The probably doesn't matter outside of a FuncDecl, which
494494
// we'll have to special-case, but it's an interesting bit of data loss.
495+
// We also lose `noescape`. <https://bugs.swift.org/browse/SR-2529>
495496
params.push_back(swiftParamTy);
496497
}
497498

lib/PrintAsObjC/PrintAsObjC.cpp

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ namespace {
8181
Normal = false,
8282
CustomNamesOnly = true,
8383
};
84+
85+
/// Whether the type being printed is in function param position.
86+
enum IsFunctionParam_t : bool {
87+
IsFunctionParam = true,
88+
IsNotFunctionParam = false,
89+
};
8490
}
8591

8692
static StringRef getNameForObjC(const ValueDecl *VD,
@@ -361,7 +367,7 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
361367
(clangParam && isNSUInteger(clangParam->getType()))) {
362368
os << "NSUInteger";
363369
} else {
364-
print(param->getType(), OTK_None);
370+
print(param->getType(), OTK_None, Identifier(), IsFunctionParam);
365371
}
366372
os << ")";
367373

@@ -542,19 +548,6 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
542548

543549
os << ";\n";
544550
}
545-
546-
void printSingleFunctionParam(const ParamDecl *param) {
547-
// The type name may be multi-part.
548-
PrintMultiPartType multiPart(*this);
549-
visitPart(param->getType(), OTK_None);
550-
auto name = param->getName();
551-
if (name.empty())
552-
return;
553-
554-
os << ' ' << name;
555-
if (isClangKeyword(name))
556-
os << "_";
557-
}
558551

559552
void printAbstractFunctionAsFunction(FuncDecl *FD) {
560553
printDocumentationComment(FD);
@@ -578,7 +571,8 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
578571
auto params = FD->getParameterLists().back();
579572
interleave(*params,
580573
[&](const ParamDecl *param) {
581-
printSingleFunctionParam(param);
574+
print(param->getType(), OTK_None, param->getName(),
575+
IsFunctionParam);
582576
},
583577
[&]{ os << ", "; });
584578

@@ -1437,12 +1431,13 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
14371431
} else {
14381432
interleave(tupleTy->getElements(),
14391433
[this](TupleTypeElt elt) {
1440-
print(elt.getType(), OTK_None, elt.getName());
1434+
print(elt.getType(), OTK_None, elt.getName(),
1435+
IsFunctionParam);
14411436
},
14421437
[this] { os << ", "; });
14431438
}
14441439
} else {
1445-
print(paramsTy, OTK_None);
1440+
print(paramsTy, OTK_None, Identifier(), IsFunctionParam);
14461441
}
14471442
os << ")";
14481443
}
@@ -1516,9 +1511,16 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
15161511
/// visitPart().
15171512
public:
15181513
void print(Type ty, Optional<OptionalTypeKind> optionalKind,
1519-
Identifier name = Identifier()) {
1514+
Identifier name = Identifier(),
1515+
IsFunctionParam_t isFuncParam = IsNotFunctionParam) {
15201516
PrettyStackTraceType trace(M.getASTContext(), "printing", ty);
15211517

1518+
if (isFuncParam)
1519+
if (auto fnTy = ty->lookThroughAllAnyOptionalTypes()
1520+
->getAs<AnyFunctionType>())
1521+
if (fnTy->isNoEscape())
1522+
os << "SWIFT_NOESCAPE ";
1523+
15221524
PrintMultiPartType multiPart(*this);
15231525
visitPart(ty, optionalKind);
15241526
if (!name.empty()) {
@@ -2104,6 +2106,11 @@ class ModuleWriter {
21042106
"#else\n"
21052107
"# define SWIFT_METHOD_FAMILY(X)\n"
21062108
"#endif\n"
2109+
"#if defined(__has_attribute) && __has_attribute(noescape)\n"
2110+
"# define SWIFT_NOESCAPE __attribute__((noescape))\n"
2111+
"#else\n"
2112+
"# define SWIFT_NOESCAPE\n"
2113+
"#endif\n"
21072114
"#if !defined(SWIFT_CLASS_EXTRA)\n"
21082115
"# define SWIFT_CLASS_EXTRA\n"
21092116
"#endif\n"

lib/Sema/TypeCheckType.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,6 +1418,7 @@ static Type applyNonEscapingFromContext(DeclContext *DC,
14181418
// FIXME: It would be better to add a new AttributedType sugared type,
14191419
// which would wrap the NameAliasType or ParenType, and apply the
14201420
// isNoEscape bit when de-sugaring.
1421+
// <https://bugs.swift.org/browse/SR-2520>
14211422
return FunctionType::get(funcTy->getInput(), funcTy->getResult(), extInfo);
14221423
}
14231424

test/ClangModules/blocks_parse.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ func testNoEscape(f: @convention(block) () -> Void, nsStr: NSString,
1919
fStr: (String!) -> Void) {
2020
accepts_noescape_block(f)
2121
accepts_noescape_block(f)
22+
23+
// Please see related tests in PrintAsObjC/imported-block-typedefs.swift.
2224

2325
// rdar://problem/19818617
2426
nsStr.enumerateLines(fStr) // okay due to @noescape

test/Inputs/clang-importer-sdk/usr/include/blocks.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ my_block_t __nullable blockWithNullable();
1919
void accepts_block(my_block_t) __attribute__((nonnull));
2020
void accepts_noescape_block(__attribute__((noescape)) my_block_t) __attribute__((nonnull));
2121

22+
// Please see related tests in PrintAsObjC/imported-block-typedefs.swift.
23+

test/PrintAsObjC/Inputs/comments-expected-output.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ SWIFT_CLASS("_TtC8comments16ClosureContainer")
127127
\a combine error: Nothing.
128128
129129
*/
130-
- (void)closureParameterExplodedExplodedWithA:(NSInteger)a combine:(NSInteger (^ _Nonnull)(NSInteger, NSInteger))combine;
130+
- (void)closureParameterExplodedExplodedWithA:(NSInteger)a combine:(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(NSInteger, NSInteger))combine;
131131
/**
132132
Partially applies a binary operator.
133133
\param a The left-hand side to partially apply.
@@ -150,7 +150,7 @@ SWIFT_CLASS("_TtC8comments16ClosureContainer")
150150
\a combine error: Nothing.
151151
152152
*/
153-
- (void)closureParameterOutlineExplodedWithA:(NSInteger)a combine:(NSInteger (^ _Nonnull)(NSInteger, NSInteger))combine;
153+
- (void)closureParameterOutlineExplodedWithA:(NSInteger)a combine:(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(NSInteger, NSInteger))combine;
154154
/**
155155
Partially applies a binary operator.
156156
\param a The left-hand side to partially apply.
@@ -173,7 +173,7 @@ SWIFT_CLASS("_TtC8comments16ClosureContainer")
173173
\a combine error: Nothing.
174174
175175
*/
176-
- (void)closureParameterOutlineOutlineWithA:(NSInteger)a combine:(NSInteger (^ _Nonnull)(NSInteger, NSInteger))combine;
176+
- (void)closureParameterOutlineOutlineWithA:(NSInteger)a combine:(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(NSInteger, NSInteger))combine;
177177
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
178178
@end
179179

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
typedef void (^PlainBlock)(void);
2+
typedef void (^BlockWithEscapingParam)(PlainBlock);
3+
typedef void (^BlockWithNoescapeParam)(__attribute__((noescape)) PlainBlock);
4+
typedef BlockWithEscapingParam (^BlockReturningBlockWithEscapingParam)(void);
5+
typedef BlockWithNoescapeParam (^BlockReturningBlockWithNoescapeParam)(void);

test/PrintAsObjC/blocks.swift

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,98 +14,136 @@ import ObjectiveC
1414
typealias MyTuple = (Int, AnyObject?)
1515
typealias MyNamedTuple = (a: Int, b: AnyObject?)
1616
typealias MyInt = Int
17+
typealias MyBlockWithEscapingParam = (@escaping () -> ()) -> Int
18+
typealias MyBlockWithNoescapeParam = (() -> ()) -> Int
19+
20+
// Please see related tests in PrintAsObjC/imported-block-typedefs.swift.
1721

1822
// CHECK-LABEL: @interface Callbacks
19-
// CHECK-NEXT: - (void (^ _Nonnull)(void))voidBlocks:(void (^ _Nonnull)(void))input;
20-
// CHECK-NEXT: - (void)manyArguments:(void (^ _Nonnull)(float, float, double, double))input;
21-
// CHECK-NEXT: - (void)blockTakesBlock:(void (^ _Nonnull)(void (^ _Nonnull)(void)))input;
22-
// CHECK-NEXT: - (void)blockReturnsBlock:(void (^ _Nonnull (^ _Nonnull)(void))(void))input;
23-
// CHECK-NEXT: - (void)blockTakesAndReturnsBlock:(uint8_t (^ _Nonnull (^ _Nonnull)(uint16_t (^ _Nonnull)(int16_t)))(int8_t))input;
24-
// CHECK-NEXT: - (void)blockTakesTwoBlocksAndReturnsBlock:(uint8_t (^ _Nonnull (^ _Nonnull)(uint16_t (^ _Nonnull)(int16_t), uint32_t (^ _Nonnull)(int32_t)))(int8_t))input;
25-
// CHECK-NEXT: - (void (^ _Nullable)(NSObject * _Nonnull))returnsBlockWithInput;
26-
// CHECK-NEXT: - (void (^ _Nullable)(NSObject * _Nonnull))returnsBlockWithParenthesizedInput;
27-
// CHECK-NEXT: - (void (^ _Nullable)(NSObject * _Nonnull, NSObject * _Nonnull))returnsBlockWithTwoInputs;
28-
// CHECK-NEXT: - (void)blockWithTypealias:(NSInteger (^ _Nonnull)(NSInteger, id _Nullable))input;
29-
// CHECK-NEXT: - (void)blockWithSimpleTypealias:(NSInteger (^ _Nonnull)(NSInteger))input;
30-
// CHECK-NEXT: - (void)namedArguments:(void (^ _Nonnull)(float, float, double, double))input;
31-
// CHECK-NEXT: - (void)blockTakesNamedBlock:(void (^ _Nonnull)(void (^ _Nonnull)(void)))input;
32-
// CHECK-NEXT: - (void (^ _Nullable)(NSObject * _Nonnull))returnsBlockWithNamedInput;
33-
// CHECK-NEXT: - (void)blockWithTypealiasWithNames:(NSInteger (^ _Nonnull)(NSInteger a, id _Nullable b))input;
34-
// CHECK-NEXT: - (void)blockWithKeyword:(NSInteger (^ _Nonnull)(NSInteger))_Nullable_;
35-
// CHECK-NEXT: - (NSInteger (* _Nonnull)(NSInteger))functionPointers:(NSInteger (* _Nonnull)(NSInteger))input;
36-
// CHECK-NEXT: - (void)functionPointerTakesAndReturnsFunctionPointer:(NSInteger (* _Nonnull (^ _Nonnull (* _Nonnull)(NSInteger))(NSInteger))(NSInteger))input;
37-
// CHECK-NEXT: - (NSInteger (* _Nonnull)(NSInteger))functionPointersWithName:(NSInteger (* _Nonnull)(NSInteger))input;
38-
// CHECK-NEXT: @property (nonatomic, copy) NSInteger (^ _Nullable savedBlock)(NSInteger);
39-
// CHECK-NEXT: @property (nonatomic, copy) NSInteger (^ _Nullable savedBlockWithName)(NSInteger);
40-
// CHECK-NEXT: @property (nonatomic) NSInteger (* _Nonnull savedFunctionPointer)(NSInteger);
41-
// CHECK-NEXT: @property (nonatomic) NSInteger (* _Nullable savedFunctionPointer2)(NSInteger);
42-
// CHECK-NEXT: @property (nonatomic) NSInteger (* _Nonnull savedFunctionPointerWithName)(NSInteger);
43-
// CHECK-NEXT: @property (nonatomic, copy, getter=this, setter=setThis:) NSInteger (^ _Nonnull this_)(NSInteger);
44-
// CHECK-NEXT: @property (nonatomic, getter=class, setter=setClass:) NSInteger (* _Nonnull class_)(NSInteger);
45-
// CHECK-NEXT: init
46-
// CHECK-NEXT: @end
4723
@objc class Callbacks {
24+
25+
// CHECK-NEXT: - (void (^ _Nonnull)(void))voidBlocks:(void (^ _Nonnull)(void))input;
4826
func voidBlocks(_ input: @escaping () -> ()) -> () -> () {
4927
return input
5028
}
29+
30+
// CHECK-NEXT: - (void)manyArguments:(void (^ _Nonnull)(float, float, double, double))input;
5131
func manyArguments(_ input: @escaping (Float, Float, Double, Double) -> ()) {}
5232

33+
// CHECK-NEXT: - (void)blockTakesBlock:(void (^ _Nonnull)(SWIFT_NOESCAPE void (^ _Nonnull)(void)))input;
5334
func blockTakesBlock(_ input: @escaping (() -> ()) -> ()) {}
35+
36+
// CHECK-NEXT: - (void)blockReturnsBlock:(void (^ _Nonnull (^ _Nonnull)(void))(void))input;
5437
func blockReturnsBlock(_ input: @escaping () -> () -> ()) {}
38+
39+
// CHECK-NEXT: - (void)blockTakesAndReturnsBlock:(SWIFT_NOESCAPE uint8_t (^ _Nonnull (^ _Nonnull)(SWIFT_NOESCAPE uint16_t (^ _Nonnull)(int16_t)))(int8_t))input;
5540
func blockTakesAndReturnsBlock(_ input:
5641
((Int16) -> (UInt16)) ->
5742
((Int8) -> (UInt8))) {}
43+
44+
// CHECK-NEXT: - (void)blockTakesTwoBlocksAndReturnsBlock:(SWIFT_NOESCAPE uint8_t (^ _Nonnull (^ _Nonnull)(SWIFT_NOESCAPE uint16_t (^ _Nonnull)(int16_t), SWIFT_NOESCAPE uint32_t (^ _Nonnull)(int32_t)))(int8_t))input;
5845
func blockTakesTwoBlocksAndReturnsBlock(_ input:
5946
((Int16) -> (UInt16),
6047
(Int32) -> (UInt32)) ->
6148
((Int8) -> (UInt8))) {}
6249

50+
// CHECK-NEXT: - (void (^ _Nullable)(NSObject * _Nonnull))returnsBlockWithInput;
6351
func returnsBlockWithInput() -> ((NSObject) -> ())? {
6452
return nil
6553
}
54+
55+
// CHECK-NEXT: - (void (^ _Nullable)(NSObject * _Nonnull))returnsBlockWithParenthesizedInput;
6656
func returnsBlockWithParenthesizedInput() -> ((NSObject) -> ())? {
6757
return nil
6858
}
59+
60+
// CHECK-NEXT: - (void (^ _Nullable)(NSObject * _Nonnull, NSObject * _Nonnull))returnsBlockWithTwoInputs;
6961
func returnsBlockWithTwoInputs() -> ((NSObject, NSObject) -> ())? {
7062
return nil
7163
}
7264

65+
// CHECK-NEXT: - (void)blockWithTypealias:(NSInteger (^ _Nonnull)(NSInteger, id _Nullable))input;
7366
func blockWithTypealias(_ input: @escaping (MyTuple) -> MyInt) {}
67+
68+
// CHECK-NEXT: - (void)blockWithSimpleTypealias:(NSInteger (^ _Nonnull)(NSInteger))input;
7469
func blockWithSimpleTypealias(_ input: @escaping (MyInt) -> MyInt) {}
7570

71+
// CHECK-NEXT: - (void)namedArguments:(void (^ _Nonnull)(float, float, double, double))input;
7672
func namedArguments(_ input: @escaping (_ f1: Float, _ f2: Float, _ d1: Double, _ d2: Double) -> ()) {}
73+
74+
// CHECK-NEXT: - (void)blockTakesNamedBlock:(void (^ _Nonnull)(SWIFT_NOESCAPE void (^ _Nonnull)(void)))input;
7775
func blockTakesNamedBlock(_ input: @escaping (_ block: () -> ()) -> ()) {}
76+
77+
// CHECK-NEXT: - (void (^ _Nullable)(NSObject * _Nonnull))returnsBlockWithNamedInput;
7878
func returnsBlockWithNamedInput() -> ((_ object: NSObject) -> ())? {
7979
return nil
8080
}
8181

82+
// CHECK-NEXT: - (void)blockWithTypealiasWithNames:(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(NSInteger a, id _Nullable b))input;
8283
func blockWithTypealiasWithNames(_ input: (MyNamedTuple) -> MyInt) {}
8384

85+
// CHECK-NEXT: - (void)blockWithKeyword:(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(NSInteger))_Nullable_;
8486
func blockWithKeyword(_ _Nullable: (_ `class`: Int) -> Int) {}
8587

88+
// CHECK-NEXT: - (NSInteger (* _Nonnull)(NSInteger))functionPointers:(NSInteger (* _Nonnull)(NSInteger))input;
8689
func functionPointers(_ input: @escaping @convention(c) (Int) -> Int)
8790
-> @convention(c) (Int) -> Int {
8891
return input
8992
}
9093

94+
// CHECK-NEXT: - (void)blockWithBlockTypealias:(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(void (^ _Nonnull)(void)))block;
95+
func blockWithBlockTypealias(_ block: MyBlockWithEscapingParam) {}
96+
97+
// CHECK-NEXT: - (void)blockWithBlockTypealias2:(NSInteger (^ _Nonnull)(void (^ _Nonnull)(void)))block;
98+
func blockWithBlockTypealias2(_ block: @escaping MyBlockWithEscapingParam) {}
99+
100+
// CHECK-NEXT: - (void)blockWithBlockTypealias3:(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(SWIFT_NOESCAPE void (^ _Nonnull)(void)))block;
101+
func blockWithBlockTypealias3(_ block: MyBlockWithNoescapeParam) {}
102+
103+
// CHECK-NEXT: - (void)blockWithBlockTypealias4:(NSInteger (^ _Nonnull)(SWIFT_NOESCAPE void (^ _Nonnull)(void)))block;
104+
func blockWithBlockTypealias4(_ block: @escaping MyBlockWithNoescapeParam) {}
105+
106+
// CHECK-NEXT: - (void)functionPointerTakesAndReturnsFunctionPointer:(NSInteger (* _Nonnull (^ _Nonnull (* _Nonnull)(NSInteger))(NSInteger))(NSInteger))input;
91107
func functionPointerTakesAndReturnsFunctionPointer(
92108
_ input: @escaping @convention(c) (Int) -> (Int)
93109
-> @convention(c) (Int) -> Int
94110
) {
95111
}
112+
113+
// CHECK-NEXT: - (void (* _Nonnull)(SWIFT_NOESCAPE NSInteger (* _Nonnull)(NSInteger, NSInteger)))returnsFunctionPointerThatTakesFunctionPointer;
114+
func returnsFunctionPointerThatTakesFunctionPointer() ->
115+
@convention(c) (_ comparator: @convention(c) (_ x: Int, _ y: Int) -> Int) -> Void {
116+
fatalError()
117+
}
96118

119+
// CHECK-NEXT: - (NSInteger (* _Nonnull)(NSInteger))functionPointersWithName:(NSInteger (* _Nonnull)(NSInteger))input;
97120
func functionPointersWithName(_ input: @escaping @convention(c) (_ value: Int) -> Int)
98121
-> @convention(c) (_ result: Int) -> Int {
99122
return input
100123
}
101124

125+
// CHECK-NEXT: @property (nonatomic, copy) NSInteger (^ _Nullable savedBlock)(NSInteger);
102126
var savedBlock: ((Int) -> Int)?
127+
128+
// CHECK-NEXT: @property (nonatomic, copy) NSInteger (^ _Nullable savedBlockWithName)(NSInteger);
103129
var savedBlockWithName: ((_ x: Int) -> Int)?
130+
131+
// CHECK-NEXT: @property (nonatomic) NSInteger (* _Nonnull savedFunctionPointer)(NSInteger);
104132
var savedFunctionPointer: @convention(c) (Int) -> Int = { $0 }
133+
134+
// CHECK-NEXT: @property (nonatomic) NSInteger (* _Nullable savedFunctionPointer2)(NSInteger);
105135
var savedFunctionPointer2: (@convention(c) (Int) -> Int)? = { $0 }
136+
137+
// CHECK-NEXT: @property (nonatomic) NSInteger (* _Nonnull savedFunctionPointerWithName)(NSInteger);
106138
var savedFunctionPointerWithName: @convention(c) (_ x: Int) -> Int = { $0 }
107139

108140
// The following uses a clang keyword as the name.
141+
142+
// CHECK-NEXT: @property (nonatomic, copy, getter=this, setter=setThis:) NSInteger (^ _Nonnull this_)(NSInteger);
109143
var this: (_ block: Int) -> Int = { $0 }
144+
145+
// CHECK-NEXT: @property (nonatomic, getter=class, setter=setClass:) NSInteger (* _Nonnull class_)(NSInteger);
110146
var `class`: @convention(c) (_ function: Int) -> Int = { $0 }
111147
}
148+
// CHECK-NEXT: init
149+
// CHECK-NEXT: @end

test/PrintAsObjC/cdecl.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,35 @@
1111
// CHECK: /**
1212
// CHECK-NEXT: What a nightmare!
1313
// CHECK: */
14-
// CHECK-LABEL: double (^ _Nonnull block_nightmare(float (^ _Nonnull x)(NSInteger)))(char);
14+
// CHECK-LABEL: double (^ _Nonnull block_nightmare(SWIFT_NOESCAPE float (^ _Nonnull x)(NSInteger)))(char);
1515

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

21+
// CHECK-LABEL: double (^ _Nonnull block_recurring_nightmare(float (^ _Nonnull x)(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(double))))(SWIFT_NOESCAPE char (^ _Nonnull)(unsigned char));
22+
@_cdecl("block_recurring_nightmare")
23+
public func block_recurring_nightmare(x: @escaping @convention(block) (@convention(block) (Double) -> Int) -> Float)
24+
-> @convention(block) (_ asdfasdf: @convention(block) (CUnsignedChar) -> CChar) -> Double {
25+
fatalError()
26+
}
27+
2128
// CHECK-LABEL: void foo_bar(NSInteger x, NSInteger y);
2229
@_cdecl("foo_bar")
2330
func foo(x: Int, bar y: Int) {}
2431

25-
// CHECK-LABEL: double (* _Nonnull function_pointer_nightmare(float (* _Nonnull x)(NSInteger)))(char);
32+
// CHECK-LABEL: double (* _Nonnull function_pointer_nightmare(SWIFT_NOESCAPE float (* _Nonnull x)(NSInteger)))(char);
2633
@_cdecl("function_pointer_nightmare")
2734
func function_pointer_nightmare(x: @convention(c) (Int) -> Float)
2835
-> @convention(c) (CChar) -> Double { return { _ in 0 } }
36+
37+
// CHECK-LABEL: double (* _Nonnull function_pointer_recurring_nightmare(float (* _Nonnull x)(SWIFT_NOESCAPE NSInteger (* _Nonnull)(double))))(SWIFT_NOESCAPE char (* _Nonnull)(unsigned char));
38+
@_cdecl("function_pointer_recurring_nightmare")
39+
public func function_pointer_recurring_nightmare(x: @escaping @convention(c) (@convention(c) (Double) -> Int) -> Float)
40+
-> @convention(c) (@convention(c) (CUnsignedChar) -> CChar) -> Double {
41+
fatalError()
42+
}
2943

3044
// CHECK-LABEL: void has_keyword_arg_names(NSInteger auto_, NSInteger union_);
3145
@_cdecl("has_keyword_arg_names")

test/PrintAsObjC/classes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ public class NonObjCClass { }
690690
// CHECK-NEXT: - (nullable instancetype)method4AndReturnError:(NSError * _Nullable * _Nullable)error;
691691
// CHECK-NEXT: - (nullable instancetype)initAndReturnError:(NSError * _Nullable * _Nullable)error OBJC_DESIGNATED_INITIALIZER;
692692
// CHECK-NEXT: - (nullable instancetype)initWithString:(NSString * _Nonnull)string error:(NSError * _Nullable * _Nullable)error OBJC_DESIGNATED_INITIALIZER;
693-
// CHECK-NEXT: - (nullable instancetype)initAndReturnError:(NSError * _Nullable * _Nullable)error fn:(NSInteger (^ _Nonnull)(NSInteger))fn OBJC_DESIGNATED_INITIALIZER;
693+
// CHECK-NEXT: - (nullable instancetype)initAndReturnError:(NSError * _Nullable * _Nullable)error fn:(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(NSInteger))fn OBJC_DESIGNATED_INITIALIZER;
694694
// CHECK-NEXT: @end
695695
@objc class Throwing1 {
696696
func method1() throws { }

0 commit comments

Comments
 (0)