Files
swift-mirror/test/Interop/Cxx/class/access/access-specifiers-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

82 lines
4.8 KiB
Swift

// Test module interface produced for C++ access specifiers test.
// Public C++ members should be imported with Swift-public access, and
// private C++ members should be imported with Swift-private access.
// RUN: %target-swift-ide-test -print-module -module-to-print=AccessSpecifiers -print-access -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s
// CHECK: public struct PublicPrivate {
// CHECK-NEXT: public init()
// CHECK-NEXT: public static var PublicStaticMemberVar: Int32
// CHECK-NEXT: public mutating func publicMemberFunc()
// CHECK-NEXT: public typealias PublicTypedef = Int32
// CHECK-NEXT: public struct PublicStruct {
// CHECK-NEXT: init()
// CHECK-NEXT: }
// CHECK-NEXT: public struct PublicEnum : Hashable, Equatable, RawRepresentable {
// CHECK-NEXT: public init(_ rawValue: [[ENUM_UNDERLYING_TYPE:Int32|UInt32]])
// CHECK-NEXT: public init(rawValue: [[ENUM_UNDERLYING_TYPE]])
// CHECK-NEXT: public var rawValue: [[ENUM_UNDERLYING_TYPE]]
// CHECK-NEXT: public typealias RawValue = [[ENUM_UNDERLYING_TYPE]]
// CHECK-NEXT: }
// CHECK-NEXT: @frozen public enum PublicClosedEnum : [[ENUM_UNDERLYING_TYPE]], @unchecked Sendable {
// CHECK-NEXT: public init?(rawValue: [[ENUM_UNDERLYING_TYPE]])
// CHECK-NEXT: public var rawValue: [[ENUM_UNDERLYING_TYPE]] { get }
// CHECK-NEXT: public typealias RawValue = [[ENUM_UNDERLYING_TYPE]]
// CHECK-NEXT: case value1
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "value1")
// CHECK-NEXT: public static var Value1: PublicPrivate.PublicClosedEnum { get }
// CHECK-NEXT: }
// CHECK-NEXT: public enum PublicOpenEnum : [[ENUM_UNDERLYING_TYPE]], @unchecked Sendable {
// CHECK-NEXT: public init?(rawValue: [[ENUM_UNDERLYING_TYPE]])
// CHECK-NEXT: public var rawValue: [[ENUM_UNDERLYING_TYPE]] { get }
// CHECK-NEXT: public typealias RawValue = [[ENUM_UNDERLYING_TYPE]]
// CHECK-NEXT: case value1
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "value1")
// CHECK-NEXT: public static var Value1: PublicPrivate.PublicOpenEnum { get }
// CHECK-NEXT: }
// CHECK-NEXT: public struct PublicFlagEnum : OptionSet, @unchecked Sendable {
// CHECK-NEXT: public init(rawValue: [[ENUM_UNDERLYING_TYPE]])
// CHECK-NEXT: public let rawValue: [[ENUM_UNDERLYING_TYPE]]
// CHECK-NEXT: public typealias RawValue = [[ENUM_UNDERLYING_TYPE]]
// CHECK-NEXT: public typealias Element = PublicPrivate.PublicFlagEnum
// CHECK-NEXT: public typealias ArrayLiteralElement = PublicPrivate.PublicFlagEnum
// CHECK-NEXT: }
// CHECK-NEXT: private static var PrivateStaticMemberVar: Int32
// CHECK-NEXT: private mutating func privateMemberFunc()
// CHECK-NEXT: private typealias PrivateTypedef = Int32
// CHECK-NEXT: private struct PrivateStruct {
// CHECK-NEXT: public init()
// CHECK-NEXT: }
// CHECK-NEXT: private struct PrivateEnum : Hashable, Equatable, RawRepresentable {
// CHECK-NEXT: private init(_ rawValue: [[ENUM_UNDERLYING_TYPE]])
// CHECK-NEXT: private init(rawValue: [[ENUM_UNDERLYING_TYPE]])
// CHECK-NEXT: private var rawValue: [[ENUM_UNDERLYING_TYPE]]
// CHECK-NEXT: private typealias RawValue = [[ENUM_UNDERLYING_TYPE]]
// CHECK-NEXT: }
// CHECK-NEXT: @frozen private enum PrivateClosedEnum : [[ENUM_UNDERLYING_TYPE]], @unchecked Sendable {
// CHECK-NEXT: private init?(rawValue: [[ENUM_UNDERLYING_TYPE]])
// CHECK-NEXT: private var rawValue: [[ENUM_UNDERLYING_TYPE]] { get }
// CHECK-NEXT: private typealias RawValue = [[ENUM_UNDERLYING_TYPE]]
// CHECK-NEXT: case value1
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "value1")
// CHECK-NEXT: private static var Value1: PublicPrivate.PrivateClosedEnum { get }
// CHECK-NEXT: }
// CHECK-NEXT: private enum PrivateOpenEnum : [[ENUM_UNDERLYING_TYPE]], @unchecked Sendable {
// CHECK-NEXT: private init?(rawValue: [[ENUM_UNDERLYING_TYPE]])
// CHECK-NEXT: private var rawValue: [[ENUM_UNDERLYING_TYPE]] { get }
// CHECK-NEXT: private typealias RawValue = [[ENUM_UNDERLYING_TYPE]]
// CHECK-NEXT: case value1
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "value1")
// CHECK-NEXT: private static var Value1: PublicPrivate.PrivateOpenEnum { get }
// CHECK-NEXT: }
// CHECK-NEXT: private struct PrivateFlagEnum : OptionSet, @unchecked Sendable {
// CHECK-NEXT: private init(rawValue: [[ENUM_UNDERLYING_TYPE]])
// CHECK-NEXT: private let rawValue: [[ENUM_UNDERLYING_TYPE]]
// CHECK-NEXT: private typealias RawValue = [[ENUM_UNDERLYING_TYPE]]
// CHECK-NEXT: private typealias Element = PublicPrivate.PrivateFlagEnum
// CHECK-NEXT: private typealias ArrayLiteralElement = PublicPrivate.PrivateFlagEnum
// CHECK-NEXT: }
// CHECK-NEXT: public var PublicMemberVar: Int32
// CHECK-NEXT: private var PrivateMemberVar: Int32
// CHECK-NEXT: }