Skip to content
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

Fix initialization of imported ObjC block types. #73577

Merged
merged 1 commit into from
May 13, 2024
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
15 changes: 14 additions & 1 deletion lib/SIL/IR/ValueOwnership.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,9 +652,22 @@ UNOWNED_OR_NONE_DEPENDING_ON_RESULT(AtomicLoad)
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(ExtractElement)
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(InsertElement)
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(ShuffleVector)
UNOWNED_OR_NONE_DEPENDING_ON_RESULT(ZeroInitializer)
#undef UNOWNED_OR_NONE_DEPENDING_ON_RESULT

#define OWNED_OR_NONE_DEPENDING_ON_RESULT(ID) \
ValueOwnershipKind ValueOwnershipKindBuiltinVisitor::visit##ID( \
BuiltinInst *BI, StringRef Attr) { \
if (BI->getType().isTrivial(*BI->getFunction())) { \
return OwnershipKind::None; \
} \
return OwnershipKind::Owned; \
}
// A zeroInitializer may initialize an imported struct with __unsafe_unretained
// fields. The initialized value is immediately consumed by an assignment, so it
// must be owned.
OWNED_OR_NONE_DEPENDING_ON_RESULT(ZeroInitializer)
#undef OWNED_OR_NONE_DEPENDING_ON_RESULT

#define BUILTIN(X,Y,Z)
#define BUILTIN_SIL_OPERATION(ID, NAME, CATEGORY) \
ValueOwnershipKind ValueOwnershipKindBuiltinVisitor::visit##ID( \
Expand Down
7 changes: 7 additions & 0 deletions test/ClangImporter/Inputs/objc_init_blocks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#import <CoreFoundation/CoreFoundation.h>

typedef bool (^boolBlock)(void);

struct objc_bool_block {
__unsafe_unretained boolBlock block;
};
18 changes: 18 additions & 0 deletions test/ClangImporter/objc_init_blocks.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: %target-swift-frontend -import-objc-header %S/Inputs/objc_init_blocks.h %s -emit-sil -sil-verify-all

// REQUIRES: objc_interop

// rdar://126142109: import an __unsafe_unretained block as zero-initialized.
//
// Make sure that the SIL ownership verifier passes.
// UnsafeUnretainedBlockClass.init()
// CHECK-LABEL: sil hidden @$s16objc_init_blocks26UnsafeUnretainedBlockClassCACycfc : $@convention(method) (@owned UnsafeUnretainedBlockClass) -> @owned UnsafeUnretainedBlockClass {
// CHECK: [[ZI:%.*]] = builtin "zeroInitializer"<objc_bool_block>() : $objc_bool_block
// CHECK: store [[ZI]] to %{{.*}} : $*objc_bool_block
// CHECK-LABEL: } // end sil function '$s16objc_init_blocks26UnsafeUnretainedBlockClassCACycfc'
open class UnsafeUnretainedBlockClass {
public internal(set) var sc: objc_bool_block
init() {
self.sc = objc_bool_block()
}
}