[ModuleInterface] Add printing for new attributes

Specially print @_hasMissingDesignatedInitializers and @_inheritsConvenienceInitializers in module interfaces

Fixes rdar://51249311
This commit is contained in:
Harlan Haskins
2019-11-19 16:53:43 -08:00
committed by Robert Widmann
parent 283854a012
commit 511db0c90a
8 changed files with 176 additions and 12 deletions

View File

@@ -990,6 +990,22 @@ void PrintAST::printAttributes(const Decl *D) {
Printer << " ";
}
}
// If the declaration has designated inits that won't be visible to
// clients, or if it inherits superclass convenience initializers,
// then print those attributes specially.
if (auto CD = dyn_cast<ClassDecl>(D)) {
if (Options.PrintImplicitAttrs) {
if (CD->inheritsSuperclassInitializers()) {
Printer.printAttrName("@_inheritsConvenienceInitializers");
Printer << " ";
}
if (CD->hasMissingDesignatedInitializers()) {
Printer.printAttrName("@_hasMissingDesignatedInitializers");
Printer << " ";
}
}
}
}
D->getAttrs().print(Printer, Options, D);

View File

@@ -452,7 +452,7 @@ class d0120_TestClassBase {
}
class d0121_TestClassDerived : d0120_TestClassBase {
// PASS_COMMON-LABEL: {{^}}class d0121_TestClassDerived : d0120_TestClassBase {{{$}}
// PASS_COMMON-LABEL: {{^}}@_inheritsConvenienceInitializers {{()?}}class d0121_TestClassDerived : d0120_TestClassBase {{{$}}
required init() { super.init() }
// PASS_COMMON-NEXT: {{^}} required init(){{$}}
@@ -611,8 +611,8 @@ struct d0200_EscapedIdentifiers {
// PASS_ONE_LINE_TYPEREPR-DAG: {{^}} typealias `protocol` = `class`{{$}}
class `extension` : `class` {}
// PASS_ONE_LINE_TYPE-DAG: {{^}} class `extension` : d0200_EscapedIdentifiers.`class` {{{$}}
// PASS_ONE_LINE_TYPEREPR-DAG: {{^}} class `extension` : `class` {{{$}}
// PASS_ONE_LINE_TYPE-DAG: {{^}} @_inheritsConvenienceInitializers class `extension` : d0200_EscapedIdentifiers.`class` {{{$}}
// PASS_ONE_LINE_TYPEREPR-DAG: {{^}} @_inheritsConvenienceInitializers class `extension` : `class` {{{$}}
// PASS_COMMON: {{^}} @objc deinit{{$}}
// PASS_COMMON-NEXT: {{^}} {{(override )?}}init(){{$}}
// PASS_COMMON-NEXT: {{^}} }{{$}}
@@ -748,7 +748,7 @@ class d0260_ExplodePattern_TestClassBase {
}
class d0261_ExplodePattern_TestClassDerived : d0260_ExplodePattern_TestClassBase {
// PASS_EXPLODE_PATTERN-LABEL: {{^}}class d0261_ExplodePattern_TestClassDerived : d0260_ExplodePattern_TestClassBase {{{$}}
// PASS_EXPLODE_PATTERN-LABEL: {{^}}@_inheritsConvenienceInitializers class d0261_ExplodePattern_TestClassDerived : d0260_ExplodePattern_TestClassBase {{{$}}
override final var baseProp2: Int {
get {
@@ -791,13 +791,13 @@ class ClassWithInheritance2 : FooProtocol, BarProtocol {}
// PASS_ONE_LINE-DAG: {{^}}class ClassWithInheritance2 : FooProtocol, BarProtocol {{{$}}
class ClassWithInheritance3 : FooClass {}
// PASS_ONE_LINE-DAG: {{^}}class ClassWithInheritance3 : FooClass {{{$}}
// PASS_ONE_LINE-DAG: {{^}}@_inheritsConvenienceInitializers class ClassWithInheritance3 : FooClass {{{$}}
class ClassWithInheritance4 : FooClass, FooProtocol {}
// PASS_ONE_LINE-DAG: {{^}}class ClassWithInheritance4 : FooClass, FooProtocol {{{$}}
// PASS_ONE_LINE-DAG: {{^}}@_inheritsConvenienceInitializers class ClassWithInheritance4 : FooClass, FooProtocol {{{$}}
class ClassWithInheritance5 : FooClass, FooProtocol, BarProtocol {}
// PASS_ONE_LINE-DAG: {{^}}class ClassWithInheritance5 : FooClass, FooProtocol, BarProtocol {{{$}}
// PASS_ONE_LINE-DAG: {{^}}@_inheritsConvenienceInitializers class ClassWithInheritance5 : FooClass, FooProtocol, BarProtocol {{{$}}
class ClassWithInheritance6 : QuxProtocol, SubFooProtocol {
typealias Qux = Int

View File

@@ -0,0 +1,41 @@
// Compile the imported module to a .swiftinterface and ensure the convenience
// init delegates through the subclasses correctly.
// RUN: %empty-directory(%t)
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module)) %S/inherits-superclass-initializers.swift -emit-module-path %t/Module.swiftmodule -emit-module-interface-path %t/Module.swiftinterface -module-name Module -enable-library-evolution
// RUN: rm %t/Module.swiftmodule
// RUN: %target-build-swift %s -I %t -L %t -lModule -o %t/main %target-rpath(%t)
// RUN: %target-codesign %t/main %t/%target-library-name(Module)
// RUN: %target-run %t/main %t/%target-library-name(Module) | %FileCheck %s
// Make sure the same error is emitted when importing a .swiftmodule
// RUN: %empty-directory(%t)
// RUN: %target-build-swift-dylib(%t/%target-library-name(Module)) %S/inherits-superclass-initializers.swift -emit-module-path %t/Module.swiftmodule -module-name Module -enable-library-evolution
// RUN: %target-build-swift %s -I %t -L %t -lModule -o %t/main %target-rpath(%t)
// RUN: %target-codesign %t/main %t/%target-library-name(Module)
// RUN: %target-run %t/main %t/%target-library-name(Module) | %FileCheck %s
import Module
_ = Base()
// CHECK: secret init from Base
_ = Sub()
// CHECK: secret init from Sub
// CHECK: secret init from Base
_ = SubSub()
// CHECK: secret init from SubSub
// CHECK: secret init from Sub
// CHECK: secret init from Base
test()
// CHECK: secret init from Sub
// CHECK: secret init from Base
// CHECK: secret init from SubSub
// CHECK: secret init from Sub
// CHECK: secret init from Base
// CHECK-NOT: public init

View File

@@ -0,0 +1,60 @@
// Note: this test has a client: inherits-superclass-initializers-client.swift
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -typecheck %s -emit-module-interface-path %t/Module.swiftinterface -module-name Module -enable-library-evolution
// RUN: %FileCheck %s < %t/Module.swiftinterface
// CHECK: @_hasMissingDesignatedInitializers open class Base {
open class Base {
// CHECK-NEXT: public init(arg: Swift.Int)
public init(arg: Int) {
print("public init from Base")
}
// CHECK-NOT: init(secret: Swift.Int)
internal init(secret: Int) {
print("secret init from Base")
}
// CHECK: convenience public init()
public convenience init() {
self.init(secret: 4)
}
// CHECK: }
}
// CHECK: @_inheritsConvenienceInitializers @_hasMissingDesignatedInitializers public class Sub : Module.Base {
public class Sub : Base {
// CHECK: override public init(arg: Swift.Int)
public override init(arg: Int) {
print("public init from Sub")
super.init(arg: arg)
}
// CHECK-NOT: init(secret: Swift.Int)
internal override init(secret: Int) {
print("secret init from Sub")
super.init(secret: secret)
}
// CHECK: }
}
// CHECK: @_inheritsConvenienceInitializers @_hasMissingDesignatedInitializers public class SubSub : Module.Sub {
public class SubSub: Sub {
// CHECK: override public init(arg: Swift.Int)
public override init(arg: Int) {
print("public init from SubSub")
super.init(arg: arg)
}
// CHECK-NOT: init(secret: Swift.Int)
internal override init(secret: Int) {
print("secret init from SubSub")
super.init(secret: secret)
}
// CHECK: }
}
@inlinable public func test() {
_ = Sub()
_ = SubSub()
}

View File

@@ -0,0 +1,26 @@
// Compile the imported module to a .swiftinterface and ensure the convenience
// init cannot be called.
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -typecheck %S/non-public-designated-inits.swift -emit-module-interface-path %t/Module.swiftinterface -module-name Module -enable-library-evolution
// RUN: %target-swift-frontend -typecheck -verify %s -I %t
// Make sure the same error is emitted when importing a .swiftmodule
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t/Module.swiftmodule %S/non-public-designated-inits.swift -module-name Module -enable-library-evolution
// RUN: %target-swift-frontend -typecheck -verify %s -I %t
import Module
open class B : A {
var x: Int
public override init(_ x: Int) {
self.x = x
super.init(x)
}
}
print(B(hi: ())) // expected-error {{cannot convert value of type '()' to expected argument type 'Int'}}
// expected-error @-1 {{extraneous argument label 'hi:' in call}}

View File

@@ -0,0 +1,21 @@
// Note: This test has a client: non-public-designated-inits-client.swift
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -typecheck %s -emit-module-interface-path %t/Module.swiftinterface -module-name Module -enable-library-evolution
// RUN: %FileCheck %s < %t/Module.swiftinterface
// CHECK: @_hasMissingDesignatedInitializers open class A {
open class A {
// This is a non-public designated init, which means the convenience
// init should not be inheritable.
init() {}
// CHECK-NEXT: public init(_: Swift.Int)
public init(_: Int) {}
// CHECK-NEXT: convenience public init(hi: ())
public convenience init(hi: ()) { self.init() }
// CHECK: }
}

View File

@@ -16,7 +16,7 @@
import CoreData
import Foundation
// CHECK: @objc public class MyObject : CoreData.NSManagedObject {
// CHECK: @objc @_inheritsConvenienceInitializers public class MyObject : CoreData.NSManagedObject {
public class MyObject: NSManagedObject {
// CHECK: @objc @NSManaged dynamic public var myVar: Swift.String {
// CHECK-NEXT: @objc get

View File

@@ -1534,7 +1534,7 @@ class infer_instanceVar2<
}
class infer_instanceVar3 : Class_ObjC1 {
// CHECK-LABEL: @objc class infer_instanceVar3 : Class_ObjC1 {
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class infer_instanceVar3 : Class_ObjC1 {
var v1: Int = 0
// CHECK-LABEL: @objc @_hasInitialValue var v1: Int
@@ -1599,13 +1599,13 @@ protocol infer_throughConformanceProto1 {
}
class infer_class1 : PlainClass {}
// CHECK-LABEL: {{^}}class infer_class1 : PlainClass {
// CHECK-LABEL: {{^}}@_inheritsConvenienceInitializers class infer_class1 : PlainClass {
class infer_class2 : Class_ObjC1 {}
// CHECK-LABEL: @objc class infer_class2 : Class_ObjC1 {
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class infer_class2 : Class_ObjC1 {
class infer_class3 : infer_class2 {}
// CHECK-LABEL: @objc class infer_class3 : infer_class2 {
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class infer_class3 : infer_class2 {
class infer_class4 : Protocol_Class1 {}
// CHECK-LABEL: {{^}}class infer_class4 : Protocol_Class1 {