Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6273,7 +6273,7 @@ static ValueDecl *cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext,
auto out = new (rawMemory) TypeAliasDecl(
typeDecl->getLoc(), typeDecl->getLoc(), typeDecl->getName(),
typeDecl->getLoc(), nullptr, newContext);
out->setUnderlyingType(typeDecl->getInterfaceType());
out->setUnderlyingType(typeDecl->getDeclaredInterfaceType());
out->setAccess(access);
inheritance.setUnavailableIfNecessary(decl, out);
return out;
Expand Down
4 changes: 2 additions & 2 deletions test/Interop/Cxx/class/inheritance/Inputs/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ module ReferenceToDerived {
requires cplusplus
}

module SubTypes {
header "sub-types.h"
module NestedTypes {
header "nested-types.h"
}

module Subscripts {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ struct Base {
};

struct Derived : Base {};
struct Derived1 : Base {};
struct Derived2 : Derived1 {};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-ide-test -print-module -module-to-print=SubTypes -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s
// RUN: %target-swift-ide-test -print-module -module-to-print=NestedTypes -I %S/Inputs -source-filename=x -cxx-interoperability-mode=default | %FileCheck %s

// CHECK: struct Base {
// CHECK-NEXT: init()
Expand Down Expand Up @@ -39,11 +39,29 @@
// CHECK-NEXT: }
// CHECK-NEXT: }

// CHECK-NEXT: struct Derived {
// CHECK: struct Derived {
// CHECK-NEXT: init()
// CHECK-NEXT: typealias EnumClass = Base.EnumClass.Type
// CHECK-NEXT: typealias Enum = Base.Enum.Type
// CHECK-NEXT: typealias Struct = Base.Struct.Type
// CHECK-NEXT: typealias Parent = Base.Parent.Type
// CHECK-NEXT: typealias Union = Base.Union.Type
// CHECK-NEXT: typealias EnumClass = Base.EnumClass
// CHECK-NEXT: typealias Enum = Base.Enum
// CHECK-NEXT: typealias Struct = Base.Struct
// CHECK-NEXT: typealias Parent = Base.Parent
// CHECK-NEXT: typealias Union = Base.Union
// CHECK-NEXT: }

// CHECK: struct Derived1 {
// CHECK-NEXT: init()
// CHECK-NEXT: typealias EnumClass = Base.EnumClass
// CHECK-NEXT: typealias Enum = Base.Enum
// CHECK-NEXT: typealias Struct = Base.Struct
// CHECK-NEXT: typealias Parent = Base.Parent
// CHECK-NEXT: typealias Union = Base.Union
// CHECK-NEXT: }

// CHECK: struct Derived2 {
// CHECK-NEXT: init()
// CHECK-NEXT: typealias EnumClass = Base.EnumClass
// CHECK-NEXT: typealias Enum = Base.Enum
// CHECK-NEXT: typealias Struct = Base.Struct
// CHECK-NEXT: typealias Parent = Base.Parent
// CHECK-NEXT: typealias Union = Base.Union
// CHECK-NEXT: }
113 changes: 113 additions & 0 deletions test/Interop/Cxx/class/inheritance/nested-types-typechecker.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=default

// This test ensures that nested type inherited from the base type are
// interchangeable with the base types themselves.

import NestedTypes

func parent(
bc: Base.EnumClass,
be: Base.Enum,
bs: Base.Struct,
bp: Base.Parent,
bpc: Base.Parent.Child,
bu: Base.Union,
) {
let dc: Derived.EnumClass = bc
let de: Derived.Enum = be
let ds: Derived.Struct = bs
let dp: Derived.Parent = bp
let dpc: Derived.Parent.Child = bpc
let du: Derived.Union = bu

let _: Base.EnumClass = dc
let _: Base.Enum = de
let _: Base.Struct = ds
let _: Base.Parent = dp
let _: Base.Parent.Child = dpc
let _: Base.Union = du
}

func grandparent(
bc: Base.EnumClass,
be: Base.Enum,
bs: Base.Struct,
bp: Base.Parent,
bpc: Base.Parent.Child,
bu: Base.Union,
) {
let dc: Derived2.EnumClass = bc
let de: Derived2.Enum = be
let ds: Derived2.Struct = bs
let dp: Derived2.Parent = bp
let dpc: Derived2.Parent.Child = bpc
let du: Derived2.Union = bu

let _: Derived.EnumClass = dc
let _: Derived.Enum = de
let _: Derived.Struct = ds
let _: Derived.Parent = dp
let _: Derived.Parent.Child = dpc
let _: Derived.Union = du
}

func siblings(
dc: Derived.EnumClass,
de: Derived.Enum,
ds: Derived.Struct,
dp: Derived.Parent,
dpc: Derived.Parent.Child,
du: Derived.Union,
) {
let _: Derived1.EnumClass = dc
let _: Derived1.Enum = de
let _: Derived1.Struct = ds
let _: Derived1.Parent = dp
let _: Derived1.Parent.Child = dpc
let _: Derived1.Union = du
}

// Instances created from derived class can be type-annotated with base class
// and vice versa
func assigner() {
let _: Base.EnumClass = Derived.EnumClass.ecb
let _: Base.Enum = Derived.ea // expected-error {{type 'Derived' has no member 'ea'}}
// ^FIXME: nested enums are broken, so inherited nested enums are broken too
let _: Base.Struct = Derived.Struct(sa: 4, sb: 2)
let _: Base.Parent = Derived.Parent()
let _: Base.Parent.Child = Derived.Parent.Child(pca: 42)
let _: Base.Union = Derived.Union(ua: 42)

let _: Derived.EnumClass = Base.EnumClass.ecc
let _: Derived.Enum = Base.ea // expected-error {{type 'Base' has no member 'ea'}}
// ^FIXME: nested enums are broken, so inherited nested enums are broken too
let _: Derived.Struct = Base.Struct(sa: 4, sb: 2)
let _: Derived.Parent = Base.Parent()
let _: Derived.Parent.Child = Base.Parent.Child(pca: 42)
let _: Derived.Union = Base.Union(ua: 42)
}

// Extensions on base type should be "seen" in derived types too, and vice versa
extension Base.Parent {
static func getChild1() -> Child {
return Child(pca: 111)
}
}

extension Derived {
func haveChild1() {
let _: Parent.Child = Parent.getChild1()
}
}

extension Derived.Parent {
static func getChild2() -> Child {
return Child(pca: 111)
}
}

extension Base {
func haveChild2() {
let _: Parent.Child = Parent.getChild2()
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-ide-test -print-module -module-to-print=TypeAliases -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s
// RUN: %target-swift-ide-test -print-module -module-to-print=TypeAliases -I %S/Inputs -source-filename=x -cxx-interoperability-mode=default | %FileCheck %s

// CHECK: struct Base {
// CHECK-NEXT: init()
Expand All @@ -11,7 +11,7 @@

// CHECK-NEXT: struct Derived {
// CHECK-NEXT: init()
// CHECK-NEXT: typealias Struct = Base.Struct.Type
// CHECK-NEXT: typealias Struct = Base.Struct
// CHECK-NEXT: typealias T = Int32
// CHECK-NEXT: typealias U = Base.Struct
// CHECK-NEXT: }
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=default

// This test ensures that nested type aliases inherited from the base type are
// interchangeable with the base types themselves.

import TypeAliases

extension Derived {
func takesBaseTypes(bs: Base.Struct, bt: Base.T, bu: Base.U) {
let _: Struct = bs
let _: U = bs

let _: T = bt
let _: Int32 = bt

let _: U = bu
let _: Struct = bu
}

func takesDerivedTypes(ds: Struct, dt: T, du: U) {
let _: Base.Struct = ds
let _: Base.U = ds

let _: Base.T = dt
let _: Int32 = dt

let _: Base.U = du
let _: Base.Struct = du
}
}
func takesBaseTypes(bs: Base.Struct, bt: Base.T, bu: Base.U) {
let _: Derived.Struct = bs
let _: Derived.U = bs

let _: Derived.T = bt
let _: Int32 = bt

let _: Derived.U = bu
let _: Derived.Struct = bu
}

func takesDerivedTypes(ds: Derived.Struct, dt: Derived.T, du: Derived.U) {
let _: Base.Struct = ds
let _: Base.U = ds

let _: Base.T = dt
let _: Int32 = dt

let _: Base.U = du
let _: Base.Struct = du
}