Skip to content

Commit 50f55c1

Browse files
authored
Merge pull request #35416 from zoecarver/cxx/cleanup-function-template-post-commit
[NFC] Cleanup function templates implementation. Address post-commit review comments from #33053.
2 parents 742ad76 + c4da497 commit 50f55c1

16 files changed

+105
-89
lines changed

include/swift/AST/ASTContext.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,15 @@ class ASTContext final {
629629
ArrayRef<SILParameterInfo> params, Optional<SILResultInfo> result,
630630
SILFunctionType::Representation trueRep);
631631

632-
/// Instantiates "Impl.Converter" if needed, then calls
633-
/// ClangTypeConverter::getClangTemplateArguments.
632+
/// Instantiates "Impl.Converter" if needed, then translate Swift generic
633+
/// substitutions to equivalent C++ types using \p templateParams and \p
634+
/// genericArgs. The converted Clang types are placed into \p templateArgs.
635+
///
636+
/// \p templateArgs must be empty. \p templateParams and \p genericArgs must
637+
/// be equal in size.
638+
///
639+
/// \returns nullptr if successful. If an error occors, returns a list of
640+
/// types that couldn't be converted.
634641
std::unique_ptr<TemplateInstantiationError> getClangTemplateArguments(
635642
const clang::TemplateParameterList *templateParams,
636643
ArrayRef<Type> genericArgs,

include/swift/AST/ClangModuleLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ class ClangModuleLoader : public ModuleLoader {
228228
SubstitutionMap subst) = 0;
229229
};
230230

231-
/// Used to describe a template instantiation error.
231+
/// Describes a C++ template instantiation error.
232232
struct TemplateInstantiationError {
233233
/// Generic types that could not be converted to QualTypes using the
234234
/// ClangTypeConverter.

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1692,7 +1692,7 @@ ERROR(where_nongeneric_toplevel,none,
16921692
"declaration", ())
16931693
ERROR(unable_to_convert_generic_swift_types,none,
16941694
"could not generate C++ types from the generic Swift types provided. "
1695-
"The following Swift type(s) provided to '%0' were unable to be "
1695+
"The following Swift type(s) provided to '%0' could not be "
16961696
"converted: %1.",
16971697
(StringRef, StringRef))
16981698

lib/AST/ClangTypeConverter.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,12 +860,15 @@ ClangTypeConverter::getClangTemplateArguments(
860860
const clang::TemplateParameterList *templateParams,
861861
ArrayRef<Type> genericArgs,
862862
SmallVectorImpl<clang::TemplateArgument> &templateArgs) {
863+
assert(templateArgs.size() == 0);
864+
assert(genericArgs.size() == templateParams->size());
865+
863866
// Keep track of the types we failed to convert so we can return a useful
864867
// error.
865868
SmallVector<Type, 2> failedTypes;
866869
for (clang::NamedDecl *param : *templateParams) {
867870
// Note: all template parameters must be template type parameters. This is
868-
// verified when we import the clang decl.
871+
// verified when we import the Clang decl.
869872
auto templateParam = cast<clang::TemplateTypeParmDecl>(param);
870873
auto replacement = genericArgs[templateParam->getIndex()];
871874
auto qualType = convert(replacement);
@@ -878,6 +881,9 @@ ClangTypeConverter::getClangTemplateArguments(
878881
}
879882
if (failedTypes.empty())
880883
return nullptr;
884+
// Clear "templateArgs" to prevent the clients from accidently reading a
885+
// partially converted set of template arguments.
886+
templateArgs.clear();
881887
auto errorInfo = std::make_unique<TemplateInstantiationError>();
882888
llvm::for_each(failedTypes, [&errorInfo](auto type) {
883889
errorInfo->failedTypes.push_back(type);

lib/AST/ClangTypeConverter.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,13 @@ class ClangTypeConverter :
8484
/// Swift declaration.
8585
Decl *getSwiftDeclForExportedClangDecl(const clang::Decl *decl) const;
8686

87-
/// Translate Swift generic arguments to template arguments.
87+
/// Translate Swift generic arguments to Clang C++ template arguments.
8888
///
89-
/// \returns nullptr if successful. If an error occors, returns a unique_ptr
90-
/// to a `TemplateInstantiationError` with a list of the failed types.
89+
/// \p templateArgs must be empty. \p templateParams and \p genericArgs must
90+
/// be equal in size.
91+
///
92+
/// \returns nullptr if successful. If an error occors, returns a list of
93+
/// types that couldn't be converted.
9194
std::unique_ptr<TemplateInstantiationError> getClangTemplateArguments(
9295
const clang::TemplateParameterList *templateParams,
9396
ArrayRef<Type> genericArgs,

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_FUNCTION_TEMPLATES_H
22
#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_FUNCTION_TEMPLATES_H
33

4-
template <class T> T add(T a, T b) { return a + b; }
4+
template <class T> T addSameTypeParams(T a, T b) { return a + b; }
55

6-
template <class A, class B> A addTwoTemplates(A a, B b) { return a + b; }
6+
template <class A, class B> A addMixedTypeParams(A a, B b) { return a + b; }
77

88
template <class T> T passThrough(T value) { return value; }
99

1010
template <class T> const T passThroughConst(const T value) { return value; }
1111

1212
void takesString(const char *) {}
13-
template <class T> void expectsString(T str) { takesString(str); }
13+
template <class T> void expectsConstCharPtr(T str) { takesString(str); }
1414

15-
template <long x> void integerTemplate() {}
16-
template <long x = 0> void defaultIntegerTemplate() {}
15+
template <long x> void hasNonTypeTemplateParameter() {}
16+
template <long x = 0> void hasDefaultedNonTypeTemplateParameter() {}
1717

18-
// We cannot yet use this in swift but, make sure we don't crash when parsing
18+
// We cannot yet use this in Swift but, make sure we don't crash when parsing
1919
// it.
20-
template <class R, class T, class U> R returns_template(T a, U b) {
20+
template <class R, class T, class U> R templateParameterReturnType(T a, U b) {
2121
return a + b;
2222
}
2323

2424
// Same here:
25-
template <class T> void cannot_infer_template() {}
25+
template <class T> void cannotInferTemplate() {}
2626

2727
struct HasVariadicMemeber {
2828
void test1(...) {}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
struct HasMemberTemplates {
2-
template <class T> T add(T a, T b) { return a + b; }
2+
template <class T> T addSameTypeParams(T a, T b) { return a + b; }
33

4-
template <class T, class U> T addTwoTemplates(T a, U b) { return a + b; }
4+
template <class T, class U> T addMixedTypeParams(T a, U b) { return a + b; }
55

66
template <class T, class U> int addAll(int a, T b, U c) { return a + b + c; }
77

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

Lines changed: 0 additions & 39 deletions
This file was deleted.

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,20 @@ public func testPassThrough(x: Int32) -> Int32 {
2020
return passThrough(x)
2121
}
2222

23-
// CHECK-LABEL: define {{.*}}i32 @"$s4main19testAddTwoTemplates1xs5Int32VAE_tF"(i32 %0)
24-
// CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z15addTwoTemplatesIiiET_S0_T0_|"\?\?\$addTwoTemplates@HH@@YAHHH@Z"}}(i32 %0, i32 %0)
23+
// CHECK-LABEL: define {{.*}}i32 @"$s4main22testAddMixedTypeParams1xs5Int32VAE_tF"(i32 %0)
24+
// CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z18addMixedTypeParamsIiiET_S0_T0_|"\?\?\$addMixedTypeParams@HH@@YAHHH@Z"}}(i32 %0, i32 %0)
2525
// CHECK: ret i32 [[OUT_VAL]]
2626

27-
// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z15addTwoTemplatesIiiET_S0_T0_|"\?\?\$addTwoTemplates@HH@@YAHHH@Z"}}(i32 %a, i32 %b)
28-
public func testAddTwoTemplates(x: Int32) -> Int32 {
29-
return addTwoTemplates(x, x)
27+
// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z18addMixedTypeParamsIiiET_S0_T0_|"\?\?\$addMixedTypeParams@HH@@YAHHH@Z"}}(i32 %a, i32 %b)
28+
public func testAddMixedTypeParams(x: Int32) -> Int32 {
29+
return addMixedTypeParams(x, x)
3030
}
3131

32-
// CHECK-LABEL: define {{.*}}i32 @"$s4main7testAdd1xs5Int32VAE_tF"(i32 %0)
33-
// CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z3addIiET_S0_S0_|"\?\?\$add@H@@YAHHH@Z"}}(i32 %0, i32 %0)
32+
// CHECK-LABEL: define {{.*}}i32 @"$s4main21testAddSameTypeParams1xs5Int32VAE_tF"(i32 %0)
33+
// CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z17addSameTypeParamsIiET_S0_S0_|"\?\?\$addSameTypeParams@H@@YAHHH@Z"}}(i32 %0, i32 %0)
3434
// CHECK: ret i32 [[OUT_VAL]]
3535

36-
// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z3addIiET_S0_S0_|"\?\?\$add@H@@YAHHH@Z"}}(i32 %a, i32 %b)
37-
public func testAdd(x: Int32) -> Int32 {
38-
return add(x, x)
36+
// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z17addSameTypeParamsIiET_S0_S0_|"\?\?\$addSameTypeParams@H@@YAHHH@Z"}}(i32 %a, i32 %b)
37+
public func testAddSameTypeParams(x: Int32) -> Int32 {
38+
return addSameTypeParams(x, x)
3939
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// RUN: %target-swift-ide-test -print-module -module-to-print=FunctionTemplates -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s
22

3-
// CHECK: func add<T>(_ a: T, _ b: T) -> T
4-
// CHECK: func addTwoTemplates<A, B>(_ a: A, _ b: B) -> A
3+
// CHECK: func addSameTypeParams<T>(_ a: T, _ b: T) -> T
4+
// CHECK: func addMixedTypeParams<A, B>(_ a: A, _ b: B) -> A
55
// CHECK: func passThrough<T>(_ value: T) -> T
66
// CHECK: func passThroughConst<T>(_ value: T) -> T
7-
// CHECK: func returns_template<R, T, U>(_ a: T, _ b: U) -> R
8-
// CHECK: func cannot_infer_template<T>()
7+
// CHECK: func templateParameterReturnType<R, T, U>(_ a: T, _ b: U) -> R
8+
// CHECK: func cannotInferTemplate<T>()
99

1010
// CHECK: struct HasVariadicMemeber {
1111
// CHECK: @available(*, unavailable, message: "Variadic function is unavailable")

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@ import FunctionTemplates
1313
// CHECK: [[PASS_THROUGH_FN:%.*]] = function_ref @{{_Z11passThroughIiET_S0_|\?\?\$passThrough@H@@YAHH@Z}} : $@convention(c) (Int32) -> Int32
1414
// CHECK: [[B:%.*]] = apply [[PASS_THROUGH_FN]](%0) : $@convention(c) (Int32) -> Int32
1515

16-
// CHECK: [[ADD_TWO_FN:%.*]] = function_ref @{{_Z15addTwoTemplatesIiiET_S0_T0_|\?\?\$addTwoTemplates@HH@@YAHHH@Z}} : $@convention(c) (Int32, Int32) -> Int32
16+
// CHECK: [[ADD_TWO_FN:%.*]] = function_ref @{{_Z18addMixedTypeParamsIiiET_S0_T0_|\?\?\$addMixedTypeParams@HH@@YAHHH@Z}} : $@convention(c) (Int32, Int32) -> Int32
1717
// CHECK: [[C:%.*]] = apply [[ADD_TWO_FN]]([[A]], [[B]]) : $@convention(c) (Int32, Int32) -> Int32
1818

1919
// CHECK: [[C_32_ADDR:%.*]] = alloc_stack $Int32
2020
// CHECK: [[C_32:%.*]] = load [[C_32_ADDR]] : $*Int32
21-
// CHECK: [[ADD_FN:%.*]] = function_ref @{{_Z3addIiET_S0_S0_|\?\?\$add@H@@YAHHH@Z}} : $@convention(c) (Int32, Int32) -> Int32
21+
// CHECK: [[ADD_FN:%.*]] = function_ref @{{_Z17addSameTypeParamsIiET_S0_S0_|\?\?\$addSameTypeParams@H@@YAHHH@Z}} : $@convention(c) (Int32, Int32) -> Int32
2222
// CHECK: [[OUT:%.*]] = apply [[ADD_FN]]([[B]], [[C_32]]) : $@convention(c) (Int32, Int32) -> Int32
2323
// CHECK: return [[OUT]] : $Int32
2424

2525
// CHECK-LABEL: end sil function '$s4main4test1xs5Int32VAE_tF'
2626
public func test(x: Int32) -> Int32 {
2727
let a = passThroughConst(Int32(0))
2828
let b = passThrough(x)
29-
let c = addTwoTemplates(a, b)
30-
return add(b, Int32(c))
29+
let c = addMixedTypeParams(a, b)
30+
return addSameTypeParams(b, Int32(c))
3131
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: not %target-typecheck-verify-swift %s -I %S/Inputs -enable-cxx-interop 2>&1 | %FileCheck %s
2+
3+
// README: If you just added support for protocol composition to the
4+
// ClangTypeConverter, please update this test to use a different type that we
5+
// don't support so the error messages here are still tested.
6+
7+
8+
import FunctionTemplates
9+
10+
// Make sure we don't import non-type template parameters.
11+
// CHECK: error: unexpected error produced: cannot find 'hasNonTypeTemplateParameter' in scope
12+
// CHECK: error: unexpected error produced: cannot find 'hasDefaultedNonTypeTemplateParameter' in scope
13+
public func callIntegerTemplates() {
14+
hasNonTypeTemplateParameter()
15+
hasDefaultedNonTypeTemplateParameter()
16+
}
17+
18+
// Use protocol composition to create a type that we cannot (yet) turn into a clang::QualType.
19+
public protocol A { }
20+
public protocol B { }
21+
public protocol C { }
22+
23+
// CHECK: error: unexpected error produced: could not generate C++ types from the generic Swift types provided. The following Swift type(s) provided to 'passThrough' could not be converted: A & B.
24+
public func caller1(x: A & B) -> A & B {
25+
return passThrough(x)
26+
}
27+
28+
// CHECK: error: unexpected error produced: could not generate C++ types from the generic Swift types provided. The following Swift type(s) provided to 'addMixedTypeParams' could not be converted: A & B, A & C.
29+
public func caller2(x: A & B, y: A & C) -> A & B {
30+
return addMixedTypeParams(x, y)
31+
}
32+
33+
// Make sure we emit an error and don't crash when failing to instantiate a function.
34+
// CHECK: error: diagnostic produced elsewhere: no matching function for call to 'takesString'
35+
// CHECK: note: diagnostic produced elsewhere: in instantiation of function template specialization 'expectsConstCharPtr<int>' requested here
36+
// CHECK: note: diagnostic produced elsewhere: candidate function not viable: no known conversion from 'int' to 'const char *' for 1st argument
37+
public func callexpectsConstCharPtr() {
38+
expectsConstCharPtr(0 as Int32)
39+
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ FunctionTemplateTestSuite.test("passThrough<T> where T == Int") {
1212
expectEqual(42, result)
1313
}
1414

15-
FunctionTemplateTestSuite.test("add<T> where T == Int") {
16-
let result = add(42, 23)
15+
FunctionTemplateTestSuite.test("addSameTypeParams<T> where T == Int") {
16+
let result = addSameTypeParams(42, 23)
1717
expectEqual(65, result)
1818
}
1919

20-
FunctionTemplateTestSuite.test("add<T, U> where T, U == Int") {
21-
let result = addTwoTemplates(42, 23)
20+
FunctionTemplateTestSuite.test("addSameTypeParams<T, U> where T, U == Int") {
21+
let result = addMixedTypeParams(42, 23)
2222
expectEqual(65, result)
2323
}
2424

test/Interop/Cxx/templates/member-templates-module-interface.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// RUN: %target-swift-ide-test -print-module -module-to-print=MemberTemplates -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s
22

33
// 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
4+
// CHECK: mutating func addSameTypeParams<T>(_ a: T, _ b: T) -> T
5+
// CHECK: mutating func addMixedTypeParams<T, U>(_ a: T, _ b: U) -> T
66
// CHECK: mutating func addAll<T, U>(_ a: Int32, _ b: T, _ c: U) -> Int32
77
// CHECK: mutating func passThrough<T>(_ val: T) -> T
88
// CHECK: mutating func passThroughConst<T>(_ val: T) -> T

test/Interop/Cxx/templates/member-templates-silgen.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import MemberTemplates
88

99
// CHECK-LABEL: sil hidden @$s4main9basicTestyyF : $@convention(thin) () -> ()
1010

11-
// CHECK: [[ADD:%.*]] = function_ref @_ZN18HasMemberTemplates3addIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
11+
// CHECK: [[ADD:%.*]] = function_ref @_ZN18HasMemberTemplates3addSameTypeParamsIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
1212
// CHECK: apply [[ADD]]({{.*}}) : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
1313

14-
// CHECK: [[ADD_TWO_TEMPLATES:%.*]] = function_ref @_ZN18HasMemberTemplates15addTwoTemplatesIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 // user: %26
14+
// CHECK: [[ADD_TWO_TEMPLATES:%.*]] = function_ref @_ZN18HasMemberTemplates15addMixedTypeParamsIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 // user: %26
1515
// CHECK: apply [[ADD_TWO_TEMPLATES]]({{.*}}) : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
1616

1717
// CHECK: [[ADD_ALL:%.*]] = function_ref @_ZN18HasMemberTemplates6addAllIiiEEiiT_T0_ : $@convention(c) (Int32, Int32, Int32, @inout HasMemberTemplates) -> Int32 // user: %39
@@ -24,15 +24,15 @@ import MemberTemplates
2424
func basicTest() {
2525
var i: Int32 = 0
2626
var obj = HasMemberTemplates()
27-
obj.add(i, i)
28-
obj.addTwoTemplates(i, i)
27+
obj.addSameTypeParams(i, i)
28+
obj.addMixedTypeParams(i, i)
2929
obj.addAll(i, i, i)
3030
obj.doNothingConstRef(&i)
3131
}
3232

33-
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates3addIiEET_S1_S1_] @_ZN18HasMemberTemplates3addIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
33+
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates3addSameTypeParamsIiEET_S1_S1_] @_ZN18HasMemberTemplates3addSameTypeParamsIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
3434

35-
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates15addTwoTemplatesIiiEET_S1_T0_] @_ZN18HasMemberTemplates15addTwoTemplatesIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
35+
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates15addMixedTypeParamsIiiEET_S1_T0_] @_ZN18HasMemberTemplates15addMixedTypeParamsIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
3636

3737
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates6addAllIiiEEiiT_T0_] @_ZN18HasMemberTemplates6addAllIiiEEiiT_T0_ : $@convention(c) (Int32, Int32, Int32, @inout HasMemberTemplates) -> Int32
3838

test/Interop/Cxx/templates/member-templates.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ TemplatesTestSuite.test("Set value - IntWrapper") {
1919

2020
TemplatesTestSuite.test("Templated Add") {
2121
var h = HasMemberTemplates()
22-
expectEqual(h.add(2, 1), 3)
23-
expectEqual(h.addTwoTemplates(2, 1), 3)
22+
expectEqual(h.addSameTypeParams(2, 1), 3)
23+
expectEqual(h.addMixedTypeParams(2, 1), 3)
2424
}
2525

2626
runAllTests()

0 commit comments

Comments
 (0)