Given these two files:
#import <objc/NSObject.h> @interface Bar : NSObject<NSObject> @end @implementation Bar @end id bar() { return [Bar class]; }
and
#import <objc/NSObject.h> @interface Foo : NSObject<NSObject> @end @implementation Foo @end id foo() { return [Foo class]; }
built with:
xcrun --sdk macosx.internal clang++ foo.m bar.m -o lib.dylib -lobjc -dynamiclib -O2 -Wl,-dead_strip
if you run nm on it, you'll see 2 copies of all the protocol metadata:
$ nm -j lib.dylib | uniq -c | grep 2 2 __OBJC_$_PROP_LIST_NSObject 2 __OBJC_$_PROTOCOL_INSTANCE_METHODS_NSObject 2 __OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_NSObject 2 __OBJC_$_PROTOCOL_METHOD_TYPES_NSObject
This is because some metadata is emitted with internal linkage and default visibility, e.g.:
@"_OBJC_$_PROP_LIST_NSObject" = internal global { i32, i32, [4 x %struct._prop_t] }
This patch changes clang to emit protocol metadata as weak hidden, so that ld64 can deduplicate them.
Fixes rdar://problem/85042564