diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index e71671c86ba4f..d76c92d302e25 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -412,6 +412,9 @@ EXPERIMENTAL_FEATURE(WarnUnsafe, true) /// Import unsafe C and C++ constructs as @unsafe. EXPERIMENTAL_FEATURE(SafeInterop, true) +/// Ignore resilience errors due to C++ types. +EXPERIMENTAL_FEATURE(AssumeResilientCxxTypes, true) + // Isolated deinit SUPPRESSIBLE_EXPERIMENTAL_FEATURE(IsolatedDeinit, true) diff --git a/lib/AST/FeatureSet.cpp b/lib/AST/FeatureSet.cpp index b9c267fd0b5d8..ae1647dde24b9 100644 --- a/lib/AST/FeatureSet.cpp +++ b/lib/AST/FeatureSet.cpp @@ -295,6 +295,7 @@ static bool usesFeatureAllowUnsafeAttribute(Decl *decl) { UNINTERESTING_FEATURE(WarnUnsafe) UNINTERESTING_FEATURE(SafeInterop) +UNINTERESTING_FEATURE(AssumeResilientCxxTypes) bool swift::usesFeatureIsolatedDeinit(const Decl *decl) { if (auto cd = dyn_cast(decl)) { diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 24484cca3fac6..314a149ad4735 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -1997,7 +1997,9 @@ swift::getDisallowedOriginKind(const Decl *decl, where.getDeclContext()->getAsDecl() && where.getDeclContext()->getAsDecl()->getModuleContext()->isResilient() && decl->hasClangNode() && !decl->getModuleContext()->isSwiftShimsModule() && - isFragileClangNode(decl->getClangNode())) + isFragileClangNode(decl->getClangNode()) && + !SF->getASTContext().LangOpts.hasFeature( + Feature::AssumeResilientCxxTypes)) return DisallowedOriginKind::FragileCxxAPI; // Report non-public import last as it can be ignored by the caller. diff --git a/test/Interop/Cxx/library-evolution/allow-cxx-api-in-evolving-libraries.swift b/test/Interop/Cxx/library-evolution/allow-cxx-api-in-evolving-libraries.swift new file mode 100644 index 0000000000000..94b2a5f823470 --- /dev/null +++ b/test/Interop/Cxx/library-evolution/allow-cxx-api-in-evolving-libraries.swift @@ -0,0 +1,87 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t +// RUN: %target-swift-frontend %t/test.swift -I %t/Inputs -typecheck -enable-library-evolution -enable-experimental-cxx-interop -disable-availability-checking -disable-implicit-cxx-module-import -enable-experimental-feature AssumeResilientCxxTypes -verify + +//--- Inputs/module.modulemap +module CxxModule { + header "header.h" + requires cplusplus +} + +//--- Inputs/header.h + +class CxxStruct { +public: + int x; int y; + + void method() const; +}; + +enum class CxxEnum { + A, B +}; + +template +class CxxTemplate { + T v; +}; + +using CxxTemplateInt = CxxTemplate; + +class +__attribute__((swift_attr("import_reference"))) +__attribute__((swift_attr("retain:immortal"))) +__attribute__((swift_attr("release:immortal"))) +SingletonReference { +public: + SingletonReference(const SingletonReference &) = delete; + + static SingletonReference * _Nonnull create(); + + void method(); +}; + +CxxStruct createStruct(); + +void freeCxxFunction(); + +using BuiltinIntTypealis = int; + +//--- test.swift + +import CxxModule + +public func usesBuiltinIntTypealis() -> BuiltinIntTypealis { + return 21 +} + +public func usesCxxSingletonReference() -> SingletonReference { + return SingletonReference.create() +} + +public func usesCxxStruct(_ x: CxxStruct) { +} + +public typealias EnumT = CxxEnum + +extension CxxTemplateInt { + func testInternal() { + + } +} + +extension CxxTemplateInt { + public func testPublicExt() { + } +} + +public func publicFuncInternalBody() { + let s = createStruct() + s.method() +} + +@inlinable +public func publicFuncPublicBody() { + let value = SingletonReference.create() + value.method() +}