[NFC] Cleanup function templates implementation. Address post-commmit review comments from #33053.

Addresses the post-commit review comments from #33053. Just re-naming,
commenting, and some other small cleanups, nothing functionally
different.
This commit is contained in:
zoecarver
2021-01-13 12:46:29 -08:00
parent a6b85522f5
commit c4da4975ed
16 changed files with 105 additions and 89 deletions

View File

@@ -629,8 +629,15 @@ public:
ArrayRef<SILParameterInfo> params, Optional<SILResultInfo> result,
SILFunctionType::Representation trueRep);
/// Instantiates "Impl.Converter" if needed, then calls
/// ClangTypeConverter::getClangTemplateArguments.
/// Instantiates "Impl.Converter" if needed, then translate Swift generic
/// substitutions to equivalent C++ types using \p templateParams and \p
/// genericArgs. The converted Clang types are placed into \p templateArgs.
///
/// \p templateArgs must be empty. \p templateParams and \p genericArgs must
/// be equal in size.
///
/// \returns nullptr if successful. If an error occors, returns a list of
/// types that couldn't be converted.
std::unique_ptr<TemplateInstantiationError> getClangTemplateArguments(
const clang::TemplateParameterList *templateParams,
ArrayRef<Type> genericArgs,

View File

@@ -228,7 +228,7 @@ public:
SubstitutionMap subst) = 0;
};
/// Used to describe a template instantiation error.
/// Describes a C++ template instantiation error.
struct TemplateInstantiationError {
/// Generic types that could not be converted to QualTypes using the
/// ClangTypeConverter.

View File

@@ -1692,7 +1692,7 @@ ERROR(where_nongeneric_toplevel,none,
"declaration", ())
ERROR(unable_to_convert_generic_swift_types,none,
"could not generate C++ types from the generic Swift types provided. "
"The following Swift type(s) provided to '%0' were unable to be "
"The following Swift type(s) provided to '%0' could not be "
"converted: %1.",
(StringRef, StringRef))

View File

@@ -860,12 +860,15 @@ ClangTypeConverter::getClangTemplateArguments(
const clang::TemplateParameterList *templateParams,
ArrayRef<Type> genericArgs,
SmallVectorImpl<clang::TemplateArgument> &templateArgs) {
assert(templateArgs.size() == 0);
assert(genericArgs.size() == templateParams->size());
// Keep track of the types we failed to convert so we can return a useful
// error.
SmallVector<Type, 2> failedTypes;
for (clang::NamedDecl *param : *templateParams) {
// Note: all template parameters must be template type parameters. This is
// verified when we import the clang decl.
// verified when we import the Clang decl.
auto templateParam = cast<clang::TemplateTypeParmDecl>(param);
auto replacement = genericArgs[templateParam->getIndex()];
auto qualType = convert(replacement);
@@ -878,6 +881,9 @@ ClangTypeConverter::getClangTemplateArguments(
}
if (failedTypes.empty())
return nullptr;
// Clear "templateArgs" to prevent the clients from accidently reading a
// partially converted set of template arguments.
templateArgs.clear();
auto errorInfo = std::make_unique<TemplateInstantiationError>();
llvm::for_each(failedTypes, [&errorInfo](auto type) {
errorInfo->failedTypes.push_back(type);

View File

@@ -84,10 +84,13 @@ public:
/// Swift declaration.
Decl *getSwiftDeclForExportedClangDecl(const clang::Decl *decl) const;
/// Translate Swift generic arguments to template arguments.
/// Translate Swift generic arguments to Clang C++ template arguments.
///
/// \returns nullptr if successful. If an error occors, returns a unique_ptr
/// to a `TemplateInstantiationError` with a list of the failed types.
/// \p templateArgs must be empty. \p templateParams and \p genericArgs must
/// be equal in size.
///
/// \returns nullptr if successful. If an error occors, returns a list of
/// types that couldn't be converted.
std::unique_ptr<TemplateInstantiationError> getClangTemplateArguments(
const clang::TemplateParameterList *templateParams,
ArrayRef<Type> genericArgs,

View File

@@ -1,28 +1,28 @@
#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_FUNCTION_TEMPLATES_H
#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_FUNCTION_TEMPLATES_H
template <class T> T add(T a, T b) { return a + b; }
template <class T> T addSameTypeParams(T a, T b) { return a + b; }
template <class A, class B> A addTwoTemplates(A a, B b) { return a + b; }
template <class A, class B> A addMixedTypeParams(A a, B b) { return a + b; }
template <class T> T passThrough(T value) { return value; }
template <class T> const T passThroughConst(const T value) { return value; }
void takesString(const char *) {}
template <class T> void expectsString(T str) { takesString(str); }
template <class T> void expectsConstCharPtr(T str) { takesString(str); }
template <long x> void integerTemplate() {}
template <long x = 0> void defaultIntegerTemplate() {}
template <long x> void hasNonTypeTemplateParameter() {}
template <long x = 0> void hasDefaultedNonTypeTemplateParameter() {}
// We cannot yet use this in swift but, make sure we don't crash when parsing
// We cannot yet use this in Swift but, make sure we don't crash when parsing
// it.
template <class R, class T, class U> R returns_template(T a, U b) {
template <class R, class T, class U> R templateParameterReturnType(T a, U b) {
return a + b;
}
// Same here:
template <class T> void cannot_infer_template() {}
template <class T> void cannotInferTemplate() {}
struct HasVariadicMemeber {
void test1(...) {}

View File

@@ -1,7 +1,7 @@
struct HasMemberTemplates {
template <class T> T add(T a, T b) { return a + b; }
template <class T> T addSameTypeParams(T a, T b) { return a + b; }
template <class T, class U> T addTwoTemplates(T a, U b) { return a + b; }
template <class T, class U> T addMixedTypeParams(T a, U b) { return a + b; }
template <class T, class U> int addAll(int a, T b, U c) { return a + b + c; }

View File

@@ -1,39 +0,0 @@
// RUN: not %target-swift-emit-sil %s -I %S/Inputs -enable-cxx-interop 2>&1 | %FileCheck %s
// README: If you just added support for protocol composition to the
// ClangTypeConverter, please update this test to use a different type that we
// don't support so the error messages here are still tested.
import FunctionTemplates
// Use protocol composition to create a type that we cannot (yet) turn into a clang::QualType.
protocol A { }
protocol B { }
protocol C { }
// CHECK: error: could not generate C++ types from the generic Swift types provided. The following Swift type(s) provided to 'passThrough' were unable to be converted: A & B.
public func caller1(x: A & B) -> A & B {
return passThrough(x)
}
// CHECK: error: could not generate C++ types from the generic Swift types provided. The following Swift type(s) provided to 'addTwoTemplates' were unable to be converted: A & B, A & C.
public func caller2(x: A & B, y: A & C) -> A & B {
return addTwoTemplates(x, y)
}
// Make sure we emit an error and don't crash when failing to instantiate a function.
// CHECK: error: no matching function for call to 'takesString'
// CHECK: note: in instantiation of function template specialization 'expectsString<int>' requested here
// CHECK: note: candidate function not viable: no known conversion from 'int' to 'const char *' for 1st argument
public func callExpectsString() {
expectsString(0 as Int32)
}
// Make sure we don't import non-type template parameters.
// CHECK: error: cannot find 'integerTemplate' in scope
// CHECK: error: cannot find 'defaultIntegerTemplate' in scope
public func callIntegerTemplates() {
integerTemplate()
defaultIntegerTemplate()
}

View File

@@ -20,20 +20,20 @@ public func testPassThrough(x: Int32) -> Int32 {
return passThrough(x)
}
// CHECK-LABEL: define {{.*}}i32 @"$s4main19testAddTwoTemplates1xs5Int32VAE_tF"(i32 %0)
// CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z15addTwoTemplatesIiiET_S0_T0_|"\?\?\$addTwoTemplates@HH@@YAHHH@Z"}}(i32 %0, i32 %0)
// CHECK-LABEL: define {{.*}}i32 @"$s4main22testAddMixedTypeParams1xs5Int32VAE_tF"(i32 %0)
// CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z18addMixedTypeParamsIiiET_S0_T0_|"\?\?\$addMixedTypeParams@HH@@YAHHH@Z"}}(i32 %0, i32 %0)
// CHECK: ret i32 [[OUT_VAL]]
// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z15addTwoTemplatesIiiET_S0_T0_|"\?\?\$addTwoTemplates@HH@@YAHHH@Z"}}(i32 %a, i32 %b)
public func testAddTwoTemplates(x: Int32) -> Int32 {
return addTwoTemplates(x, x)
// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z18addMixedTypeParamsIiiET_S0_T0_|"\?\?\$addMixedTypeParams@HH@@YAHHH@Z"}}(i32 %a, i32 %b)
public func testAddMixedTypeParams(x: Int32) -> Int32 {
return addMixedTypeParams(x, x)
}
// CHECK-LABEL: define {{.*}}i32 @"$s4main7testAdd1xs5Int32VAE_tF"(i32 %0)
// CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z3addIiET_S0_S0_|"\?\?\$add@H@@YAHHH@Z"}}(i32 %0, i32 %0)
// CHECK-LABEL: define {{.*}}i32 @"$s4main21testAddSameTypeParams1xs5Int32VAE_tF"(i32 %0)
// CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z17addSameTypeParamsIiET_S0_S0_|"\?\?\$addSameTypeParams@H@@YAHHH@Z"}}(i32 %0, i32 %0)
// CHECK: ret i32 [[OUT_VAL]]
// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z3addIiET_S0_S0_|"\?\?\$add@H@@YAHHH@Z"}}(i32 %a, i32 %b)
public func testAdd(x: Int32) -> Int32 {
return add(x, x)
// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z17addSameTypeParamsIiET_S0_S0_|"\?\?\$addSameTypeParams@H@@YAHHH@Z"}}(i32 %a, i32 %b)
public func testAddSameTypeParams(x: Int32) -> Int32 {
return addSameTypeParams(x, x)
}

View File

@@ -1,11 +1,11 @@
// RUN: %target-swift-ide-test -print-module -module-to-print=FunctionTemplates -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s
// CHECK: func add<T>(_ a: T, _ b: T) -> T
// CHECK: func addTwoTemplates<A, B>(_ a: A, _ b: B) -> A
// CHECK: func addSameTypeParams<T>(_ a: T, _ b: T) -> T
// CHECK: func addMixedTypeParams<A, B>(_ a: A, _ b: B) -> A
// CHECK: func passThrough<T>(_ value: T) -> T
// CHECK: func passThroughConst<T>(_ value: T) -> T
// CHECK: func returns_template<R, T, U>(_ a: T, _ b: U) -> R
// CHECK: func cannot_infer_template<T>()
// CHECK: func templateParameterReturnType<R, T, U>(_ a: T, _ b: U) -> R
// CHECK: func cannotInferTemplate<T>()
// CHECK: struct HasVariadicMemeber {
// CHECK: @available(*, unavailable, message: "Variadic function is unavailable")

View File

@@ -13,12 +13,12 @@ import FunctionTemplates
// CHECK: [[PASS_THROUGH_FN:%.*]] = function_ref @{{_Z11passThroughIiET_S0_|\?\?\$passThrough@H@@YAHH@Z}} : $@convention(c) (Int32) -> Int32
// CHECK: [[B:%.*]] = apply [[PASS_THROUGH_FN]](%0) : $@convention(c) (Int32) -> Int32
// CHECK: [[ADD_TWO_FN:%.*]] = function_ref @{{_Z15addTwoTemplatesIiiET_S0_T0_|\?\?\$addTwoTemplates@HH@@YAHHH@Z}} : $@convention(c) (Int32, Int32) -> Int32
// CHECK: [[ADD_TWO_FN:%.*]] = function_ref @{{_Z18addMixedTypeParamsIiiET_S0_T0_|\?\?\$addMixedTypeParams@HH@@YAHHH@Z}} : $@convention(c) (Int32, Int32) -> Int32
// CHECK: [[C:%.*]] = apply [[ADD_TWO_FN]]([[A]], [[B]]) : $@convention(c) (Int32, Int32) -> Int32
// CHECK: [[C_32_ADDR:%.*]] = alloc_stack $Int32
// CHECK: [[C_32:%.*]] = load [[C_32_ADDR]] : $*Int32
// CHECK: [[ADD_FN:%.*]] = function_ref @{{_Z3addIiET_S0_S0_|\?\?\$add@H@@YAHHH@Z}} : $@convention(c) (Int32, Int32) -> Int32
// CHECK: [[ADD_FN:%.*]] = function_ref @{{_Z17addSameTypeParamsIiET_S0_S0_|\?\?\$addSameTypeParams@H@@YAHHH@Z}} : $@convention(c) (Int32, Int32) -> Int32
// CHECK: [[OUT:%.*]] = apply [[ADD_FN]]([[B]], [[C_32]]) : $@convention(c) (Int32, Int32) -> Int32
// CHECK: return [[OUT]] : $Int32
@@ -26,6 +26,6 @@ import FunctionTemplates
public func test(x: Int32) -> Int32 {
let a = passThroughConst(Int32(0))
let b = passThrough(x)
let c = addTwoTemplates(a, b)
return add(b, Int32(c))
let c = addMixedTypeParams(a, b)
return addSameTypeParams(b, Int32(c))
}

View File

@@ -0,0 +1,39 @@
// RUN: not %target-typecheck-verify-swift %s -I %S/Inputs -enable-cxx-interop 2>&1 | %FileCheck %s
// README: If you just added support for protocol composition to the
// ClangTypeConverter, please update this test to use a different type that we
// don't support so the error messages here are still tested.
import FunctionTemplates
// Make sure we don't import non-type template parameters.
// CHECK: error: unexpected error produced: cannot find 'hasNonTypeTemplateParameter' in scope
// CHECK: error: unexpected error produced: cannot find 'hasDefaultedNonTypeTemplateParameter' in scope
public func callIntegerTemplates() {
hasNonTypeTemplateParameter()
hasDefaultedNonTypeTemplateParameter()
}
// Use protocol composition to create a type that we cannot (yet) turn into a clang::QualType.
public protocol A { }
public protocol B { }
public protocol C { }
// 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.
public func caller1(x: A & B) -> A & B {
return passThrough(x)
}
// 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.
public func caller2(x: A & B, y: A & C) -> A & B {
return addMixedTypeParams(x, y)
}
// Make sure we emit an error and don't crash when failing to instantiate a function.
// CHECK: error: diagnostic produced elsewhere: no matching function for call to 'takesString'
// CHECK: note: diagnostic produced elsewhere: in instantiation of function template specialization 'expectsConstCharPtr<int>' requested here
// CHECK: note: diagnostic produced elsewhere: candidate function not viable: no known conversion from 'int' to 'const char *' for 1st argument
public func callexpectsConstCharPtr() {
expectsConstCharPtr(0 as Int32)
}

View File

@@ -12,13 +12,13 @@ FunctionTemplateTestSuite.test("passThrough<T> where T == Int") {
expectEqual(42, result)
}
FunctionTemplateTestSuite.test("add<T> where T == Int") {
let result = add(42, 23)
FunctionTemplateTestSuite.test("addSameTypeParams<T> where T == Int") {
let result = addSameTypeParams(42, 23)
expectEqual(65, result)
}
FunctionTemplateTestSuite.test("add<T, U> where T, U == Int") {
let result = addTwoTemplates(42, 23)
FunctionTemplateTestSuite.test("addSameTypeParams<T, U> where T, U == Int") {
let result = addMixedTypeParams(42, 23)
expectEqual(65, result)
}

View File

@@ -1,8 +1,8 @@
// RUN: %target-swift-ide-test -print-module -module-to-print=MemberTemplates -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s
// CHECK: struct HasMemberTemplates {
// CHECK: mutating func add<T>(_ a: T, _ b: T) -> T
// CHECK: mutating func addTwoTemplates<T, U>(_ a: T, _ b: U) -> T
// CHECK: mutating func addSameTypeParams<T>(_ a: T, _ b: T) -> T
// CHECK: mutating func addMixedTypeParams<T, U>(_ a: T, _ b: U) -> T
// CHECK: mutating func addAll<T, U>(_ a: Int32, _ b: T, _ c: U) -> Int32
// CHECK: mutating func passThrough<T>(_ val: T) -> T
// CHECK: mutating func passThroughConst<T>(_ val: T) -> T

View File

@@ -8,10 +8,10 @@ import MemberTemplates
// CHECK-LABEL: sil hidden @$s4main9basicTestyyF : $@convention(thin) () -> ()
// CHECK: [[ADD:%.*]] = function_ref @_ZN18HasMemberTemplates3addIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
// CHECK: [[ADD:%.*]] = function_ref @_ZN18HasMemberTemplates3addSameTypeParamsIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
// CHECK: apply [[ADD]]({{.*}}) : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
// CHECK: [[ADD_TWO_TEMPLATES:%.*]] = function_ref @_ZN18HasMemberTemplates15addTwoTemplatesIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 // user: %26
// CHECK: [[ADD_TWO_TEMPLATES:%.*]] = function_ref @_ZN18HasMemberTemplates15addMixedTypeParamsIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 // user: %26
// CHECK: apply [[ADD_TWO_TEMPLATES]]({{.*}}) : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
// CHECK: [[ADD_ALL:%.*]] = function_ref @_ZN18HasMemberTemplates6addAllIiiEEiiT_T0_ : $@convention(c) (Int32, Int32, Int32, @inout HasMemberTemplates) -> Int32 // user: %39
@@ -24,15 +24,15 @@ import MemberTemplates
func basicTest() {
var i: Int32 = 0
var obj = HasMemberTemplates()
obj.add(i, i)
obj.addTwoTemplates(i, i)
obj.addSameTypeParams(i, i)
obj.addMixedTypeParams(i, i)
obj.addAll(i, i, i)
obj.doNothingConstRef(&i)
}
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates3addIiEET_S1_S1_] @_ZN18HasMemberTemplates3addIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates3addSameTypeParamsIiEET_S1_S1_] @_ZN18HasMemberTemplates3addSameTypeParamsIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates15addTwoTemplatesIiiEET_S1_T0_] @_ZN18HasMemberTemplates15addTwoTemplatesIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates15addMixedTypeParamsIiiEET_S1_T0_] @_ZN18HasMemberTemplates15addMixedTypeParamsIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32
// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates6addAllIiiEEiiT_T0_] @_ZN18HasMemberTemplates6addAllIiiEEiiT_T0_ : $@convention(c) (Int32, Int32, Int32, @inout HasMemberTemplates) -> Int32

View File

@@ -19,8 +19,8 @@ TemplatesTestSuite.test("Set value - IntWrapper") {
TemplatesTestSuite.test("Templated Add") {
var h = HasMemberTemplates()
expectEqual(h.add(2, 1), 3)
expectEqual(h.addTwoTemplates(2, 1), 3)
expectEqual(h.addSameTypeParams(2, 1), 3)
expectEqual(h.addMixedTypeParams(2, 1), 3)
}
runAllTests()