Skip to content

Commit

Permalink
Merge pull request swiftlang#72912 from apple/egorzhdan/cxx-interop-c…
Browse files Browse the repository at this point in the history
…ompat-mode

[cxx-interop] Pull changes from `swift-6` compat mode into `swift-5.9`
  • Loading branch information
egorzhdan authored Apr 24, 2024
2 parents e373cae + b330376 commit 3fe8b71
Show file tree
Hide file tree
Showing 26 changed files with 69 additions and 78 deletions.
4 changes: 0 additions & 4 deletions include/swift/AST/DiagnosticsClangImporter.def
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,6 @@ ERROR(conforms_to_ambiguous,none,
ERROR(conforms_to_not_protocol,none,
"%0 %1 referenced in protocol conformance '%2' is not a protocol", (DescriptiveDeclKind, ValueDecl *, StringRef))

ERROR(move_only_requires_move_only,none,
"use of noncopyable C++ type '%0' requires -enable-experimental-move-only",
(StringRef))

ERROR(failed_base_method_call_synthesis,none,
"failed to synthesize call to the base method %0 of type %0",
(ValueDecl *, ValueDecl *))
Expand Down
97 changes: 39 additions & 58 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2192,22 +2192,12 @@ namespace {
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;

if (recordHasMoveOnlySemantics(decl)) {
if (Impl.isCxxInteropCompatVersionAtLeast(6)) {
if (decl->isInStdNamespace() && decl->getName() == "promise") {
// Do not import std::promise.
return nullptr;
}
result->getAttrs().add(new (Impl.SwiftContext)
MoveOnlyAttr(/*Implicit=*/true));
} else {
Impl.addImportDiagnostic(
decl,
Diagnostic(
diag::move_only_requires_move_only,
Impl.SwiftContext.AllocateCopy(decl->getNameAsString())),
decl->getLocation());
if (decl->isInStdNamespace() && decl->getName() == "promise") {
// Do not import std::promise.
return nullptr;
}
result->getAttrs().add(new (Impl.SwiftContext)
MoveOnlyAttr(/*Implicit=*/true));
}

// FIXME: Figure out what to do with superclasses in C++. One possible
Expand Down Expand Up @@ -2666,8 +2656,7 @@ namespace {
// SemaLookup.cpp).
if (!decl->isBeingDefined() && !decl->isDependentContext() &&
areRecordFieldsComplete(decl)) {
if (decl->hasInheritedConstructor() &&
Impl.isCxxInteropCompatVersionAtLeast(6)) {
if (decl->hasInheritedConstructor()) {
for (auto member : decl->decls()) {
if (auto usingDecl = dyn_cast<clang::UsingDecl>(member)) {
for (auto usingShadowDecl : usingDecl->shadows()) {
Expand Down Expand Up @@ -2838,14 +2827,12 @@ namespace {
void
addExplicitProtocolConformances(NominalTypeDecl *decl,
const clang::CXXRecordDecl *clangDecl) {
if (Impl.isCxxInteropCompatVersionAtLeast(6)) {
// Propagate conforms_to attribute from public base classes.
for (auto base : clangDecl->bases()) {
if (base.getAccessSpecifier() != clang::AccessSpecifier::AS_public)
continue;
if (auto *baseClangDecl = base.getType()->getAsCXXRecordDecl())
addExplicitProtocolConformances(decl, baseClangDecl);
}
// Propagate conforms_to attribute from public base classes.
for (auto base : clangDecl->bases()) {
if (base.getAccessSpecifier() != clang::AccessSpecifier::AS_public)
continue;
if (auto *baseClangDecl = base.getType()->getAsCXXRecordDecl())
addExplicitProtocolConformances(decl, baseClangDecl);
}

if (!clangDecl->hasAttrs())
Expand Down Expand Up @@ -3763,39 +3750,34 @@ namespace {

if (decl->isVirtual()) {
if (auto funcDecl = dyn_cast_or_null<FuncDecl>(method)) {
if (Impl.isCxxInteropCompatVersionAtLeast(6)) {
if (auto structDecl =
dyn_cast_or_null<StructDecl>(method->getDeclContext())) {
// If this is a method of a Swift struct, any possible override of
// this method would get sliced away, and an invocation would get
// dispatched statically. This is fine because it matches the C++
// behavior.
if (decl->isPure()) {
// If this is a pure virtual method, we won't have any
// implementation of it to invoke.
Impl.markUnavailable(
funcDecl, "virtual function is not available in Swift "
"because it is pure");
}
} else if (auto classDecl = dyn_cast_or_null<ClassDecl>(
funcDecl->getDeclContext())) {
// This is a foreign reference type. Since `class T` on the Swift
// side is mapped from `T*` on the C++ side, an invocation of a
// virtual method `t->method()` should get dispatched dynamically.
// Create a thunk that will perform dynamic dispatch.
// TODO: we don't have to import the actual `method` in this case,
// we can just synthesize a thunk and import that instead.
auto result = synthesizer.makeVirtualMethod(decl);
if (result) {
return result;
} else {
Impl.markUnavailable(
funcDecl, "virtual function is not available in Swift");
}
if (auto structDecl =
dyn_cast_or_null<StructDecl>(method->getDeclContext())) {
// If this is a method of a Swift struct, any possible override of
// this method would get sliced away, and an invocation would get
// dispatched statically. This is fine because it matches the C++
// behavior.
if (decl->isPure()) {
// If this is a pure virtual method, we won't have any
// implementation of it to invoke.
Impl.markUnavailable(funcDecl,
"virtual function is not available in Swift "
"because it is pure");
}
} else if (auto classDecl = dyn_cast_or_null<ClassDecl>(
funcDecl->getDeclContext())) {
// This is a foreign reference type. Since `class T` on the Swift
// side is mapped from `T*` on the C++ side, an invocation of a
// virtual method `t->method()` should get dispatched dynamically.
// Create a thunk that will perform dynamic dispatch.
// TODO: we don't have to import the actual `method` in this case,
// we can just synthesize a thunk and import that instead.
auto result = synthesizer.makeVirtualMethod(decl);
if (result) {
return result;
} else {
Impl.markUnavailable(
funcDecl, "virtual function is not available in Swift");
}
} else {
Impl.markUnavailable(
funcDecl, "virtual functions are not yet available in Swift");
}
}
}
Expand Down Expand Up @@ -4053,8 +4035,7 @@ namespace {
// 1. Types
// 2. C++ methods from privately inherited base classes
if (!isa<clang::TypeDecl>(decl->getTargetDecl()) &&
!(isa<clang::CXXMethodDecl>(decl->getTargetDecl()) &&
Impl.isCxxInteropCompatVersionAtLeast(6)))
!isa<clang::CXXMethodDecl>(decl->getTargetDecl()))
return nullptr;
// Constructors (e.g. `using BaseClass::BaseClass`) are handled in
// VisitCXXRecordDecl, since we need them to determine whether a struct
Expand Down
1 change: 0 additions & 1 deletion lib/ClangImporter/ImportType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2623,7 +2623,6 @@ static ParamDecl *getParameterInfo(ClangImporter::Implementation *impl,
// (https://github.com/apple/swift/issues/70124)
if (param->hasDefaultArg() && !isInOut &&
!isa<clang::CXXConstructorDecl>(param->getDeclContext()) &&
impl->isCxxInteropCompatVersionAtLeast(6) &&
impl->isDefaultArgSafeToImport(param)) {
SwiftDeclSynthesizer synthesizer(*impl);
if (CallExpr *defaultArgExpr = synthesizer.makeDefaultArgument(
Expand Down
11 changes: 3 additions & 8 deletions test/Interop/Cxx/class/conforms-to.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
// RUN: %target-swift-frontend %S/Inputs/conforms-to-imported.swift -module-name ImportedModule -emit-module -emit-module-path %t/ImportedModule.swiftmodule

// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %t -I %S/Inputs -module-name SwiftTest -enable-experimental-cxx-interop
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %t -I %S/Inputs -module-name SwiftTest -cxx-interoperability-mode=swift-6 -D UPCOMING_SWIFT
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %t -I %S/Inputs -module-name SwiftTest -cxx-interoperability-mode=upcoming-swift -D UPCOMING_SWIFT
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %t -I %S/Inputs -module-name SwiftTest -cxx-interoperability-mode=swift-5.9
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %t -I %S/Inputs -module-name SwiftTest -cxx-interoperability-mode=swift-6
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %t -I %S/Inputs -module-name SwiftTest -cxx-interoperability-mode=upcoming-swift

import ConformsTo
import ImportedModule
Expand All @@ -23,11 +24,9 @@ func callee(_ _: Testable) {
func caller(_ x: HasTest) {
callee(x)
}
#if UPCOMING_SWIFT
func caller(_ x: DerivedFromHasTest) { callee(x) }
func caller(_ x: DerivedFromDerivedFromHasTest) { callee(x) }
func caller(_ x: DerivedFromDerivedFromHasTestWithDuplicateArg) { callee(x) }
#endif

func callee(_ _: Playable) {

Expand All @@ -36,7 +35,6 @@ func callee(_ _: Playable) {
func caller(_ x: Playable) {
callee(x)
}
#if UPCOMING_SWIFT
func caller(_ x: DerivedFromHasPlay) { callee(x) }
func caller(_ x: DerivedFromDerivedFromHasPlay) { callee(x) }

Expand All @@ -48,15 +46,12 @@ func caller(_ x: DerivedFromHasTestAndPlay) {
callee(x as Testable)
callee(x as Playable)
}
#endif

func callee(_ _: ProtocolFromImportedModule) {
}

func caller(_ x: HasImportedConf) {
callee(x)
}
#if UPCOMING_SWIFT
func caller(_ x: DerivedFromHasImportedConf) { callee(x) }
func caller(_ x: DerivedFromDerivedFromHasImportedConf) { callee(x) }
#endif
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -cxx-interoperability-mode=swift-5.9
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -cxx-interoperability-mode=swift-6
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -cxx-interoperability-mode=upcoming-swift

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -cxx-interoperability-mode=swift-5.9)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -cxx-interoperability-mode=swift-6)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -cxx-interoperability-mode=upcoming-swift)
//
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %target-swift-emit-ir -I %S/Inputs -cxx-interoperability-mode=upcoming-swift %s -validate-tbd-against-ir=none -Xcc -fignore-exceptions | %FileCheck %s
// RUN: %target-swift-emit-ir -I %S/Inputs -cxx-interoperability-mode=swift-5.9 %s -validate-tbd-against-ir=none -Xcc -fignore-exceptions | %FileCheck %s
// RUN: %target-swift-emit-ir -I %S/Inputs -cxx-interoperability-mode=swift-6 %s -validate-tbd-against-ir=none -Xcc -fignore-exceptions | %FileCheck %s

import VirtualMethods
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-swift-ide-test -print-module -cxx-interoperability-mode=swift-5.9 -print-implicit-attrs -module-to-print=VirtualMethods -I %S/Inputs -source-filename=x | %FileCheck %s
// RUN: %target-swift-ide-test -print-module -cxx-interoperability-mode=swift-6 -print-implicit-attrs -module-to-print=VirtualMethods -I %S/Inputs -source-filename=x | %FileCheck %s
// RUN: %target-swift-ide-test -print-module -cxx-interoperability-mode=upcoming-swift -print-implicit-attrs -module-to-print=VirtualMethods -I %S/Inputs -source-filename=x | %FileCheck %s

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -cxx-interoperability-mode=upcoming-swift
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -cxx-interoperability-mode=swift-5.9
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -cxx-interoperability-mode=swift-6

import VirtualMethods
Expand Down
1 change: 1 addition & 0 deletions test/Interop/Cxx/class/inheritance/virtual-methods.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=swift-5.9)
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=swift-6)
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=upcoming-swift)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=upcoming-swift)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=upcoming-swift -enable-experimental-feature NoncopyableGenerics -D HAS_NONCOPYABLE_GENERICS)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=swift-5.9 -O)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=swift-6 -O)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=swift-6 -O -enable-experimental-feature NoncopyableGenerics -D HAS_NONCOPYABLE_GENERICS)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Tests that a C++ class can conform to a Swift protocol.

// RUN: %target-typecheck-verify-swift -I %S/Inputs -enable-experimental-cxx-interop
// RUN: %target-typecheck-verify-swift -I %S/Inputs -D VIRTUAL_METHODS -cxx-interoperability-mode=swift-5.9
// RUN: %target-typecheck-verify-swift -I %S/Inputs -D VIRTUAL_METHODS -cxx-interoperability-mode=swift-6
// RUN: %target-typecheck-verify-swift -I %S/Inputs -D VIRTUAL_METHODS -cxx-interoperability-mode=upcoming-swift

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-swift-ide-test -print-module -module-to-print=TypeClassification -I %S/Inputs -source-filename=x -cxx-interoperability-mode=swift-5.9 | %FileCheck %s
// RUN: %target-swift-ide-test -print-module -module-to-print=TypeClassification -I %S/Inputs -source-filename=x -cxx-interoperability-mode=swift-6 | %FileCheck %s
// RUN: %target-swift-ide-test -print-module -module-to-print=TypeClassification -I %S/Inputs -source-filename=x -cxx-interoperability-mode=upcoming-swift | %FileCheck %s
// RUN: %target-swift-ide-test -print-module -skip-unsafe-cxx-methods -module-to-print=TypeClassification -I %S/Inputs -source-filename=x -cxx-interoperability-mode=swift-6 | %FileCheck %s -check-prefix=CHECK-SKIP-UNSAFE
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=swift-5.9
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=swift-6
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=upcoming-swift

Expand Down
1 change: 1 addition & 0 deletions test/Interop/Cxx/function/default-arguments-irgen.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-swift-emit-irgen -I %S/Inputs -cxx-interoperability-mode=swift-5.9 %s | %FileCheck %s
// RUN: %target-swift-emit-irgen -I %S/Inputs -cxx-interoperability-mode=swift-6 %s | %FileCheck %s
// RUN: %target-swift-emit-irgen -I %S/Inputs -cxx-interoperability-mode=upcoming-swift %s | %FileCheck %s

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-swift-ide-test -print-module -module-to-print=DefaultArguments -I %S/Inputs -source-filename=x -cxx-interoperability-mode=swift-5.9 | %FileCheck %s
// RUN: %target-swift-ide-test -print-module -module-to-print=DefaultArguments -I %S/Inputs -source-filename=x -cxx-interoperability-mode=swift-6 | %FileCheck %s
// RUN: %target-swift-ide-test -print-module -module-to-print=DefaultArguments -I %S/Inputs -source-filename=x -cxx-interoperability-mode=upcoming-swift | %FileCheck %s

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -cxx-interoperability-mode=swift-5.9
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -cxx-interoperability-mode=swift-6
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -cxx-interoperability-mode=upcoming-swift

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-swift-ide-test -print-module -module-to-print=MemberInline -I %S/Inputs -source-filename=x -cxx-interoperability-mode=swift-5.9 | %FileCheck %s
// RUN: %target-swift-ide-test -print-module -module-to-print=MemberInline -I %S/Inputs -source-filename=x -cxx-interoperability-mode=swift-6 | %FileCheck %s
// RUN: %target-swift-ide-test -print-module -module-to-print=MemberInline -I %S/Inputs -source-filename=x -cxx-interoperability-mode=upcoming-swift | %FileCheck %s

Expand Down
1 change: 1 addition & 0 deletions test/Interop/Cxx/operators/member-inline-typechecker.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=swift-5.9
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=swift-6
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=upcoming-swift

Expand Down
1 change: 1 addition & 0 deletions test/Interop/Cxx/operators/member-inline.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -cxx-interoperability-mode=swift-5.9)
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -cxx-interoperability-mode=swift-6)
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -cxx-interoperability-mode=upcoming-swift)
//
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=swift-5.9)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=swift-6)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=upcoming-swift)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=upcoming-swift -enable-experimental-feature NoncopyableGenerics -D HAS_NONCOPYABLE_GENERICS)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=swift-5.9 -O)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=swift-6 -O)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=upcoming-swift -O)
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=upcoming-swift -O -enable-experimental-feature NoncopyableGenerics -D HAS_NONCOPYABLE_GENERICS)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=swift-5.9 -DNO_CONSUME
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=swift-6 -DNO_CONSUME
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=upcoming-swift -DNO_CONSUME

Expand Down
1 change: 1 addition & 0 deletions test/Interop/Cxx/stdlib/use-std-chrono.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=swift-5.9)
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=swift-6)
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=upcoming-swift)
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=upcoming-swift -Xcc -std=c++14)
Expand Down
1 change: 1 addition & 0 deletions test/Interop/Cxx/stdlib/use-std-optional.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -cxx-interoperability-mode=swift-5.9)
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -cxx-interoperability-mode=swift-6)
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -cxx-interoperability-mode=upcoming-swift)
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -cxx-interoperability-mode=upcoming-swift -Xcc -std=c++20)
Expand Down
Loading

0 comments on commit 3fe8b71

Please sign in to comment.