Skip to content

Commit 7c1852e

Browse files
authored
Merge pull request #82485 from swiftlang/susmonteiro/rename-virtual-methods
[cxx-interop] Allow virtual methods to be renamed with SWIFT_NAME
2 parents 507f82c + b3e2288 commit 7c1852e

11 files changed

+165
-131
lines changed

lib/ClangImporter/ImportName.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,11 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
15311531
if (isa<clang::ObjCCategoryDecl>(D))
15321532
return ImportedName();
15331533

1534+
// C++ interop was not available in Swift 2
1535+
if (!swift3OrLaterName && isa<clang::CXXMethodDecl>(D)) {
1536+
return ImportedName();
1537+
}
1538+
15341539
// Dig out the definition, if there is one.
15351540
if (auto def = getDefinitionForClangTypeDecl(D)) {
15361541
if (*def)

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2125,6 +2125,8 @@ clang::CXXMethodDecl *SwiftDeclSynthesizer::synthesizeCXXForwardingMethod(
21252125
// convention.
21262126
newMethod->addAttr(clang::CFReturnsRetainedAttr::CreateImplicit(clangCtx));
21272127
}
2128+
if (auto swiftNameAttr = method->getAttr<clang::SwiftNameAttr>())
2129+
newMethod->addAttr(swiftNameAttr->clone(clangCtx));
21282130

21292131
llvm::SmallVector<clang::ParmVarDecl *, 4> params;
21302132
for (size_t i = 0; i < method->getNumParams(); ++i) {

test/Interop/Cxx/class/inheritance/Inputs/virtual-methods.h

Lines changed: 2 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ inline void testFunctionCollected() {
66

77
struct Base {
88
virtual void foo() = 0;
9+
virtual void virtualRename() const
10+
__attribute__((swift_name("swiftVirtualRename()")));
911
};
1012

1113
struct Base2 { virtual int f() = 0; };
@@ -49,48 +51,3 @@ struct DerivedFromCallsPureMethod : CallsPureMethod {
4951
};
5052

5153
struct DerivedFromDerivedFromCallsPureMethod : DerivedFromCallsPureMethod {};
52-
53-
struct HasDestructor {
54-
~HasDestructor() {}
55-
};
56-
57-
// MARK: Reference Types:
58-
59-
#define IMMORTAL_FRT \
60-
__attribute__((swift_attr("import_reference"))) \
61-
__attribute__((swift_attr("retain:immortal"))) \
62-
__attribute__((swift_attr("release:immortal")))
63-
64-
struct IMMORTAL_FRT ImmortalBase {
65-
int value = 0;
66-
67-
virtual int get42() const { return 42; }
68-
virtual int getOverridden42() const { return 123; }
69-
virtual int getIntValue() const { return value; }
70-
};
71-
72-
struct IMMORTAL_FRT Immortal : public ImmortalBase {
73-
static Immortal *_Nonnull create() { return new Immortal(); }
74-
75-
virtual int getOverridden42() const override { return 42; }
76-
virtual void setIntValue(int newValue) { this->value = newValue; }
77-
};
78-
79-
struct IMMORTAL_FRT DerivedFromImmortal : public Immortal {
80-
static DerivedFromImmortal *_Nonnull create() { return new DerivedFromImmortal(); }
81-
};
82-
83-
struct IMMORTAL_FRT Immortal2 {
84-
public:
85-
virtual void virtualMethod(HasDestructor) = 0;
86-
};
87-
88-
inline const ImmortalBase *_Nonnull castToImmortalBase(
89-
const Immortal *_Nonnull immortal) {
90-
return static_cast<const ImmortalBase *>(immortal);
91-
}
92-
93-
inline const Immortal *_Nonnull castToImmortal(
94-
const DerivedFromImmortal *_Nonnull immortal) {
95-
return static_cast<const Immortal *>(immortal);
96-
}

test/Interop/Cxx/class/inheritance/functions-module-interface.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@
2828
// CHECK-NEXT: public static func staticInBase() -> UnsafePointer<CChar>!
2929
// CHECK-NEXT: @discardableResult
3030
// CHECK-NEXT: public mutating func swiftRenamed(input i: Int32) -> Int32
31-
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "swiftRenamed(input:)")
32-
// CHECK-NEXT: public mutating func renamed(_ i: Int32) -> Int32
3331
// CHECK-NEXT: @discardableResult
3432
// CHECK-NEXT: @_effects(readonly) public func pure() -> Int32
3533
// CHECK-NEXT: @discardableResult
@@ -64,8 +62,6 @@
6462
// CHECK-NEXT: public func returnsNonTrivialInBase() -> NonTrivial
6563
// CHECK-NEXT: @discardableResult
6664
// CHECK-NEXT: public mutating func swiftRenamed(input i: Int32) -> Int32
67-
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "swiftRenamed(input:)")
68-
// CHECK-NEXT: public mutating func renamed(_ i: Int32) -> Int32
6965
// CHECK-NEXT: @discardableResult
7066
// CHECK-NEXT: @_effects(readonly) public func pure() -> Int32
7167
// CHECK-NEXT: @discardableResult
@@ -96,8 +92,6 @@
9692
// CHECK-NEXT: public func returnsNonTrivialInBase() -> NonTrivial
9793
// CHECK-NEXT: @discardableResult
9894
// CHECK-NEXT: public mutating func swiftRenamed(input i: Int32) -> Int32
99-
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "swiftRenamed(input:)")
100-
// CHECK-NEXT: public mutating func renamed(_ i: Int32) -> Int32
10195
// CHECK-NEXT: @discardableResult
10296
// CHECK-NEXT: @_effects(readonly) public func pure() -> Int32
10397
// CHECK-NEXT: @discardableResult

test/Interop/Cxx/class/inheritance/virtual-methods-module-interface.swift

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// CHECK-NEXT: init()
88
// CHECK-NEXT: @available(*, unavailable, message: "virtual function is not available in Swift because it is pure")
99
// CHECK-NEXT: mutating func foo()
10+
// CHECK-NEXT: func swiftVirtualRename()
1011
// CHECK: }
1112

1213
// CHECK: struct Base3 {
@@ -25,12 +26,3 @@
2526
// CHECK: struct VirtualNonAbstractBase {
2627
// CHECK-NEXT: init()
2728
// CHECK-NEXT: func nonAbstractMethod()
28-
29-
// CHECK: class ImmortalBase {
30-
// CHECK: func get42() -> Int32
31-
// CHECK: func getOverridden42() -> Int32
32-
// CHECK: }
33-
// CHECK: class Immortal {
34-
// CHECK: func getOverridden42() -> Int32
35-
// CHECK: func get42() -> Int32
36-
// CHECK: }

test/Interop/Cxx/class/inheritance/virtual-methods-typechecker.swift

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,7 @@ let _ = DerivedFromDerived2()
1515

1616
VirtualNonAbstractBase().nonAbstractMethod()
1717

18-
@available(SwiftStdlib 5.8, *)
19-
func takesImmortalBase(_ i: ImmortalBase) {
20-
let _ = i.get42()
21-
let _ = i.getOverridden42()
22-
let _ = i.getIntValue()
23-
}
24-
25-
@available(SwiftStdlib 5.8, *)
26-
func takesImmortal(_ i: Immortal) {
27-
let _ = i.get42()
28-
let _ = i.getOverridden42()
29-
let _ = i.getIntValue()
30-
i.setIntValue(1)
31-
}
32-
33-
@available(SwiftStdlib 5.8, *)
34-
func takesDerivedFromImmortal(_ i: DerivedFromImmortal) {
35-
let _ = i.get42()
36-
let _ = i.getOverridden42()
37-
let _ = i.getIntValue()
38-
i.setIntValue(1)
18+
func callVirtualRenamedMethod(_ b: Base) {
19+
b.virtualRename() // expected-error {{value of type 'Base' has no member 'virtualRename'}}
20+
b.swiftVirtualRename()
3921
}

test/Interop/Cxx/class/inheritance/virtual-methods.swift

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -29,39 +29,4 @@ VirtualMethodsTestSuite.test("value type") {
2929
expectEqual(789, d6.getPureInt())
3030
}
3131

32-
if #available(SwiftStdlib 5.8, *) {
33-
VirtualMethodsTestSuite.test("immortal reference type") {
34-
let i = Immortal.create()
35-
expectEqual(42, i.get42())
36-
expectEqual(0, i.getIntValue())
37-
38-
let base = castToImmortalBase(i)
39-
expectEqual(42, base.get42())
40-
expectEqual(42, base.getOverridden42())
41-
expectEqual(0, base.getIntValue())
42-
43-
i.setIntValue(566)
44-
expectEqual(566, i.getIntValue())
45-
expectEqual(566, base.getIntValue())
46-
47-
let d = DerivedFromImmortal.create()
48-
expectEqual(42, d.get42())
49-
expectEqual(42, d.getOverridden42())
50-
d.setIntValue(321)
51-
expectEqual(321, d.getIntValue())
52-
let base2 = castToImmortalBase(castToImmortal(d))
53-
expectEqual(321, base2.getIntValue())
54-
}
55-
}
56-
57-
#if !os(Windows)
58-
// FIXME in Windows, non-trivial C++ class with trivial ABI is not yet available in Swift
59-
VirtualMethodsTestSuite.test("C++ virtual method with complex parameter") {
60-
@available(SwiftStdlib 5.8, *)
61-
func f(simpleClass: HasDestructor, immortalClass: Immortal2) {
62-
immortalClass.virtualMethod(simpleClass)
63-
}
64-
}
65-
#endif
66-
6732
runAllTests()

test/Interop/Cxx/foreign-reference/Inputs/member-inheritance.h

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#pragma once
22

3-
#define FRT \
3+
#define IMMORTAL_FRT \
44
__attribute__((swift_attr("import_reference"))) \
55
__attribute__((swift_attr("retain:immortal"))) \
66
__attribute__((swift_attr("release:immortal")))
@@ -28,7 +28,7 @@ class CopyTrackedBaseClass {
2828
}
2929
private:
3030
int x;
31-
} FRT;
31+
} IMMORTAL_FRT;
3232

3333
class CopyTrackedDerivedClass: public CopyTrackedBaseClass {
3434
public:
@@ -37,7 +37,7 @@ class CopyTrackedDerivedClass: public CopyTrackedBaseClass {
3737
int getDerivedX() const {
3838
return getX();
3939
}
40-
} FRT;
40+
} IMMORTAL_FRT;
4141

4242
CopyTrackedDerivedClass *makeCopyTrackedDerivedClass(int x) {
4343
return new CopyTrackedDerivedClass(x);
@@ -50,12 +50,12 @@ class NonEmptyBase {
5050
}
5151
private:
5252
int y = 11;
53-
} FRT;
53+
} IMMORTAL_FRT;
5454

5555
class CopyTrackedDerivedDerivedClass: public NonEmptyBase, public CopyTrackedDerivedClass {
5656
public:
5757
CopyTrackedDerivedDerivedClass(int x) : CopyTrackedDerivedClass(x) {}
58-
} FRT;
58+
} IMMORTAL_FRT;
5959

6060
CopyTrackedDerivedDerivedClass *makeCopyTrackedDerivedDerivedClass(int x) {
6161
return new CopyTrackedDerivedDerivedClass(x);
@@ -66,15 +66,14 @@ class BaseReturningFRTFromSubscript {
6666
CopyTrackedDerivedClass &operator[](int x) const {
6767
return *new CopyTrackedDerivedClass(x);
6868
}
69-
} FRT;
69+
} IMMORTAL_FRT;
7070

7171
BaseReturningFRTFromSubscript *makeBaseReturningFRTFromSubscript() {
7272
return new BaseReturningFRTFromSubscript();
7373
}
7474

75-
class DerivedFromBaseReturningFRTFromSubscript: public BaseReturningFRTFromSubscript {
76-
public:
77-
} FRT;
75+
class DerivedFromBaseReturningFRTFromSubscript
76+
: public BaseReturningFRTFromSubscript{public : } IMMORTAL_FRT;
7877

7978
DerivedFromBaseReturningFRTFromSubscript *makeDerivedFromBaseReturningFRTFromSubscript() {
8079
return new DerivedFromBaseReturningFRTFromSubscript();
@@ -90,12 +89,53 @@ class BaseReturningFRTFromSubscriptPointer {
9089

9190
private:
9291
CopyTrackedDerivedClass *value;
93-
} FRT;
92+
} IMMORTAL_FRT;
9493

95-
class DerivedFromBaseReturningFRTFromSubscriptPointer: public BaseReturningFRTFromSubscriptPointer {
96-
public:
97-
} FRT;
94+
class DerivedFromBaseReturningFRTFromSubscriptPointer
95+
: public BaseReturningFRTFromSubscriptPointer{public : } IMMORTAL_FRT;
9896

9997
DerivedFromBaseReturningFRTFromSubscriptPointer *makeDerivedFromBaseReturningFRTFromSubscriptPointer() {
10098
return new DerivedFromBaseReturningFRTFromSubscriptPointer();
10199
}
100+
101+
struct IMMORTAL_FRT ImmortalBase {
102+
int value = 0;
103+
104+
virtual int get42() const { return 42; }
105+
virtual int getOverridden42() const { return 123; }
106+
virtual int getIntValue() const { return value; }
107+
};
108+
109+
struct IMMORTAL_FRT Immortal : public ImmortalBase {
110+
static Immortal *_Nonnull create() { return new Immortal(); }
111+
112+
virtual int getOverridden42() const override { return 42; }
113+
virtual void setIntValue(int newValue) { this->value = newValue; }
114+
};
115+
116+
struct IMMORTAL_FRT DerivedFromImmortal : public Immortal {
117+
static DerivedFromImmortal *_Nonnull create() {
118+
return new DerivedFromImmortal();
119+
}
120+
};
121+
122+
struct HasDestructor {
123+
~HasDestructor() {}
124+
};
125+
126+
struct IMMORTAL_FRT Immortal2 {
127+
public:
128+
virtual void virtualMethod(HasDestructor) = 0;
129+
virtual void virtualRename() const
130+
__attribute__((swift_name("swiftVirtualRename()")));
131+
};
132+
133+
inline const ImmortalBase *_Nonnull castToImmortalBase(
134+
const Immortal *_Nonnull immortal) {
135+
return static_cast<const ImmortalBase *>(immortal);
136+
}
137+
138+
inline const Immortal *_Nonnull castToImmortal(
139+
const DerivedFromImmortal *_Nonnull immortal) {
140+
return static_cast<const Immortal *>(immortal);
141+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-ide-test -print-module -cxx-interoperability-mode=swift-5.9 -print-implicit-attrs -module-to-print=MemberInheritance -I %S/Inputs -source-filename=x | %FileCheck %s
2+
// RUN: %target-swift-ide-test -print-module -cxx-interoperability-mode=swift-6 -print-implicit-attrs -module-to-print=MemberInheritance -I %S/Inputs -source-filename=x | %FileCheck %s
3+
// RUN: %target-swift-ide-test -print-module -cxx-interoperability-mode=upcoming-swift -print-implicit-attrs -module-to-print=MemberInheritance -I %S/Inputs -source-filename=x | %FileCheck %s
4+
5+
// CHECK: class ImmortalBase {
6+
// CHECK: func get42() -> Int32
7+
// CHECK: func getOverridden42() -> Int32
8+
// CHECK: }
9+
// CHECK: class Immortal {
10+
// CHECK: func getOverridden42() -> Int32
11+
// CHECK: func get42() -> Int32
12+
// CHECK: }
13+
14+
// CHECK: class Immortal2 {
15+
// CHECK-NEXT: final func virtualMethod(_: HasDestructor)
16+
// CHECK-NEXT: final func swiftVirtualRename()
17+
// CHECK: }
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -cxx-interoperability-mode=upcoming-swift
2+
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -cxx-interoperability-mode=swift-5.9
3+
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -cxx-interoperability-mode=swift-6
4+
5+
import MemberInheritance
6+
7+
@available(SwiftStdlib 5.8, *)
8+
func takesImmortalBase(_ i: ImmortalBase) {
9+
let _ = i.get42()
10+
let _ = i.getOverridden42()
11+
let _ = i.getIntValue()
12+
}
13+
14+
@available(SwiftStdlib 5.8, *)
15+
func takesImmortal(_ i: Immortal) {
16+
let _ = i.get42()
17+
let _ = i.getOverridden42()
18+
let _ = i.getIntValue()
19+
i.setIntValue(1)
20+
}
21+
22+
@available(SwiftStdlib 5.8, *)
23+
func takesDerivedFromImmortal(_ i: DerivedFromImmortal) {
24+
let _ = i.get42()
25+
let _ = i.getOverridden42()
26+
let _ = i.getIntValue()
27+
i.setIntValue(1)
28+
}
29+
30+
@available(SwiftStdlib 5.8, *)
31+
func callsRenamedVirtualMethodsInFRT(_ i: Immortal2) {
32+
i.virtualRename() // expected-error {{value of type 'Immortal2' has no member 'virtualRename'}}
33+
i.swiftVirtualRename()
34+
}

0 commit comments

Comments
 (0)