Skip to content

Commit cb7bb52

Browse files
authored
[cxx-interop] Support reference types in function templates. (swiftlang#34536)
1 parent b785a5f commit cb7bb52

File tree

4 files changed

+29
-2
lines changed

4 files changed

+29
-2
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,8 +1814,20 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList(
18141814
// Import the parameter type into Swift.
18151815
Type swiftParamTy;
18161816
bool isParamTypeImplicitlyUnwrapped = false;
1817-
if (auto *templateParamType =
1818-
dyn_cast<clang::TemplateTypeParmType>(paramTy)) {
1817+
1818+
auto referenceType = dyn_cast<clang::ReferenceType>(paramTy);
1819+
if (referenceType &&
1820+
isa<clang::TemplateTypeParmType>(referenceType->getPointeeType())) {
1821+
auto pointeeType = referenceType->getPointeeType();
1822+
auto templateParamType = cast<clang::TemplateTypeParmType>(pointeeType);
1823+
PointerTypeKind pointerKind = pointeeType.getQualifiers().hasConst()
1824+
? PTK_UnsafePointer
1825+
: PTK_UnsafeMutablePointer;
1826+
auto genericType =
1827+
findGenericTypeInGenericDecls(templateParamType, genericParams);
1828+
swiftParamTy = genericType->wrapInPointer(pointerKind);
1829+
} else if (auto *templateParamType =
1830+
dyn_cast<clang::TemplateTypeParmType>(paramTy)) {
18191831
swiftParamTy =
18201832
findGenericTypeInGenericDecls(templateParamType, genericParams);
18211833
} else {

test/Interop/Cxx/templates/Inputs/function-templates.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,9 @@ decltype(auto) testAuto(T arg) {
4646
template <class T> struct Dep { using TT = T; };
4747

4848
template <class T> void useDependentType(typename Dep<T>::TT) {}
49+
50+
template <class T> void lvalueReference(T &ref) { ref = 42; }
51+
52+
template <class T> void constLvalueReference(const T &) {}
53+
54+
template <class T> void forwardingReference(T &&) {}

test/Interop/Cxx/templates/function-template-module-interface.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@
66
// CHECK: func passThroughConst<T>(_ value: T) -> T
77
// CHECK: func returns_template<R, T, U>(_ a: T, _ b: U) -> R
88
// CHECK: func cannot_infer_template<T>()
9+
// CHECK: func lvalueReference<T>(_ ref: UnsafeMutablePointer<T>)
10+
// CHECK: func constLvalueReference<T>(_: UnsafePointer<T>)
11+
// CHECK: func forwardingReference<T>(_: UnsafeMutablePointer<T>)

test/Interop/Cxx/templates/function-template.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ FunctionTemplateTestSuite.test("add<T, U> where T, U == Int") {
2222
expectEqual(65, result)
2323
}
2424

25+
FunctionTemplateTestSuite.test("lvalueReference<T> where T == Int") {
26+
var value = 0
27+
lvalueReference(&value)
28+
expectEqual(value, 42)
29+
}
30+
2531
// TODO: currently "Any" is imported as an Objective-C "id".
2632
// This doesn't work without the Objective-C runtime.
2733
#if _runtime(_ObjC)

0 commit comments

Comments
 (0)