-
Notifications
You must be signed in to change notification settings - Fork 10.6k
[cxx-interop] Add flag to set minimum access level for reverse interop #84816
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,7 @@ | |
| #include "PrintSwiftToClangCoreScaffold.h" | ||
| #include "SwiftToClangInteropContext.h" | ||
|
|
||
| #include "swift/AST/AttrKind.h" | ||
| #include "swift/AST/Decl.h" | ||
| #include "swift/AST/DiagnosticsSema.h" | ||
| #include "swift/AST/ExistentialLayout.h" | ||
|
|
@@ -1151,35 +1152,43 @@ class ModuleWriter { | |
| }; | ||
| } // end anonymous namespace | ||
|
|
||
| static AccessLevel getRequiredAccess(const ModuleDecl &M) { | ||
| static AccessLevel getRequiredAccess(const ModuleDecl &M, | ||
| std::optional<AccessLevel> minAccess) { | ||
| if (minAccess) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I should have brought this up last time, but since you're writing this in a way that affects ObjC generated headers, would you be willing to add test cases for that? I took a look and I think you'd get adequate coverage by just adding another set of RUN lines to test/PrintAsObjC/accessibility.swift: // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -parse-as-library %s -application-extension-library -emit-clang-header-min-access internal -typecheck -verify -emit-objc-header-path %t/accessibility-explicit-internal.h -disable-objc-attr-requires-foundation-module
// RUN: %FileCheck -check-prefix=CHECK -check-prefix=CHECK-INTERNAL %s < %t/accessibility-explicit-internal.h
// RUN: %check-in-clang %t/accessibility-explicit-internal.h
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -parse-as-library %s -application-extension -emit-clang-header-min-access public -typecheck -verify -emit-objc-header-path %t/accessibility-explicit-public.h -disable-objc-attr-requires-foundation-module
// RUN: %FileCheck -check-prefix=CHECK -check-prefix=CHECK-PUBLIC %s < %t/accessibility-explicit-public.h
// RUN: %check-in-clang %t/accessibility-explicit-public.hThis test is already set up to exercise all the heuristics; we're just adding another pair of cases that override the heuristics with your new flag. Assuming that passes, that's the only issue I see at this point—feel free to merge once it's resolved.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added these tests and they pass. Thanks a lot! Will merge this PR, but I am also happy to address if anything comes up post-merge. |
||
| return *minAccess; | ||
| return M.isExternallyConsumed() ? AccessLevel::Public : AccessLevel::Internal; | ||
| } | ||
|
|
||
| void swift::printModuleContentsAsObjC( | ||
| raw_ostream &os, llvm::SmallPtrSetImpl<ImportModuleTy> &imports, | ||
| ModuleDecl &M, SwiftToClangInteropContext &interopContext) { | ||
| ModuleDecl &M, SwiftToClangInteropContext &interopContext, | ||
| std::optional<AccessLevel> minAccess) { | ||
| llvm::raw_null_ostream prologueOS; | ||
| llvm::StringSet<> exposedModules; | ||
| ModuleWriter(os, prologueOS, imports, M, interopContext, getRequiredAccess(M), | ||
| ModuleWriter(os, prologueOS, imports, M, interopContext, | ||
| getRequiredAccess(M, minAccess), | ||
| /*requiresExposedAttribute=*/false, exposedModules, | ||
| OutputLanguageMode::ObjC) | ||
| .write(); | ||
| } | ||
|
|
||
| void swift::printModuleContentsAsC( | ||
| raw_ostream &os, llvm::SmallPtrSetImpl<ImportModuleTy> &imports, | ||
| ModuleDecl &M, SwiftToClangInteropContext &interopContext) { | ||
| ModuleDecl &M, SwiftToClangInteropContext &interopContext, | ||
| std::optional<AccessLevel> minAccess) { | ||
| llvm::raw_null_ostream prologueOS; | ||
| llvm::StringSet<> exposedModules; | ||
| ModuleWriter(os, prologueOS, imports, M, interopContext, getRequiredAccess(M), | ||
| ModuleWriter(os, prologueOS, imports, M, interopContext, | ||
| getRequiredAccess(M, minAccess), | ||
| /*requiresExposedAttribute=*/false, exposedModules, | ||
| OutputLanguageMode::C) | ||
| .write(); | ||
| } | ||
|
|
||
| EmittedClangHeaderDependencyInfo swift::printModuleContentsAsCxx( | ||
| raw_ostream &os, ModuleDecl &M, SwiftToClangInteropContext &interopContext, | ||
| bool requiresExposedAttribute, llvm::StringSet<> &exposedModules) { | ||
| AccessLevel minAccess, bool requiresExposedAttribute, | ||
| llvm::StringSet<> &exposedModules) { | ||
| std::string moduleContentsBuf; | ||
| llvm::raw_string_ostream moduleOS{moduleContentsBuf}; | ||
| std::string modulePrologueBuf; | ||
|
|
@@ -1197,8 +1206,8 @@ EmittedClangHeaderDependencyInfo swift::printModuleContentsAsCxx( | |
|
|
||
| // FIXME: Use getRequiredAccess once @expose is supported. | ||
| ModuleWriter writer(moduleOS, prologueOS, info.imports, M, interopContext, | ||
| AccessLevel::Public, requiresExposedAttribute, | ||
| exposedModules, OutputLanguageMode::Cxx); | ||
| minAccess, requiresExposedAttribute, exposedModules, | ||
| OutputLanguageMode::Cxx); | ||
| writer.write(); | ||
| info.dependsOnStandardLibrary = writer.isStdlibRequired(); | ||
| if (M.isStdlibModule()) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| // RUN: %empty-directory(%t) | ||
| // RUN: %target-swift-frontend %s -module-name Core -typecheck -verify -emit-clang-header-path %t/core.h -clang-header-expose-decls=has-expose-attr -emit-clang-header-min-access public -package-name Core | ||
| // RUN: %FileCheck %s --check-prefix CHECK-PUBLIC < %t/core.h | ||
|
|
||
| // RUN: %empty-directory(%t) | ||
| // RUN: %target-swift-frontend %s -module-name Core -typecheck -verify -emit-clang-header-path %t/core.h -clang-header-expose-decls=has-expose-attr -emit-clang-header-min-access package -package-name Core | ||
| // RUN: %FileCheck %s --check-prefix CHECK-PACKAGE < %t/core.h | ||
|
|
||
| // RUN: %empty-directory(%t) | ||
| // RUN: %target-swift-frontend %s -module-name Core -typecheck -verify -emit-clang-header-path %t/core.h -clang-header-expose-decls=has-expose-attr -emit-clang-header-min-access internal -package-name Core | ||
| // RUN: %FileCheck %s --check-prefix CHECK-INTERNAL < %t/core.h | ||
|
|
||
| @_expose(Cxx) | ||
| public func publicFunc(_ x: Int) -> Int { | ||
| return x | ||
| } | ||
|
|
||
| @_expose(Cxx) | ||
| package func packageFunc(_ x: Int) -> Int { | ||
| return x | ||
| } | ||
|
|
||
| @_expose(Cxx) | ||
| internal func internalFunc(_ x: Int) -> Int { | ||
| return x | ||
| } | ||
|
|
||
| @_expose(Cxx) | ||
| private func privateFunc(_ x: Int) -> Int { | ||
Xazax-hun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return x | ||
| } | ||
|
|
||
| // CHECK-PUBLIC-NOT: internalFunc | ||
| // CHECK-PUBLIC-NOT: packageFunc | ||
| // CHECK-PUBLIC-NOT: privateFunc | ||
| // CHECK-PUBLIC: SWIFT_INLINE_THUNK swift::Int publicFunc(swift::Int x) noexcept SWIFT_SYMBOL("s:4Core10publicFuncyS2iF") SWIFT_WARN_UNUSED_RESULT { | ||
|
|
||
| // CHECK-PACKAGE-NOT: internalFunc | ||
| // CHECK-PACKAGE: SWIFT_INLINE_THUNK swift::Int packageFunc(swift::Int x) noexcept SWIFT_SYMBOL("s:4Core11packageFuncyS2iF") SWIFT_WARN_UNUSED_RESULT { | ||
| // CHECK-PACKAGE-NOT: privateFunc | ||
| // CHECK-PACKAGE: SWIFT_INLINE_THUNK swift::Int publicFunc(swift::Int x) noexcept SWIFT_SYMBOL("s:4Core10publicFuncyS2iF") SWIFT_WARN_UNUSED_RESULT { | ||
|
|
||
| // CHECK-INTERNAL: SWIFT_INLINE_THUNK swift::Int internalFunc(swift::Int x) noexcept SWIFT_SYMBOL("s:4Core12internalFuncyS2iF") SWIFT_WARN_UNUSED_RESULT { | ||
| // CHECK-INTERNAL: SWIFT_INLINE_THUNK swift::Int packageFunc(swift::Int x) noexcept SWIFT_SYMBOL("s:4Core11packageFuncyS2iF") SWIFT_WARN_UNUSED_RESULT { | ||
| // CHECK-INTERNAL-NOT: privateFunc | ||
| // CHECK-INTERNAL: SWIFT_INLINE_THUNK swift::Int publicFunc(swift::Int x) noexcept SWIFT_SYMBOL("s:4Core10publicFuncyS2iF") SWIFT_WARN_UNUSED_RESULT { | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| // RUN: %empty-directory(%t) | ||
| // RUN: %target-swift-frontend %s -module-name Core -typecheck -verify -emit-clang-header-path %t/core.h -clang-header-expose-decls=all-public -emit-clang-header-min-access public -package-name Core | ||
| // RUN: %FileCheck %s --check-prefix CHECK-PUBLIC < %t/core.h | ||
|
|
||
| // RUN: %empty-directory(%t) | ||
| // RUN: %target-swift-frontend %s -module-name Core -typecheck -verify -emit-clang-header-path %t/core.h -clang-header-expose-decls=all-public -emit-clang-header-min-access package -package-name Core | ||
| // RUN: %FileCheck %s --check-prefix CHECK-PACKAGE < %t/core.h | ||
|
|
||
| // RUN: %empty-directory(%t) | ||
| // RUN: %target-swift-frontend %s -module-name Core -typecheck -verify -emit-clang-header-path %t/core.h -clang-header-expose-decls=all-public -emit-clang-header-min-access internal -package-name Core | ||
| // RUN: %FileCheck %s --check-prefix CHECK-INTERNAL < %t/core.h | ||
|
|
||
| // RUN: %empty-directory(%t) | ||
| // RUN: not %target-swift-frontend %s -module-name Core -typecheck -emit-clang-header-path %t/core.h -clang-header-expose-decls=all-public -emit-clang-header-min-access inernal -package-name Core 2>&1 | %FileCheck %s --check-prefix CHECK-DIAGNOSTIC | ||
|
|
||
| public func publicFunc(_ x: Int) -> Int { | ||
| return x | ||
| } | ||
|
|
||
| package func packageFunc(_ x: Int) -> Int { | ||
| return x | ||
| } | ||
|
|
||
| internal func internalFunc(_ x: Int) -> Int { | ||
| return x | ||
| } | ||
|
|
||
| private func privateFunc(_ x: Int) -> Int { | ||
| return x | ||
| } | ||
|
|
||
| public struct S { | ||
| public func publicMethod(_ x: Int) -> Int { | ||
| return x | ||
| } | ||
|
|
||
| package func packageMethod(_ x: Int) -> Int { | ||
| return x | ||
| } | ||
|
|
||
| internal func internalMethod(_ x: Int) -> Int { | ||
| return x | ||
| } | ||
|
|
||
| private func privateMethod(_ x: Int) -> Int { | ||
| return x | ||
| } | ||
|
|
||
| private var x: Int | ||
| } | ||
|
|
||
| // CHECK-PUBLIC-NOT: internalFunc | ||
| // CHECK-PUBLIC-NOT: packageFunc | ||
| // CHECK-PUBLIC-NOT: privateFunc | ||
| // CHECK-PUBLIC: SWIFT_INLINE_THUNK swift::Int publicFunc(swift::Int x) noexcept SWIFT_SYMBOL("s:4Core10publicFuncyS2iF") SWIFT_WARN_UNUSED_RESULT { | ||
| // CHECK-PUBLIC: SWIFT_INLINE_THUNK swift::Int S::publicMethod(swift::Int x) const { | ||
| // CHECK-PUBLIC-NOT: packageMethod | ||
| // CHECK-PUBLIC-NOT: internalMethod | ||
| // CHECK-PUBLIC-NOT: privateMethod | ||
|
|
||
| // CHECK-PACKAGE-NOT: internalFunc | ||
| // CHECK-PACKAGE: SWIFT_INLINE_THUNK swift::Int packageFunc(swift::Int x) noexcept SWIFT_SYMBOL("s:4Core11packageFuncyS2iF") SWIFT_WARN_UNUSED_RESULT { | ||
| // CHECK-PACKAGE-NOT: privateFunc | ||
| // CHECK-PACKAGE: SWIFT_INLINE_THUNK swift::Int publicFunc(swift::Int x) noexcept SWIFT_SYMBOL("s:4Core10publicFuncyS2iF") SWIFT_WARN_UNUSED_RESULT { | ||
| // CHECK-PACKAGE: SWIFT_INLINE_THUNK swift::Int S::publicMethod(swift::Int x) const { | ||
| // CHECK-PACKAGE: SWIFT_INLINE_THUNK swift::Int S::packageMethod(swift::Int x) const { | ||
| // CHECK-PACKAGE-NOT: internalMethod | ||
| // CHECK-PACKAGE-NOT: privateMethod | ||
|
|
||
| // CHECK-INTERNAL: SWIFT_INLINE_THUNK swift::Int internalFunc(swift::Int x) noexcept SWIFT_SYMBOL("s:4Core12internalFuncyS2iF") SWIFT_WARN_UNUSED_RESULT { | ||
| // CHECK-INTERNAL: SWIFT_INLINE_THUNK swift::Int packageFunc(swift::Int x) noexcept SWIFT_SYMBOL("s:4Core11packageFuncyS2iF") SWIFT_WARN_UNUSED_RESULT { | ||
| // CHECK-INTERNAL-NOT: privateFunc | ||
| // CHECK-INTERNAL: SWIFT_INLINE_THUNK swift::Int publicFunc(swift::Int x) noexcept SWIFT_SYMBOL("s:4Core10publicFuncyS2iF") SWIFT_WARN_UNUSED_RESULT { | ||
| // CHECK-INTERNAL: SWIFT_INLINE_THUNK swift::Int S::publicMethod(swift::Int x) const { | ||
| // CHECK-INTERNAL: SWIFT_INLINE_THUNK swift::Int S::packageMethod(swift::Int x) const { | ||
| // CHECK-INTERNAL: SWIFT_INLINE_THUNK swift::Int S::internalMethod(swift::Int x) const { | ||
| // CHECK-INTERNAL-NOT: privateMethod | ||
|
|
||
| // CHECK-DIAGNOSTIC: error: invalid minimum clang header access level 'inernal'; chose from 'public'|'package'|'internal' |
Uh oh!
There was an error while loading. Please reload this page.