Merge pull request #9407 from slavapestov/use-objc-msgsend-for-overrides-of-imported-methods
Use objc_msgSend() for overrides of imported methods [4.0]
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 69c1412..68bec97 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -2139,6 +2139,8 @@
}
if (superclassCtor->isRequired())
ctor->getAttrs().add(new (tc.Context) RequiredAttr(/*IsImplicit=*/true));
+ if (superclassCtor->isDynamic())
+ ctor->getAttrs().add(new (tc.Context) DynamicAttr(/*IsImplicit*/true));
// Wire up the overrides.
ctor->getAttrs().add(new (tc.Context) OverrideAttr(/*IsImplicit=*/true));
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 26b31cb..bf17898 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -2472,7 +2472,8 @@
///
/// This occurs when
/// - it is implied by an attribute like @NSManaged
-/// - we need to dynamically dispatch to a method in an extension.
+/// - when we have an override of an imported method
+/// - we need to dynamically dispatch to a method in an extension
///
/// FIXME: The latter reason is a hack. We should figure out how to safely
/// put extension methods into the class vtable.
@@ -2485,11 +2486,15 @@
if (!D->isObjC() || D->hasClangNode())
return;
+ bool overridesImportedMethod =
+ (D->getOverriddenDecl() &&
+ D->getOverriddenDecl()->hasClangNode());
+
// Only introduce 'dynamic' on declarations...
bool isNSManaged = D->getAttrs().hasAttribute<NSManagedAttr>();
if (!isa<ExtensionDecl>(D->getDeclContext())) {
// ...and in classes on decls marked @NSManaged.
- if (!isNSManaged)
+ if (!isNSManaged && !overridesImportedMethod)
return;
}
diff --git a/test/SILGen/dynamic.swift b/test/SILGen/dynamic.swift
index 4a15ffd..c33ebb1 100644
--- a/test/SILGen/dynamic.swift
+++ b/test/SILGen/dynamic.swift
@@ -235,6 +235,23 @@
dynamic override func overriddenByDynamic() {}
}
+class SubclassWithInheritedInits: Foo {
+ // CHECK-LABEL: sil hidden @_T07dynamic26SubclassWithInheritedInitsC{{[_0-9a-zA-Z]*}}fc
+ // CHECK: super_method [volatile] {{%.*}} : $SubclassWithInheritedInits, #Foo.init!initializer.1.foreign :
+}
+class GrandchildWithInheritedInits: SubclassWithInheritedInits {
+ // CHECK-LABEL: sil hidden @_T07dynamic28GrandchildWithInheritedInitsC{{[_0-9a-zA-Z]*}}fc
+ // CHECK: super_method [volatile] {{%.*}} : $GrandchildWithInheritedInits, #SubclassWithInheritedInits.init!initializer.1.foreign :
+}
+class GrandchildOfInheritedInits: SubclassWithInheritedInits {
+ // Dynamic methods are super-dispatched by objc_msgSend
+ override init(dynamic: Int) {
+ super.init(dynamic: dynamic)
+ }
+ // CHECK-LABEL: sil hidden @_T07dynamic26GrandchildOfInheritedInitsC{{[_0-9a-zA-Z]*}}fc
+ // CHECK: super_method [volatile] {{%.*}} : $GrandchildOfInheritedInits, #SubclassWithInheritedInits.init!initializer.1.foreign :
+}
+
// CHECK-LABEL: sil hidden @_T07dynamic20nativeMethodDispatchyyF : $@convention(thin) () -> ()
func nativeMethodDispatch() {
// CHECK: function_ref @_T07dynamic3{{[_0-9a-zA-Z]*}}fC
@@ -508,6 +525,25 @@
// CHECK: #Foo.overriddenByDynamic!1: {{.*}} : public _T07dynamic8SubclassC19overriddenByDynamic{{[_0-9a-zA-Z]*}}FTD
// CHECK: }
+// Check vtables for implicitly-inherited initializers
+// CHECK-LABEL: sil_vtable SubclassWithInheritedInits {
+// CHECK: #Foo.init!initializer.1: (Foo.Type) -> (Int) -> Foo : _T07dynamic26SubclassWithInheritedInitsCACSi6native_tcfc
+// CHECK: #Foo.init!initializer.1: (Foo.Type) -> (Int) -> Foo : _T07dynamic26SubclassWithInheritedInitsCACSi4objc_tcfc
+// CHECK-NOT: .init!
+// CHECK: }
+
+// CHECK-LABEL: sil_vtable GrandchildWithInheritedInits {
+// CHECK: #Foo.init!initializer.1: (Foo.Type) -> (Int) -> Foo : _T07dynamic28GrandchildWithInheritedInitsCACSi6native_tcfc
+// CHECK: #Foo.init!initializer.1: (Foo.Type) -> (Int) -> Foo : _T07dynamic28GrandchildWithInheritedInitsCACSi4objc_tcfc
+// CHECK-NOT: .init!
+// CHECK: }
+
+// CHECK-LABEL: sil_vtable GrandchildOfInheritedInits {
+// CHECK: #Foo.init!initializer.1: (Foo.Type) -> (Int) -> Foo : _T07dynamic26GrandchildOfInheritedInitsCACSi6native_tcfc
+// CHECK: #Foo.init!initializer.1: (Foo.Type) -> (Int) -> Foo : _T07dynamic26GrandchildOfInheritedInitsCACSi4objc_tcfc
+// CHECK-NOT: .init!
+// CHECK: }
+
// No vtable entry for override of @objc extension property
// CHECK-LABEL: sil_vtable SubExt {
// CHECK-NEXT: #BaseExt.init!initializer.1: (BaseExt.Type) -> () -> BaseExt : _T07dynamic6SubExtCACycfc // dynamic.SubExt.init() -> dynamic.SubExt
diff --git a/test/SILGen/objc_thunks.swift b/test/SILGen/objc_thunks.swift
index 032c157..c43a24d 100644
--- a/test/SILGen/objc_thunks.swift
+++ b/test/SILGen/objc_thunks.swift
@@ -445,9 +445,9 @@
// Calling objc methods of subclass should go through native entry points
func useHoozit(_ h: Hoozit) {
// sil @_T011objc_thunks9useHoozityAA0D0C1h_tF
- // In the class decl, gets dynamically dispatched
+ // In the class decl, overrides importd method, 'dynamic' was inferred
h.fork()
- // CHECK: class_method {{%.*}} : {{.*}}, #Hoozit.fork!1 :
+ // CHECK: class_method [volatile] {{%.*}} : {{.*}}, #Hoozit.fork!1.foreign
// In an extension, 'dynamic' was inferred.
h.foof()
diff --git a/test/SILGen/vtables.swift b/test/SILGen/vtables.swift
index 20e9b3e..dfc100b 100644
--- a/test/SILGen/vtables.swift
+++ b/test/SILGen/vtables.swift
@@ -88,11 +88,12 @@
// Entries only exist for native Swift methods
// CHECK: sil_vtable Hoozit {
-// CHECK: #Hoozit.frob!1: {{.*}} : _T07vtables6HoozitC4frob{{[_0-9a-zA-Z]*}}F
-// CHECK: #Hoozit.funge!1: {{.*}} : _T07vtables6HoozitC5funge{{[_0-9a-zA-Z]*}}F
-// CHECK: #Hoozit.anse!1: {{.*}} : _T07vtables6HoozitC4anse{{[_0-9a-zA-Z]*}}F
-// CHECK: #Hoozit.incorrige!1: {{.*}} : _T07vtables6HoozitC9incorrige{{[_0-9a-zA-Z]*}}F
-// CHECK: }
+// CHECK-NEXT: #Hoozit.anse!1: {{.*}} : _T07vtables6HoozitC4anse{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: #Hoozit.incorrige!1: {{.*}} : _T07vtables6HoozitC9incorrige{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> () -> Hoozit! : _T07vtables6HoozitCSQyACGycfc
+// CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> (Int) -> Hoozit! : _T07vtables6HoozitCSQyACGSi7bellsOn_tcfc
+// CHECK-NEXT: #Hoozit.deinit!deallocator: _T07vtables6HoozitCfD
+// CHECK-NEXT: }
class Wotsit : Hoozit {
override func funge() {}
@@ -100,11 +101,12 @@
}
// CHECK: sil_vtable Wotsit {
-// CHECK: #Hoozit.frob!1: {{.*}} : _T07vtables6HoozitC4frob{{[_0-9a-zA-Z]*}}F
-// CHECK: #Hoozit.funge!1: {{.*}} : _T07vtables6WotsitC5funge{{[_0-9a-zA-Z]*}}F
-// CHECK: #Hoozit.anse!1: {{.*}} : _T07vtables6HoozitC4anse{{[_0-9a-zA-Z]*}}F
-// CHECK: #Hoozit.incorrige!1: {{.*}} : _T07vtables6WotsitC9incorrige{{[_0-9a-zA-Z]*}}F
-// CHECK: }
+// CHECK-NEXT: #Hoozit.anse!1: {{.*}} : _T07vtables6HoozitC4anse{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: #Hoozit.incorrige!1: {{.*}} : _T07vtables6WotsitC9incorrige{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> () -> Hoozit! : _T07vtables6WotsitCSQyACGycfc
+// CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> (Int) -> Hoozit! : _T07vtables6WotsitCSQyACGSi7bellsOn_tcfc
+// CHECK-NEXT: #Wotsit.deinit!deallocator: _T07vtables6WotsitCfD
+// CHECK-NEXT: }
// <rdar://problem/15282548>
// CHECK: sil_vtable Base {