Skip to content

Commit a0a432e

Browse files
authored
Merge pull request #31351 from slavapestov/empty-field-part-31337-5.3
IRGen: Fix crash with empty-sized field in a class with resilient ancestry [5.3]
2 parents 57dfd41 + fd0cac5 commit a0a432e

File tree

5 files changed

+99
-7
lines changed

5 files changed

+99
-7
lines changed

lib/IRGen/GenClass.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,13 @@ namespace {
273273
// context.
274274
if (superclassType.hasArchetype())
275275
Options |= ClassMetadataFlags::ClassHasGenericLayout;
276+
277+
// Since we're not going to visit the superclass, make sure that we still
278+
// set ClassHasObjCAncestry correctly.
279+
if (superclassType.getASTType()->getReferenceCounting()
280+
== ReferenceCounting::ObjC) {
281+
Options |= ClassMetadataFlags::ClassHasObjCAncestry;
282+
}
276283
} else {
277284
// Otherwise, we are allowed to have total knowledge of the superclass
278285
// fields, so walk them to compute the layout.

test/IRGen/class_resilience_objc.swift

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
3-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %t -enable-library-evolution -enable-objc-interop -emit-ir -o - -primary-file %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize -DINT=i%target-ptrsize
3+
// RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_objc_class.swiftmodule -module-name=resilient_objc_class %S/../Inputs/resilient_objc_class.swift -I %t
4+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %t -enable-library-evolution -emit-ir -o - -primary-file %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize -DINT=i%target-ptrsize
45

5-
// XFAIL: CPU=armv7k
6-
// XFAIL: CPU=powerpc64le
7-
// XFAIL: CPU=s390x
6+
// REQUIRES: objc_interop
87

98
import Foundation
109
import resilient_struct
10+
import resilient_objc_class
1111

1212
// Note that these are all mutable to allow for the runtime to slide them.
1313
// CHECK: @"$s21class_resilience_objc27ClassWithEmptyThenResilientC9resilient0I7_struct0H3IntVvpWvd" = hidden global [[INT]] 0,
1414
// CHECK: @"$s21class_resilience_objc27ClassWithResilientThenEmptyC9resilient0I7_struct0F3IntVvpWvd" = hidden global [[INT]] 0,
15+
// CHECK: @"$s21class_resilience_objc34AnotherClassWithEmptyThenResilientC9resilient0J7_struct0I3IntVvpWvd" = hidden global [[INT]] 0,
16+
// CHECK: @"$s21class_resilience_objc34AnotherClassWithResilientThenEmptyC9resilient0J7_struct0G3IntVvpWvd" = hidden global [[INT]] 0,
17+
1518
// CHECK: @"$s21class_resilience_objc27ClassWithEmptyThenResilientC5emptyAA0F0VvpWvd" = hidden global [[INT]] 0,
1619
// CHECK: @"$s21class_resilience_objc27ClassWithResilientThenEmptyC5emptyAA0H0VvpWvd" = hidden global [[INT]] 0,
20+
// CHECK: @"$s21class_resilience_objc34AnotherClassWithEmptyThenResilientC5emptyAA0G0VvpWvd" = hidden global [[INT]] 0,
21+
// CHECK: @"$s21class_resilience_objc34AnotherClassWithResilientThenEmptyC5emptyAA0I0VvpWvd" = hidden global [[INT]] 0,
1722

1823
public class FixedLayoutObjCSubclass : NSObject {
1924
// This field could use constant direct access because NSObject has
@@ -121,3 +126,26 @@ public class ClassWithResilientThenEmpty : DummyClass {
121126
self.resilient = resilient
122127
}
123128
}
129+
130+
// Same as the above, but the superclass is resilient, and ultimately inherits
131+
// from an Objective-C base class.
132+
133+
public class AnotherClassWithEmptyThenResilient : ResilientNSObjectOutsideParent {
134+
public let empty: Empty
135+
public let resilient: ResilientInt
136+
137+
public init(empty: Empty, resilient: ResilientInt) {
138+
self.empty = empty
139+
self.resilient = resilient
140+
}
141+
}
142+
143+
public class AnotherClassWithResilientThenEmpty : ResilientNSObjectOutsideParent {
144+
public let resilient: ResilientInt
145+
public let empty: Empty
146+
147+
public init(empty: Empty, resilient: ResilientInt) {
148+
self.empty = empty
149+
self.resilient = resilient
150+
}
151+
}

test/Interpreter/Inputs/ObjCClasses/ObjCClasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ NS_ASSUME_NONNULL_BEGIN
88
/* This class has instance variables which are not apparent in the
99
interface. Subclasses will need to be slid by the ObjC runtime. */
1010
@interface HasHiddenIvars : NSObject
11+
- (instancetype)init;
1112
@property NSInteger x;
1213
@property NSInteger y;
1314
@property NSInteger z;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import ObjCClasses
2+
3+
open class HasResilientObjCBaseClass : HasHiddenIvars {}

test/Interpreter/objc_class_resilience.swift

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
// RUN: %empty-directory(%t)
22

33
// RUN: %target-clang -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o
4+
45
// RUN: %target-build-swift-dylib(%t/%target-library-name(resilient_struct)) -enable-library-evolution %S/../Inputs/resilient_struct.swift -emit-module -emit-module-path %t/resilient_struct.swiftmodule -module-name resilient_struct
5-
// RUN: %target-codesign %t/%target-library-name(resilient_struct)
6+
// RUN: %target-build-swift-dylib(%t/%target-library-name(resilient_objc_class)) -enable-library-evolution %S/Inputs/resilient_objc_class.swift -emit-module -emit-module-path %t/resilient_objc_class.swiftmodule -module-name resilient_objc_class -I %S/Inputs/ObjCClasses/ -L %t -Xlinker %t/ObjCClasses.o -framework Foundation
7+
8+
// RUN: %target-codesign %t/%target-library-name(resilient_struct) %t/%target-library-name(resilient_objc_class)
69

7-
// RUN: %target-build-swift %s -L %t -I %t -lresilient_struct -I %S/Inputs/ObjCClasses/ -Xlinker %t/ObjCClasses.o -o %t/main %target-rpath(%t)
10+
// RUN: %target-build-swift %s -L %t -I %t -lresilient_struct -lresilient_objc_class -I %S/Inputs/ObjCClasses/ -o %t/main %target-rpath(%t)
811
// RUN: %target-codesign %t/main
912

10-
// RUN: %target-run %t/main %t/%target-library-name(resilient_struct)
13+
// RUN: %target-run %t/main %t/%target-library-name(resilient_struct) %t/%target-library-name(resilient_objc_class)
1114

1215
// REQUIRES: executable_test
1316
// REQUIRES: objc_interop
1417

1518
import StdlibUnittest
1619
import Foundation
1720
import resilient_struct
21+
import resilient_objc_class
1822
import ObjCClasses
1923

2024

@@ -105,4 +109,53 @@ ResilientClassTestSuite.test("ResilientThenEmpty") {
105109
expectEqual(c.t, 400000)
106110
}
107111

112+
// Same as the above, but the class itself has a resilient base class
113+
class AnotherClassWithEmptyThenResilient : HasResilientObjCBaseClass {
114+
let empty: Empty
115+
let resilient: ResilientInt
116+
117+
init(empty: Empty, resilient: ResilientInt) {
118+
self.empty = empty
119+
self.resilient = resilient
120+
}
121+
}
122+
123+
ResilientClassTestSuite.test("AnotherEmptyThenResilient") {
124+
let c = AnotherClassWithEmptyThenResilient(empty: Empty(),
125+
resilient: ResilientInt(i: 17))
126+
c.x = 100
127+
c.y = 2000
128+
c.z = 30000
129+
c.t = 400000
130+
expectEqual(c.resilient.i, 17)
131+
expectEqual(c.x, 100)
132+
expectEqual(c.y, 2000)
133+
expectEqual(c.z, 30000)
134+
expectEqual(c.t, 400000)
135+
}
136+
137+
class AnotherClassWithResilientThenEmpty : HasHiddenIvars {
138+
let resilient: ResilientInt
139+
let empty: Empty
140+
141+
init(empty: Empty, resilient: ResilientInt) {
142+
self.empty = empty
143+
self.resilient = resilient
144+
}
145+
}
146+
147+
ResilientClassTestSuite.test("AnotherResilientThenEmpty") {
148+
let c = AnotherClassWithResilientThenEmpty(empty: Empty(),
149+
resilient: ResilientInt(i: 17))
150+
c.x = 100
151+
c.y = 2000
152+
c.z = 30000
153+
c.t = 400000
154+
expectEqual(c.resilient.i, 17)
155+
expectEqual(c.x, 100)
156+
expectEqual(c.y, 2000)
157+
expectEqual(c.z, 30000)
158+
expectEqual(c.t, 400000)
159+
}
160+
108161
runAllTests()

0 commit comments

Comments
 (0)