Template argument deduction for function types.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73070 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 812b319..db7e622 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -265,6 +265,37 @@
return false;
}
+ case Type::FunctionProto: {
+ const FunctionProtoType *FunctionProtoArg =
+ dyn_cast<FunctionProtoType>(Arg);
+ if (!FunctionProtoArg)
+ return false;
+
+ const FunctionProtoType *FunctionProtoParam =
+ cast<FunctionProtoType>(Param);
+
+ // Check return types.
+ if (!DeduceTemplateArguments(Context,
+ FunctionProtoParam->getResultType(),
+ FunctionProtoArg->getResultType(),
+ Deduced))
+ return false;
+
+ if (FunctionProtoParam->getNumArgs() != FunctionProtoArg->getNumArgs())
+ return false;
+
+ for (unsigned I = 0, N = FunctionProtoParam->getNumArgs(); I != N; ++I) {
+ // Check argument types.
+ if (!DeduceTemplateArguments(Context,
+ FunctionProtoParam->getArgType(I),
+ FunctionProtoArg->getArgType(I),
+ Deduced))
+ return false;
+ }
+
+ return true;
+ }
+
default:
break;
}
diff --git a/test/SemaTemplate/temp_class_spec.cpp b/test/SemaTemplate/temp_class_spec.cpp
index 8cb46cf..4e4f556 100644
--- a/test/SemaTemplate/temp_class_spec.cpp
+++ b/test/SemaTemplate/temp_class_spec.cpp
@@ -102,3 +102,35 @@
};
int array_size0[get_array_size<int[12]>::value == 12? 1 : -1];
+
+template<typename T>
+struct is_unary_function {
+ static const bool value = false;
+};
+
+template<typename T, typename U>
+struct is_unary_function<T (*)(U)> {
+ static const bool value = true;
+};
+
+int is_unary_function0[is_unary_function<int>::value ? -1 : 1];
+int is_unary_function1[is_unary_function<int (*)()>::value ? -1 : 1];
+int is_unary_function2[is_unary_function<int (*)(int, bool)>::value ? -1 : 1];
+int is_unary_function3[is_unary_function<int (*)(bool)>::value ? 1 : -1];
+int is_unary_function4[is_unary_function<int (*)(int)>::value ? 1 : -1];
+
+template<typename T>
+struct is_unary_function_with_same_return_type_as_argument_type {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_unary_function_with_same_return_type_as_argument_type<T (*)(T)> {
+ static const bool value = true;
+};
+
+int is_unary_function5[is_unary_function_with_same_return_type_as_argument_type<int>::value ? -1 : 1];
+int is_unary_function6[is_unary_function_with_same_return_type_as_argument_type<int (*)()>::value ? -1 : 1];
+int is_unary_function7[is_unary_function_with_same_return_type_as_argument_type<int (*)(int, bool)>::value ? -1 : 1];
+int is_unary_function8[is_unary_function_with_same_return_type_as_argument_type<int (*)(bool)>::value ? -1 : 1];
+int is_unary_function9[is_unary_function_with_same_return_type_as_argument_type<int (*)(int)>::value ? 1 : -1];