Skip to content

Commit 24aa9ac

Browse files
committed
[cxx-interop] Add support for templated member functions.
Essentially applying the same change as for supporting templated constructors.
1 parent 40723a1 commit 24aa9ac

File tree

6 files changed

+138
-3
lines changed

6 files changed

+138
-3
lines changed

lib/Sema/CSApply.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,12 @@ static ConcreteDeclRef generateDeclRefForSpecializedCXXFunctionTemplate(
115115
auto newFnType = oldFnType->substGenericArgs(subst);
116116
// The constructor type is a function type as follows:
117117
// (CType.Type) -> (Generic) -> CType
118-
// But we only want the result of that function type because that is the
119-
// function type with the generic params that need to be substituted:
118+
// And a method's function type is as follows:
119+
// (inout CType) -> (Generic) -> Void
120+
// In either case, we only want the result of that function type because that
121+
// is the function type with the generic params that need to be substituted:
120122
// (Generic) -> CType
121-
if (isa<ConstructorDecl>(oldDecl))
123+
if (isa<ConstructorDecl>(oldDecl) || oldDecl->isInstanceMember())
122124
newFnType = cast<FunctionType>(newFnType->getResult().getPointer());
123125
SmallVector<ParamDecl *, 4> newParams;
124126
unsigned i = 0;
@@ -159,6 +161,7 @@ static ConcreteDeclRef generateDeclRefForSpecializedCXXFunctionTemplate(
159161
/*Async=*/false, oldDecl->hasThrows(), newParamList,
160162
newFnType->getResult(), /*GenericParams=*/nullptr,
161163
oldDecl->getDeclContext(), specialized);
164+
newFnDecl->setSelfAccessKind(cast<FuncDecl>(oldDecl)->getSelfAccessKind());
162165
return ConcreteDeclRef(newFnDecl);
163166
}
164167

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
struct HasMemberTemplates {
2+
template <class T> T add(T a, T b) { return a + b; }
3+
4+
template <class T, class U> T addTwoTemplates(T a, U b) { return a + b; }
5+
6+
template <class T, class U> int addAll(int a, T b, U c) { return a + b + c; }
7+
8+
template <class T> T passThrough(T val) { return val; }
9+
10+
template <class T> T passThroughConst(const T val) { return val; }
11+
12+
template <class T> T passThroughOnConst(T val) const { return val; }
13+
14+
template <class T> T passThroughConstOnConst(const T val) const {
15+
return val;
16+
}
17+
18+
template <class T> void doNothingConstRef(const T &val) {}
19+
20+
template <class T> void make42Ref(T &val) {}
21+
};
22+
23+
template <class T> struct TemplateClassWithMemberTemplates {
24+
T value;
25+
26+
template <class U> void setValue(U val) { value = val; }
27+
28+
TemplateClassWithMemberTemplates(T val) : value(val) {}
29+
};
30+
31+
using IntWrapper = TemplateClassWithMemberTemplates<int>;

test/Interop/Cxx/templates/Inputs/module.modulemap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,7 @@ module ClassTemplateWithTypedef {
6161
module ClassTemplateInNamespace {
6262
header "class-template-in-namespace.h"
6363
}
64+
65+
module MemberTemplates {
66+
header "member-templates.h"
67+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-swift-ide-test -print-module -module-to-print=MemberTemplates -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s
2+
3+
// CHECK: struct HasMemberTemplates {
4+
// CHECK: mutating func add<T>(_ a: T, _ b: T) -> T
5+
// CHECK: mutating func addTwoTemplates<T, U>(_ a: T, _ b: U) -> T
6+
// CHECK: mutating func addAll<T, U>(_ a: Int32, _ b: T, _ c: U) -> Int32
7+
// CHECK: mutating func passThrough<T>(_ val: T) -> T
8+
// CHECK: mutating func passThroughConst<T>(_ val: T) -> T
9+
// CHECK: mutating func passThroughOnConst<T>(_ val: T) -> T
10+
// CHECK: mutating func passThroughConstOnConst<T>(_ val: T) -> T
11+
// CHECK: mutating func doNothingConstRef<T>(_ val: UnsafePointer<T>)
12+
// CHECK: mutating func make42Ref<T>(_ val: UnsafeMutablePointer<T>)
13+
// CHECK: }
14+
15+
// CHECK: struct __CxxTemplateInst32TemplateClassWithMemberTemplatesIiE {
16+
// CHECK: var value: Int32
17+
// CHECK: init(_ val: Int32)
18+
// CHECK: mutating func setValue<U>(_ val: U)
19+
// CHECK: }
20+
21+
// CHECK: typealias IntWrapper = __CxxTemplateInst32TemplateClassWithMemberTemplatesIiE
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// RUN: %target-swift-emit-sil %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s
2+
3+
// We can't yet call member functions correctly on Windows (SR-13129).
4+
// XFAIL: OS=windows-msvc
5+
// REQUIRES: fixing-after-30630
6+
7+
import MemberTemplates
8+
9+
// CHECK-LABEL: sil hidden @$s4main9basicTestyyF : $@convention(thin) () -> ()
10+
11+
// CHECK: [[ADD:%.*]] = function_ref @_ZN18HasMemberTemplates3addIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
12+
// CHECK: apply [[ADD]]({{.*}}) : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
13+
14+
// CHECK: [[ADD_TWO_TEMPLATES:%.*]] = function_ref @_ZN18HasMemberTemplates15addTwoTemplatesIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 // user: %26
15+
// CHECK: apply [[ADD_TWO_TEMPLATES]]({{.*}}) : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
16+
17+
// CHECK: [[ADD_ALL:%.*]] = function_ref @_ZN18HasMemberTemplates6addAllIiiEEiiT_T0_ : $@convention(c) (Int32, Int32, Int32, @inout HasMemberTemplates) -> Int32 // user: %39
18+
// CHECK: apply [[ADD_ALL]]({{.*}}) : $@convention(c) (Int32, Int32, Int32, @inout HasMemberTemplates) -> Int32
19+
20+
// CHECK: [[DO_NOTHING:%.*]] = function_ref @_ZN18HasMemberTemplates17doNothingConstRefIiEEvRKT_ : $@convention(c) (UnsafePointer<Int32>, @inout HasMemberTemplates) -> () // user: %48
21+
// CHECK: apply [[DO_NOTHING]]({{.*}}) : $@convention(c) (UnsafePointer<Int32>, @inout HasMemberTemplates) -> ()
22+
23+
// CHECK-LABEL: end sil function '$s4main9basicTestyyF'
24+
func basicTest() {
25+
var i: Int32 = 0
26+
var obj = HasMemberTemplates()
27+
obj.add(i, i)
28+
obj.addTwoTemplates(i, i)
29+
obj.addAll(i, i, i)
30+
obj.doNothingConstRef(&i)
31+
}
32+
33+
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates3addIiEET_S1_S1_] @_ZN18HasMemberTemplates3addIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
34+
35+
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates15addTwoTemplatesIiiEET_S1_T0_] @_ZN18HasMemberTemplates15addTwoTemplatesIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
36+
37+
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates6addAllIiiEEiiT_T0_] @_ZN18HasMemberTemplates6addAllIiiEEiiT_T0_ : $@convention(c) (Int32, Int32, Int32, @inout HasMemberTemplates) -> Int32
38+
39+
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates17doNothingConstRefIiEEvRKT_] @_ZN18HasMemberTemplates17doNothingConstRefIiEEvRKT_ : $@convention(c) (UnsafePointer<Int32>, @inout HasMemberTemplates) -> ()
40+
41+
// CHECK-LABEL: sil hidden @$s4main12testSetValueyyF : $@convention(thin) () -> ()
42+
43+
// CHECK: [[SET_VALUE:%.*]] = function_ref @_ZN32TemplateClassWithMemberTemplatesIiE8setValueIlEEvT_ : $@convention(c) (Int, @inout __CxxTemplateInst32TemplateClassWithMemberTemplatesIiE) -> ()
44+
// CHECK: apply [[SET_VALUE]]({{.*}}) : $@convention(c) (Int, @inout __CxxTemplateInst32TemplateClassWithMemberTemplatesIiE) -> ()
45+
46+
// CHECK-LABEL: end sil function '$s4main12testSetValueyyF'
47+
func testSetValue() {
48+
var w = IntWrapper(11)
49+
w.setValue(42)
50+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop)
2+
//
3+
// REQUIRES: executable_test
4+
//
5+
// We can't yet call member functions correctly on Windows (SR-13129).
6+
// XFAIL: OS=windows-msvc
7+
// REQUIRES: fixing-after-30630
8+
9+
import MemberTemplates
10+
import StdlibUnittest
11+
12+
var TemplatesTestSuite = TestSuite("Member Templates")
13+
14+
TemplatesTestSuite.test("Set value - IntWrapper") {
15+
var w = IntWrapper(11)
16+
w.setValue(42)
17+
expectEqual(w.value, 42)
18+
}
19+
20+
TemplatesTestSuite.test("Templated Add") {
21+
var h = HasMemberTemplates()
22+
expectEqual(h.add(2, 1), 3)
23+
expectEqual(h.addTwoTemplates(2, 1), 3)
24+
}
25+
26+
runAllTests()

0 commit comments

Comments
 (0)