Files
swift-mirror/test/Interop/Cxx/class/inheritance/functions-module-interface.swift
John Hui 66c2e2c52b [cxx-interop] Import non-public inherited members (#79348)
This patch is follow-up work from #78942 and imports non-public members,
which were previously not being imported. Those members can be accessed
in a Swift file blessed by the SWIFT_PRIVATE_FILEID annotation.

As a consequence of this patch, we are also now importing inherited members
that are inaccessible from the derived classes, because they were declared
private, or because they were inherited via nested private inheritance. We
import them anyway but mark them unavailable, for better diagnostics and to
(somewhat) simplify the import logic for inheritance.

Because non-public base class members are now imported too, this patch
inflames an existing issue where a 'using' declaration on an inherited member
with a synthesized name (e.g., operators) produces duplicate members, leading
to miscompilation (resulting in a runtime crash). This was not previously noticed
because a 'using' declaration on a public inherited member is not usually
necessary, but is a common way to expose otherwise non-public members.
This patch puts in a workaround to prevent this from affecting the behavior
of MSVC's std::optional implementation, which uses this pattern of 'using'
a private inherited member. That will be fixed in a follow-up patch.

Follow-up work is also needed to correctly diagnose ambiguous overloads
in cases of multiple inheritance, and to account for virtual inheritance.

rdar://137764620
2025-02-25 01:03:16 -08:00

230 lines
11 KiB
Swift

// RUN: %target-swift-ide-test -print-module -print-implicit-attrs -print-access -module-to-print=Functions -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s
// CHECK: public struct NonTrivial {
// CHECK-NEXT: public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func inNonTrivial() -> UnsafePointer<CChar>!
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func inNonTrivialWithArgs(_ a: Int32, _ b: Int32) -> UnsafePointer<CChar>!
// CHECK-NEXT: }
// CHECK-NEXT: public struct Base {
// CHECK-NEXT: public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public mutating func mutatingInBase() -> UnsafePointer<CChar>!
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func constInBase() -> UnsafePointer<CChar>!
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func rvalueThisInBase() -> UnsafePointer<CChar>!
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func takesArgsInBase(_ a: Int32, _ b: Int32, _ c: Int32) -> UnsafePointer<CChar>!
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func takesNonTrivialInBase(_ a: NonTrivial) -> UnsafePointer<CChar>!
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func returnsNonTrivialInBase() -> NonTrivial
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func templateInBase<T>(_ t: T) -> UnsafePointer<CChar>!
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public static func staticInBase() -> UnsafePointer<CChar>!
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public mutating func swiftRenamed(input i: Int32) -> Int32
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "swiftRenamed(input:)")
// CHECK-NEXT: public mutating func renamed(_ i: Int32) -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: @_effects(readonly) public func pure() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func sameMethodNameSameSignature() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func sameMethodDifferentSignature() -> Int32
// CHECK-NEXT: }
// CHECK-NEXT: public struct OtherBase {
// CHECK-NEXT: public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func inOtherBase() -> UnsafePointer<CChar>!
// CHECK-NEXT: }
// CHECK-NEXT: public struct Derived {
// CHECK-NEXT: public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func inDerived() -> UnsafePointer<CChar>!
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func sameMethodNameSameSignature() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func sameMethodDifferentSignature(_ x: Int32) -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public mutating func mutatingInBase() -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func constInBase() -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func takesArgsInBase(_ a: Int32, _ b: Int32, _ c: Int32) -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func takesNonTrivialInBase(_ a: NonTrivial) -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func returnsNonTrivialInBase() -> NonTrivial
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public mutating func swiftRenamed(input i: Int32) -> Int32
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "swiftRenamed(input:)")
// CHECK-NEXT: public mutating func renamed(_ i: Int32) -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: @_effects(readonly) public func pure() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func sameMethodDifferentSignature() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func inOtherBase() -> UnsafePointer<CChar>?
// CHECK-NEXT: }
// CHECK-NEXT: public struct DerivedFromDerived {
// CHECK-NEXT: public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func topLevel() -> UnsafePointer<CChar>!
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func inDerived() -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func sameMethodNameSameSignature() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func sameMethodDifferentSignature(_ x: Int32) -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public mutating func mutatingInBase() -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func constInBase() -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func takesArgsInBase(_ a: Int32, _ b: Int32, _ c: Int32) -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func takesNonTrivialInBase(_ a: NonTrivial) -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func returnsNonTrivialInBase() -> NonTrivial
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public mutating func swiftRenamed(input i: Int32) -> Int32
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "swiftRenamed(input:)")
// CHECK-NEXT: public mutating func renamed(_ i: Int32) -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: @_effects(readonly) public func pure() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func sameMethodDifferentSignature() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func inOtherBase() -> UnsafePointer<CChar>?
// CHECK-NEXT: }
// CHECK-NEXT: public struct DerivedFromNonTrivial {
// CHECK-NEXT: public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func inNonTrivial() -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func inNonTrivialWithArgs(_ a: Int32, _ b: Int32) -> UnsafePointer<CChar>?
// CHECK-NEXT: }
// CHECK-NEXT: public struct PrivatelyInherited {
// CHECK-NEXT: public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private mutating func mutatingInBase() -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private func constInBase() -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private func takesArgsInBase(_ a: Int32, _ b: Int32, _ c: Int32) -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private func takesNonTrivialInBase(_ a: NonTrivial) -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private func returnsNonTrivialInBase() -> NonTrivial
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private mutating func swiftRenamed(input i: Int32) -> Int32
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "swiftRenamed(input:)")
// CHECK-NEXT: private mutating func renamed(_ i: Int32) -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: @_effects(readonly) private func pure() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private func sameMethodNameSameSignature() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private func sameMethodDifferentSignature() -> Int32
// CHECK-NEXT: }
// CHECK-NEXT: public struct ProtectedInherited {
// CHECK-NEXT: public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private mutating func mutatingInBase() -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private func constInBase() -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private func takesArgsInBase(_ a: Int32, _ b: Int32, _ c: Int32) -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private func takesNonTrivialInBase(_ a: NonTrivial) -> UnsafePointer<CChar>?
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private func returnsNonTrivialInBase() -> NonTrivial
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private mutating func swiftRenamed(input i: Int32) -> Int32
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "swiftRenamed(input:)")
// CHECK-NEXT: private mutating func renamed(_ i: Int32) -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: @_effects(readonly) private func pure() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private func sameMethodNameSameSignature() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: private func sameMethodDifferentSignature() -> Int32
// CHECK-NEXT: }
// CHECK-NEXT: public struct EmptyBaseClass {
// CHECK-NEXT: public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func inBase() -> UnsafePointer<CChar>!
// CHECK-NEXT: }
// CHECK-NEXT: public struct DerivedFromEmptyBaseClass {
// CHECK-NEXT: public init()
// CHECK-NEXT: public var a: Int32
// CHECK-NEXT: public var b: Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func inBase() -> UnsafePointer<CChar>?
// CHECK-NEXT: }
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func getCopyCounter() -> UnsafeMutablePointer<Int32>
// CHECK-NEXT: public struct CopyTrackedBaseClass {
// CHECK-NEXT: public init(_ x: Int32)
// CHECK-NEXT: @available(*, deprecated, message: "This zero-initializes the backing memory of the struct, which is unsafe for some C++ structs. Consider adding an explicit default initializer for this C++ struct.")
// CHECK-NEXT: @_transparent public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func getX() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public mutating func getXMut() -> Int32
// CHECK-NEXT: private var x: Int32
// CHECK-NEXT: }
// CHECK-NEXT: public struct CopyTrackedDerivedClass {
// CHECK-NEXT: public init(_ x: Int32)
// CHECK-NEXT: @available(*, deprecated, message: "This zero-initializes the backing memory of the struct, which is unsafe for some C++ structs. Consider adding an explicit default initializer for this C++ struct.")
// CHECK-NEXT: @_transparent public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func getDerivedX() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func getX() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public mutating func getXMut() -> Int32
// CHECK-NEXT: @available(*, unavailable, message: "this base member is not accessible because it is private")
// CHECK-NEXT: private var x: Int32
// CHECK-NEXT: }
// CHECK-NEXT: public struct NonEmptyBase {
// CHECK-NEXT: public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func getY() -> Int32
// CHECK-NEXT: private var y: Int32
// CHECK-NEXT: }
// CHECK-NEXT: public struct CopyTrackedDerivedDerivedClass {
// CHECK-NEXT: public init(_ x: Int32)
// CHECK-NEXT: @available(*, deprecated, message: "This zero-initializes the backing memory of the struct, which is unsafe for some C++ structs. Consider adding an explicit default initializer for this C++ struct.")
// CHECK-NEXT: @_transparent public init()
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func getY() -> Int32
// CHECK-NEXT: @available(*, unavailable, message: "this base member is not accessible because it is private")
// CHECK-NEXT: private var y: Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func getDerivedX() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public func getX() -> Int32
// CHECK-NEXT: @discardableResult
// CHECK-NEXT: public mutating func getXMut() -> Int32
// CHECK-NEXT: @available(*, unavailable, message: "this base member is not accessible because it is private")
// CHECK-NEXT: private var x: Int32
// CHECK-NEXT: }