From f9e28aff2a78425beb7225808e9780b4ccda6659 Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 15 Nov 2017 03:09:04 -0500 Subject: [PATCH] When building a block-to-func reabstraction thunk, be sure to bridge the block's formal parameter and result types, because otherwise the bridging code gets real confused. Fixes rdar://35402696 --- lib/SILGen/SILGenBridging.cpp | 14 ++++++++++---- .../Inputs/usr/include/BridgeTestFoundation.h | 2 ++ test/SILGen/objc_blocks_bridging.swift | 8 ++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index 6a2784c7afab6..ae0d27273d3af 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -355,6 +355,12 @@ expandTupleTypes(AnyFunctionType::CanParamArrayRef params) { return results; } +static CanAnyFunctionType getBridgedBlockType(SILGenModule &SGM, + CanAnyFunctionType blockType) { + return SGM.Types.getBridgedFunctionType(AbstractionPattern(blockType), + blockType, blockType->getExtInfo()); +} + static void buildFuncToBlockInvokeBody(SILGenFunction &SGF, SILLocation loc, CanAnyFunctionType formalFuncType, @@ -368,10 +374,7 @@ static void buildFuncToBlockInvokeBody(SILGenFunction &SGF, SILFunctionConventions funcConv(funcTy, SGF.SGM.M); // Make sure we lower the component types of the formal block type. - formalBlockType = - SGF.SGM.Types.getBridgedFunctionType(AbstractionPattern(formalBlockType), - formalBlockType, - formalBlockType->getExtInfo()); + formalBlockType = getBridgedBlockType(SGF.SGM, formalBlockType); // Set up the indirect result. SILType blockResultTy = blockTy->getAllResultsType(); @@ -764,6 +767,9 @@ static void buildBlockToFuncThunkBody(SILGenFunction &SGF, // Collect the native arguments, which should all be +1. Scope scope(SGF.Cleanups, CleanupLocation::get(loc)); + // Make sure we lower the component types of the formal block type. + formalBlockTy = getBridgedBlockType(SGF.SGM, formalBlockTy); + assert(blockTy->getNumParameters() == funcTy->getNumParameters() && "block and function types don't match"); diff --git a/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h b/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h index 2d59069a6194b..456b446659aff 100644 --- a/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h +++ b/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h @@ -93,3 +93,5 @@ void escapeBlockAlias(dispatch_block_t block); @interface ObjectWithSplitProperty : NSObject @property (nonatomic, setter=private_setFlagForSomething:) BOOL flagForSomething; @end + +extern NSString * __nonnull (^ const __nonnull GlobalBlock)(NSString * __nonnull); diff --git a/test/SILGen/objc_blocks_bridging.swift b/test/SILGen/objc_blocks_bridging.swift index cb3ef5928dc8f..08b07c31146d0 100644 --- a/test/SILGen/objc_blocks_bridging.swift +++ b/test/SILGen/objc_blocks_bridging.swift @@ -188,3 +188,11 @@ struct GenericStruct { // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0Ix_Ixx_IyB_IyBy_TR : $@convention(c) (@inout_aliasable @block_storage @noescape @callee_owned (@owned @noescape @callee_owned () -> ()) -> (), @convention(block) @noescape () -> ()) -> () // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0IyB_Ix_TR : $@convention(thin) (@owned @convention(block) @noescape () -> ()) -> () +// rdar://35402696 +func takeOptStringFunction(fn: (String) -> String?) {} +func testGlobalBlock() { + takeOptStringFunction(fn: GlobalBlock) +} +// CHECK-LABEL: sil hidden @_T020objc_blocks_bridging15testGlobalBlockyyF +// CHECK: global_addr @GlobalBlock : $*@convention(block) (NSString) -> @autoreleased Optional +// CHECK: function_ref @_T0So8NSStringCABSgIeyBya_S2SIexxo_TR : $@convention(thin) (@owned String, @owned @convention(block) (NSString) -> @autoreleased Optional) -> @owned String