mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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>.
This commit is contained in:
@@ -141,9 +141,9 @@ namespace {
|
||||
|
||||
unsigned NumInherited = 0;
|
||||
|
||||
// If the class has @objc ancestry, we lay out resiliently-typed fields
|
||||
// as if they were fragile.
|
||||
bool CompletelyFragileLayout = false;
|
||||
// For now we always lay out resiliently-typed fields as if they
|
||||
// were fragile.
|
||||
bool CompletelyFragileLayout;
|
||||
|
||||
// Does the class metadata require dynamic initialization above and
|
||||
// beyond what the runtime can automatically achieve?
|
||||
@@ -171,6 +171,11 @@ namespace {
|
||||
ReferenceCounting refcounting)
|
||||
: StructLayoutBuilder(IGM)
|
||||
{
|
||||
// Perform fragile layout if Objective-C interop is enabled.
|
||||
CompletelyFragileLayout =
|
||||
(IGM.Context.LangOpts.EnableObjCInterop &&
|
||||
!IGM.IRGen.Opts.EnableClassResilience);
|
||||
|
||||
// Start by adding a heap header.
|
||||
switch (refcounting) {
|
||||
case ReferenceCounting::Native:
|
||||
@@ -249,10 +254,6 @@ namespace {
|
||||
}
|
||||
|
||||
if (superclass->hasClangNode()) {
|
||||
// Perform fragile layout if the class has @objc ancestry.
|
||||
if (!IGM.IRGen.Opts.EnableClassResilience)
|
||||
CompletelyFragileLayout = true;
|
||||
|
||||
// If the superclass was imported from Objective-C, its size is
|
||||
// not known at compile time. However, since the field offset
|
||||
// vector only stores offsets of stored properties defined in
|
||||
|
||||
27
test/IRGen/completely_fragile_class_layout.swift
Normal file
27
test/IRGen/completely_fragile_class_layout.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
|
||||
// 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
|
||||
// RUN: %target-swift-frontend -I %t -emit-ir -enable-resilience -O %s
|
||||
|
||||
// REQUIRES: objc_interop
|
||||
|
||||
import resilient_struct
|
||||
|
||||
// Class has static metadata:
|
||||
// CHECK-LABEL: $S31completely_fragile_class_layout23ClassWithResilientFieldCMf
|
||||
|
||||
// CHECK-LABEL: define swiftcc %swift.metadata_response @"$S31completely_fragile_class_layout23ClassWithResilientFieldCMa
|
||||
// CHECK: call %objc_class* @swift_getInitializedObjCClass(%objc_class* {{.*}} @"$S31completely_fragile_class_layout23ClassWithResilientFieldCMf"
|
||||
// CHECK: ret
|
||||
|
||||
public class ClassWithResilientField {
|
||||
var first: Int
|
||||
var second: Size
|
||||
var third: Int
|
||||
|
||||
init(x: Int, y: Size, z: Int) {
|
||||
self.first = x
|
||||
self.second = y
|
||||
self.third = z
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %utils/chex.py < %s > %t/objc_class_resilience.swift
|
||||
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
|
||||
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -I %t -emit-ir -enable-resilience %t/objc_class_resilience.swift | %FileCheck %t/objc_class_resilience.swift --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize -DINT=i%target-ptrsize
|
||||
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -I %t -emit-ir -enable-resilience -O %t/objc_class_resilience.swift
|
||||
|
||||
// REQUIRES: objc_interop
|
||||
|
||||
import ObjectiveC
|
||||
import resilient_struct
|
||||
|
||||
// CHECK-32-LABEL: @"$S21objc_class_resilience23ClassWithResilientFieldC5firstSivpWvd" = hidden global i32 4
|
||||
// CHECK-64-LABEL: @"$S21objc_class_resilience23ClassWithResilientFieldC5firstSivpWvd" = hidden global i64 8
|
||||
|
||||
// CHECK-32-LABEL: @"$S21objc_class_resilience23ClassWithResilientFieldC6second16resilient_struct4SizeVvpWvd" = hidden global i32 8
|
||||
// CHECK-64-LABEL: @"$S21objc_class_resilience23ClassWithResilientFieldC6second16resilient_struct4SizeVvpWvd" = hidden global i64 16
|
||||
|
||||
// CHECK-32-LABEL: @"$S21objc_class_resilience23ClassWithResilientFieldC5thirdSivpWvd" = hidden global i32 16
|
||||
// CHECK-64-LABEL: @"$S21objc_class_resilience23ClassWithResilientFieldC5thirdSivpWvd" = hidden global i64 32
|
||||
|
||||
// CHECK-LABEL: @"OBJC_CLASS_$__TtC21objc_class_resilience23ClassWithResilientField" = alias
|
||||
|
||||
// CHECK-LABEL: define hidden swiftcc {{i32|i64}} @"$S21objc_class_resilience23ClassWithResilientFieldC5firstSivg"(%T21objc_class_resilience23ClassWithResilientFieldC* swiftself) {{.*}} {
|
||||
// CHECK: %offset = load [[INT]], [[INT]]* @"$S21objc_class_resilience23ClassWithResilientFieldC5firstSivpWvd"
|
||||
// CHECK: }
|
||||
|
||||
// CHECK-LABEL: define hidden swiftcc void @"$S21objc_class_resilience23ClassWithResilientFieldC6second16resilient_struct4SizeVvg"(%swift.opaque* noalias nocapture sret, %T21objc_class_resilience23ClassWithResilientFieldC* swiftself) {{.*}} {
|
||||
// CHECK: %offset = load [[INT]], [[INT]]* @"$S21objc_class_resilience23ClassWithResilientFieldC6second16resilient_struct4SizeVvpWvd"
|
||||
// CHECK: }
|
||||
|
||||
// CHECK-LABEL: define hidden swiftcc {{i32|i64}} @"$S21objc_class_resilience23ClassWithResilientFieldC5thirdSivg"(%T21objc_class_resilience23ClassWithResilientFieldC* swiftself) {{.*}} {
|
||||
// CHECK: %offset = load [[INT]], [[INT]]* @"$S21objc_class_resilience23ClassWithResilientFieldC5thirdSivpWvd"
|
||||
// CHECK: }
|
||||
|
||||
public class ClassWithResilientField : NSObject {
|
||||
var first: Int
|
||||
var second: Size
|
||||
var third: Int
|
||||
|
||||
init(x: Int, y: Size, z: Int) {
|
||||
self.first = x
|
||||
self.second = y
|
||||
self.third = z
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user