Skip to content

Commit d3868ad

Browse files
committed
IRGen: Perform completely fragile layout for all classes, not just @objc ancestry
Otherwise, Objective C categories don't work for classes with resilient fields, such as the value types defined in the Foundation overlay. Fixes <rdar://problem/40819319>, <https://bugs.swift.org/browse/SR-7882>.
1 parent cd5d738 commit d3868ad

File tree

3 files changed

+35
-52
lines changed

3 files changed

+35
-52
lines changed

lib/IRGen/GenClass.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ namespace {
141141

142142
unsigned NumInherited = 0;
143143

144-
// If the class has @objc ancestry, we lay out resiliently-typed fields
145-
// as if they were fragile.
146-
bool CompletelyFragileLayout = false;
144+
// For now we always lay out resiliently-typed fields as if they
145+
// were fragile.
146+
bool CompletelyFragileLayout;
147147

148148
// Does the class metadata require dynamic initialization above and
149149
// beyond what the runtime can automatically achieve?
@@ -171,6 +171,11 @@ namespace {
171171
ReferenceCounting refcounting)
172172
: StructLayoutBuilder(IGM)
173173
{
174+
// Perform fragile layout if Objective-C interop is enabled.
175+
CompletelyFragileLayout =
176+
(IGM.Context.LangOpts.EnableObjCInterop &&
177+
!IGM.IRGen.Opts.EnableClassResilience);
178+
174179
// Start by adding a heap header.
175180
switch (refcounting) {
176181
case ReferenceCounting::Native:
@@ -249,10 +254,6 @@ namespace {
249254
}
250255

251256
if (superclass->hasClangNode()) {
252-
// Perform fragile layout if the class has @objc ancestry.
253-
if (!IGM.IRGen.Opts.EnableClassResilience)
254-
CompletelyFragileLayout = true;
255-
256257
// If the superclass was imported from Objective-C, its size is
257258
// not known at compile time. However, since the field offset
258259
// vector only stores offsets of stored properties defined in
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
3+
// RUN: %target-swift-frontend -I %t -emit-ir -enable-resilience %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize -DINT=i%target-ptrsize
4+
// RUN: %target-swift-frontend -I %t -emit-ir -enable-resilience -O %s
5+
6+
// REQUIRES: objc_interop
7+
8+
import resilient_struct
9+
10+
// Class has static metadata:
11+
// CHECK-LABEL: $S31completely_fragile_class_layout23ClassWithResilientFieldCMf
12+
13+
// CHECK-LABEL: define swiftcc %swift.metadata_response @"$S31completely_fragile_class_layout23ClassWithResilientFieldCMa
14+
// CHECK: call %objc_class* @swift_getInitializedObjCClass(%objc_class* {{.*}} @"$S31completely_fragile_class_layout23ClassWithResilientFieldCMf"
15+
// CHECK: ret
16+
17+
public class ClassWithResilientField {
18+
var first: Int
19+
var second: Size
20+
var third: Int
21+
22+
init(x: Int, y: Size, z: Int) {
23+
self.first = x
24+
self.second = y
25+
self.third = z
26+
}
27+
}

test/IRGen/objc_class_resilience.swift

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)