Skip to content

Commit f0c3bc2

Browse files
committed
[IRGen] Don't emit ObjC class property metadata on old targets. (#2350)
The ObjC runtime on OS X 10.10 and older and iOS 9 and older can't handle them, so for these targets, emit nil for all class property lists. It's a little unfortunate that this is target-dependent, but there's not much we can do about it. rdar://problem/25605427
1 parent 3105ef9 commit f0c3bc2

File tree

5 files changed

+136
-45
lines changed

5 files changed

+136
-45
lines changed

lib/IRGen/GenClass.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,12 +1648,20 @@ namespace {
16481648
llvm::Constant *buildPropertyList(ForMetaClass_t classOrMeta) {
16491649
Size eltSize = 2 * IGM.getPointerSize();
16501650
StringRef namePrefix;
1651+
16511652
if (classOrMeta == ForClass) {
16521653
return buildOptionalList(InstanceProperties, eltSize,
16531654
chooseNamePrefix("_PROPERTIES_",
16541655
"_CATEGORY_PROPERTIES_",
16551656
"_PROTOCOL_PROPERTIES_"));
16561657
}
1658+
1659+
// Older OSs' libobjcs can't handle class property data.
1660+
if ((IGM.Triple.isMacOSX() && IGM.Triple.isMacOSXVersionLT(10, 11)) ||
1661+
(IGM.Triple.isiOS() && IGM.Triple.isOSVersionLT(9))) {
1662+
return null();
1663+
}
1664+
16571665
return buildOptionalList(ClassProperties, eltSize,
16581666
chooseNamePrefix("_CLASS_PROPERTIES_",
16591667
"_CATEGORY_CLASS_PROPERTIES_",

test/IRGen/objc_properties.swift

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
// RUN: %target-swift-frontend %s -emit-ir -disable-objc-attr-requires-foundation-module | FileCheck %s
1+
// This file is also used by objc_properties_ios.swift.
22

3-
// REQUIRES: CPU=x86_64
3+
// RUN: %swift -target x86_64-apple-macosx10.11 %s -disable-target-os-checking -emit-ir -disable-objc-attr-requires-foundation-module | FileCheck -check-prefix=CHECK -check-prefix=CHECK-NEW %s
4+
// RUN: %swift -target x86_64-apple-macosx10.10 %s -disable-target-os-checking -emit-ir -disable-objc-attr-requires-foundation-module | FileCheck -check-prefix=CHECK -check-prefix=CHECK-OLD %s
5+
6+
// REQUIRES: OS=macosx
47
// REQUIRES: objc_interop
58

69
@objc class SomeObject {
@@ -94,22 +97,23 @@ class Class17127126 {
9497
// CHECK: [[SHARED_NAME:@.*]] = private unnamed_addr constant [11 x i8] c"sharedProp\00"
9598
// CHECK: [[SHARED_ATTRS:@.*]] = private unnamed_addr constant [17 x i8] c"Tq,N,VsharedProp\00"
9699

97-
// CHECK: @_CLASS_PROPERTIES__TtC15objc_properties10SomeObject = private constant { {{.*}}] } {
98-
// CHECK: i32 16,
99-
// CHECK: i32 1,
100-
// CHECK: [1 x { i8*, i8* }] [{
101-
// CHECK: i8* getelementptr inbounds ([11 x i8], [11 x i8]* [[SHARED_NAME]], i64 0, i64 0),
102-
// CHECK: i8* getelementptr inbounds ([17 x i8], [17 x i8]* [[SHARED_ATTRS]], i64 0, i64 0)
103-
// CHECK: }]
104-
// CHECK: }, section "__DATA, __objc_const", align 8
100+
// CHECK-NEW: @_CLASS_PROPERTIES__TtC15objc_properties10SomeObject = private constant { {{.*}}] } {
101+
// CHECK-NEW: i32 16,
102+
// CHECK-NEW: i32 1,
103+
// CHECK-NEW: [1 x { i8*, i8* }] [{
104+
// CHECK-NEW: i8* getelementptr inbounds ([11 x i8], [11 x i8]* [[SHARED_NAME]], i64 0, i64 0),
105+
// CHECK-NEW: i8* getelementptr inbounds ([17 x i8], [17 x i8]* [[SHARED_ATTRS]], i64 0, i64 0)
106+
// CHECK-NEW: }]
107+
// CHECK-NEW: }, section "__DATA, __objc_const", align 8
105108

106109
// CHECK: @_METACLASS_DATA__TtC15objc_properties10SomeObject = private constant { {{.*}} } {
107110
// CHECK-SAME: i32 {{[0-9]+}}, i32 {{[0-9]+}}, i32 {{[0-9]+}}, i32 {{[0-9]+}},
108111
// CHECK-SAME: i8* null,
109112
// CHECK-SAME: i8* getelementptr inbounds ([{{.+}} x i8], [{{.+}} x i8]* {{@.+}}, i64 0, i64 0),
110113
// CHECK-SAME: { {{.+}} }* @_CLASS_METHODS__TtC15objc_properties10SomeObject,
111114
// CHECK-SAME: i8* null, i8* null, i8* null,
112-
// CHECK-SAME: { {{.+}} }* @_CLASS_PROPERTIES__TtC15objc_properties10SomeObject
115+
// CHECK-NEW-SAME: { {{.+}} }* @_CLASS_PROPERTIES__TtC15objc_properties10SomeObject
116+
// CHECK-OLD-SAME: i8* null
113117
// CHECK-SAME: }, section "__DATA, __objc_const", align 8
114118

115119
// CHECK: @_INSTANCE_METHODS__TtC15objc_properties10SomeObject = private constant { {{.*}}] } {
@@ -207,14 +211,14 @@ class Class17127126 {
207211
// CHECK: }]
208212
// CHECK: }, section "__DATA, __objc_const", align 8
209213

210-
// CHECK: @"_CATEGORY_CLASS_PROPERTIES__TtC15objc_properties10SomeObject_$_objc_properties" = private constant { {{.*}}] } {
211-
// CHECK: i32 16,
212-
// CHECK: i32 1,
213-
// CHECK: [1 x { i8*, i8* }] [{
214-
// CHECK: i8* getelementptr inbounds ([19 x i8], [19 x i8]* [[EXTENSIONCLASSPROPERTY_NAME]], i64 0, i64 0),
215-
// CHECK: i8* getelementptr inbounds ([7 x i8], [7 x i8]* [[EXTENSIONCLASSPROPERTY_ATTRS]], i64 0, i64 0)
216-
// CHECK: }]
217-
// CHECK: }, section "__DATA, __objc_const", align 8
214+
// CHECK-NEW: @"_CATEGORY_CLASS_PROPERTIES__TtC15objc_properties10SomeObject_$_objc_properties" = private constant { {{.*}}] } {
215+
// CHECK-NEW: i32 16,
216+
// CHECK-NEW: i32 1,
217+
// CHECK-NEW: [1 x { i8*, i8* }] [{
218+
// CHECK-NEW: i8* getelementptr inbounds ([19 x i8], [19 x i8]* [[EXTENSIONCLASSPROPERTY_NAME]], i64 0, i64 0),
219+
// CHECK-NEW: i8* getelementptr inbounds ([7 x i8], [7 x i8]* [[EXTENSIONCLASSPROPERTY_ATTRS]], i64 0, i64 0)
220+
// CHECK-NEW: }]
221+
// CHECK-NEW: }, section "__DATA, __objc_const", align 8
218222

219223
// CHECK: @"_CATEGORY__TtC15objc_properties10SomeObject_$_objc_properties" = private constant { {{.+}} } {
220224
// CHECK: i8* getelementptr inbounds ([{{.+}} x i8], [{{.+}} x i8]* {{@.+}}, i64 0, i64 0),
@@ -223,7 +227,8 @@ class Class17127126 {
223227
// CHECK: { {{.+}} }* @"_CATEGORY_CLASS_METHODS__TtC15objc_properties10SomeObject_$_objc_properties",
224228
// CHECK: i8* null,
225229
// CHECK: { {{.+}} }* @"_CATEGORY_PROPERTIES__TtC15objc_properties10SomeObject_$_objc_properties",
226-
// CHECK: { {{.+}} }* @"_CATEGORY_CLASS_PROPERTIES__TtC15objc_properties10SomeObject_$_objc_properties",
230+
// CHECK-NEW: { {{.+}} }* @"_CATEGORY_CLASS_PROPERTIES__TtC15objc_properties10SomeObject_$_objc_properties",
231+
// CHECK-OLD: i8* null,
227232
// CHECK: i32 60
228233
// CHECK: }, section "__DATA, __objc_const", align 8
229234

@@ -248,7 +253,8 @@ class Class17127126 {
248253
// CHECK: i32 96, i32 1,
249254
// CHECK: { {{.+}} }* @_PROTOCOL_METHOD_TYPES__TtP15objc_properties5Proto_,
250255
// CHECK: i8* null,
251-
// CHECK: { {{.+}} }* @_PROTOCOL_CLASS_PROPERTIES__TtP15objc_properties5Proto_
256+
// CHECK-NEW: { {{.+}} }* @_PROTOCOL_CLASS_PROPERTIES__TtP15objc_properties5Proto_
257+
// CHECK-OLD: i8* null
252258
// CHECK: }, section "__DATA, __objc_const", align 8
253259

254260

@@ -267,11 +273,11 @@ class Class17127126 {
267273
// CHECK: }]
268274
// CHECK: }, section "__DATA, __objc_const", align 8
269275

270-
// CHECK: @_PROTOCOL_CLASS_PROPERTIES__TtP15objc_properties5Proto_ = private constant { {{.*}}] } {
271-
// CHECK: i32 16,
272-
// CHECK: i32 1,
273-
// CHECK: [1 x { i8*, i8* }] [{
274-
// CHECK: i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[PROTOCOLCLASSPROPERTY_NAME]], i64 0, i64 0),
275-
// CHECK: i8* getelementptr inbounds ([7 x i8], [7 x i8]* [[PROTOCOLCLASSPROPERTY_ATTRS]], i64 0, i64 0)
276-
// CHECK: }]
277-
// CHECK: }, section "__DATA, __objc_const", align 8
276+
// CHECK-NEW: @_PROTOCOL_CLASS_PROPERTIES__TtP15objc_properties5Proto_ = private constant { {{.*}}] } {
277+
// CHECK-NEW: i32 16,
278+
// CHECK-NEW: i32 1,
279+
// CHECK-NEW: [1 x { i8*, i8* }] [{
280+
// CHECK-NEW: i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[PROTOCOLCLASSPROPERTY_NAME]], i64 0, i64 0),
281+
// CHECK-NEW: i8* getelementptr inbounds ([7 x i8], [7 x i8]* [[PROTOCOLCLASSPROPERTY_ATTRS]], i64 0, i64 0)
282+
// CHECK-NEW: }]
283+
// CHECK-NEW: }, section "__DATA, __objc_const", align 8

test/IRGen/objc_properties_ios.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %swift -target x86_64-apple-ios9 %S/objc_properties.swift -disable-target-os-checking -emit-ir -disable-objc-attr-requires-foundation-module | FileCheck -check-prefix=CHECK -check-prefix=CHECK-NEW %S/objc_properties.swift
2+
// RUN: %swift -target x86_64-apple-ios8 %S/objc_properties.swift -disable-target-os-checking -emit-ir -disable-objc-attr-requires-foundation-module | FileCheck -check-prefix=CHECK -check-prefix=CHECK-OLD %S/objc_properties.swift
3+
4+
// REQUIRES: OS=ios
5+
// REQUIRES: CPU=x86_64
6+
// REQUIRES: objc_interop

test/Interpreter/objc_class_properties.swift

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,7 @@ class NamingConflictSubclass : PropertyNamingConflict {
175175
override class var prop: AnyObject? { return NamingConflictSubclass() }
176176
}
177177

178-
ClassProperties.test("namingConflict")
179-
.skip(.osxMinorRange(10, 0...10, reason: "unexpected failures on 10.10"))
180-
.code {
178+
ClassProperties.test("namingConflict") {
181179
let obj = PropertyNamingConflict()
182180
expectTrue(obj === obj.prop)
183181
expectEmpty(obj.dynamicType.prop)
@@ -200,9 +198,7 @@ extension NamingConflictSubclass : PropertyNamingConflictProto {
200198
}
201199
}
202200

203-
ClassProperties.test("namingConflict/protocol")
204-
.skip(.osxMinorRange(10, 0...10, reason: "unexpected failures on 10.10"))
205-
.code {
201+
ClassProperties.test("namingConflict/protocol") {
206202
let obj: PropertyNamingConflictProto = NamingConflictSubclass()
207203
expectTrue(obj === obj.protoProp)
208204
expectEmpty(obj.dynamicType.protoProp)
@@ -211,15 +207,5 @@ ClassProperties.test("namingConflict/protocol")
211207
expectEmpty(type.protoProp)
212208
}
213209

214-
ClassProperties.test("runtime") {
215-
let theClass: AnyObject = SwiftClass.self
216-
let prop = class_getProperty(object_getClass(theClass), "value")
217-
expectTrue(prop != nil)
218-
219-
let nameAsCString = property_getName(prop)
220-
expectTrue(nameAsCString != nil)
221-
expectEqual("value", String(cString: nameAsCString))
222-
}
223-
224210
runAllTests()
225211

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// RUN: rm -rf %t && mkdir -p %t
2+
3+
// RUN: %clang -arch x86_64 -mmacosx-version-min=10.11 -isysroot %sdk -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o
4+
5+
// RUN: %swiftc_driver -target $(echo '%target-triple' | sed -E -e 's/macosx10.(9|10).*/macosx10.11/') -sdk %sdk -I %S/Inputs/ObjCClasses/ %t/ObjCClasses.o %s -o %t/a.out
6+
// RUN: %t/a.out
7+
8+
// REQUIRES: OS=macosx
9+
// REQUIRES: executable_test
10+
// REQUIRES: objc_interop
11+
12+
import Foundation
13+
import StdlibUnittest
14+
import ObjCClasses
15+
16+
class SwiftClass : ProtoWithClassProperty {
17+
static var getCount = 0
18+
static var setCount = 0
19+
20+
private static var _value: CInt = 0
21+
22+
@objc class func reset() {
23+
getCount = 0
24+
setCount = 0
25+
_value = 0
26+
}
27+
28+
@objc class var value: CInt {
29+
get {
30+
getCount += 1
31+
return _value
32+
}
33+
set {
34+
setCount += 1
35+
_value = newValue
36+
}
37+
}
38+
39+
@objc class var optionalClassProp: Bool {
40+
return true
41+
}
42+
}
43+
44+
class Subclass : ClassWithClassProperty {
45+
static var getCount = 0
46+
static var setCount = 0
47+
48+
override class func reset() {
49+
getCount = 0
50+
setCount = 0
51+
super.reset()
52+
}
53+
54+
override class var value: CInt {
55+
get {
56+
getCount += 1
57+
return super.value
58+
}
59+
set {
60+
setCount += 1
61+
super.value = newValue
62+
}
63+
}
64+
65+
override class var optionalClassProp: Bool {
66+
return true
67+
}
68+
}
69+
70+
var ClassProperties = TestSuite("ClassProperties")
71+
72+
ClassProperties.test("runtime")
73+
.skip(.osxMinorRange(10, 0...10, reason: "not supported on 10.10 or below"))
74+
.code {
75+
let theClass: AnyObject = SwiftClass.self
76+
let prop = class_getProperty(object_getClass(theClass), "value")
77+
expectNotEmpty(prop)
78+
79+
let nameAsCString = property_getName(prop)
80+
expectNotEmpty(nameAsCString)
81+
expectEqual("value", String(cString: nameAsCString))
82+
}
83+
84+
runAllTests()
85+

0 commit comments

Comments
 (0)