Sema: Infer 'dynamic' for overrides of imported methods

Fixes <rdar://problem/31104529>.
This commit is contained in:
Slava Pestov
2017-05-04 23:53:11 -07:00
parent cc707c76e1
commit bcbd1d28fe
3 changed files with 21 additions and 14 deletions

View File

@@ -2522,7 +2522,8 @@ static Optional<ObjCReason> shouldMarkAsObjC(TypeChecker &TC,
/// ///
/// This occurs when /// This occurs when
/// - it is implied by an attribute like @NSManaged /// - 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 /// FIXME: The latter reason is a hack. We should figure out how to safely
/// put extension methods into the class vtable. /// put extension methods into the class vtable.
@@ -2535,11 +2536,15 @@ static void inferDynamic(ASTContext &ctx, ValueDecl *D) {
if (!D->isObjC() || D->hasClangNode()) if (!D->isObjC() || D->hasClangNode())
return; return;
bool overridesImportedMethod =
(D->getOverriddenDecl() &&
D->getOverriddenDecl()->hasClangNode());
// Only introduce 'dynamic' on declarations... // Only introduce 'dynamic' on declarations...
bool isNSManaged = D->getAttrs().hasAttribute<NSManagedAttr>(); bool isNSManaged = D->getAttrs().hasAttribute<NSManagedAttr>();
if (!isa<ExtensionDecl>(D->getDeclContext())) { if (!isa<ExtensionDecl>(D->getDeclContext())) {
// ...and in classes on decls marked @NSManaged. // ...and in classes on decls marked @NSManaged.
if (!isNSManaged) if (!isNSManaged && !overridesImportedMethod)
return; return;
} }

View File

@@ -445,9 +445,9 @@ extension Hoozit {
// Calling objc methods of subclass should go through native entry points // Calling objc methods of subclass should go through native entry points
func useHoozit(_ h: Hoozit) { func useHoozit(_ h: Hoozit) {
// sil @_T011objc_thunks9useHoozityAA0D0C1h_tF // sil @_T011objc_thunks9useHoozityAA0D0C1h_tF
// In the class decl, gets dynamically dispatched // In the class decl, overrides importd method, 'dynamic' was inferred
h.fork() h.fork()
// CHECK: class_method {{%.*}} : {{.*}}, #Hoozit.fork!1 : // CHECK: class_method [volatile] {{%.*}} : {{.*}}, #Hoozit.fork!1.foreign
// In an extension, 'dynamic' was inferred. // In an extension, 'dynamic' was inferred.
h.foof() h.foof()

View File

@@ -88,11 +88,12 @@ class Hoozit : Gizmo {
// Entries only exist for native Swift methods // Entries only exist for native Swift methods
// CHECK: sil_vtable Hoozit { // CHECK: sil_vtable Hoozit {
// CHECK: #Hoozit.frob!1: {{.*}} : _T07vtables6HoozitC4frob{{[_0-9a-zA-Z]*}}F // CHECK-NEXT: #Hoozit.anse!1: {{.*}} : _T07vtables6HoozitC4anse{{[_0-9a-zA-Z]*}}F
// CHECK: #Hoozit.funge!1: {{.*}} : _T07vtables6HoozitC5funge{{[_0-9a-zA-Z]*}}F // CHECK-NEXT: #Hoozit.incorrige!1: {{.*}} : _T07vtables6HoozitC9incorrige{{[_0-9a-zA-Z]*}}F
// CHECK: #Hoozit.anse!1: {{.*}} : _T07vtables6HoozitC4anse{{[_0-9a-zA-Z]*}}F // CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> () -> Hoozit! : _T07vtables6HoozitCSQyACGycfc
// CHECK: #Hoozit.incorrige!1: {{.*}} : _T07vtables6HoozitC9incorrige{{[_0-9a-zA-Z]*}}F // CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> (Int) -> Hoozit! : _T07vtables6HoozitCSQyACGSi7bellsOn_tcfc
// CHECK: } // CHECK-NEXT: #Hoozit.deinit!deallocator: _T07vtables6HoozitCfD
// CHECK-NEXT: }
class Wotsit : Hoozit { class Wotsit : Hoozit {
override func funge() {} override func funge() {}
@@ -100,11 +101,12 @@ class Wotsit : Hoozit {
} }
// CHECK: sil_vtable Wotsit { // CHECK: sil_vtable Wotsit {
// CHECK: #Hoozit.frob!1: {{.*}} : _T07vtables6HoozitC4frob{{[_0-9a-zA-Z]*}}F // CHECK-NEXT: #Hoozit.anse!1: {{.*}} : _T07vtables6HoozitC4anse{{[_0-9a-zA-Z]*}}F
// CHECK: #Hoozit.funge!1: {{.*}} : _T07vtables6WotsitC5funge{{[_0-9a-zA-Z]*}}F // CHECK-NEXT: #Hoozit.incorrige!1: {{.*}} : _T07vtables6WotsitC9incorrige{{[_0-9a-zA-Z]*}}F
// CHECK: #Hoozit.anse!1: {{.*}} : _T07vtables6HoozitC4anse{{[_0-9a-zA-Z]*}}F // CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> () -> Hoozit! : _T07vtables6WotsitCSQyACGycfc
// CHECK: #Hoozit.incorrige!1: {{.*}} : _T07vtables6WotsitC9incorrige{{[_0-9a-zA-Z]*}}F // CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> (Int) -> Hoozit! : _T07vtables6WotsitCSQyACGSi7bellsOn_tcfc
// CHECK: } // CHECK-NEXT: #Wotsit.deinit!deallocator: _T07vtables6WotsitCfD
// CHECK-NEXT: }
// <rdar://problem/15282548> // <rdar://problem/15282548>
// CHECK: sil_vtable Base { // CHECK: sil_vtable Base {