nargs = list_length (target_arg_types);
args = XALLOCAVEC (tree, nargs);
for (arg = target_arg_types, ia = 0;
- arg != NULL_TREE && arg != void_list_node;
+ arg != NULL_TREE;
arg = TREE_CHAIN (arg), ++ia)
args[ia] = TREE_VALUE (arg);
nargs = ia;
{
tree decl_arg_types;
tree fn_arg_types;
- tree insttype;
/* In case of explicit specialization, we need to check if
the number of template headers appearing in the specialization
template argument. */
continue;
- /* Remove, from the set of candidates, all those functions
- whose constraints are not satisfied. */
- if (flag_concepts && !constraints_satisfied_p (fn, targs))
- continue;
-
- // Then, try to form the new function type.
- insttype = tsubst (TREE_TYPE (fn), targs, tf_fndecl_type, NULL_TREE);
- if (insttype == error_mark_node)
- continue;
- fn_arg_types
- = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (insttype));
- if (!compparms (fn_arg_types, decl_arg_types))
- continue;
-
/* Save this template, and the arguments deduced. */
templates = tree_cons (targs, fn, templates);
}
TREE_VALUE (sarg));
goto fail;
}
+ if ((i < nargs || sarg)
+ /* add_candidates uses DEDUCE_EXACT for x.operator foo(), but args
+ doesn't contain the trailing void, and conv fns are always (). */
+ && !DECL_CONV_FN_P (decl))
+ {
+ unsigned nsargs = i + list_length (sarg);
+ unify_arity (explain_p, nargs, nsargs);
+ goto fail;
+ }
}
/* After doing deduction with the inherited constructor, actually return an
args = xargs;
nargs = xnargs;
+ /* Only fn_type_unification cares about terminal void. */
+ if (nargs && args[nargs-1] == void_type_node)
+ --nargs;
+
ia = 0;
while (parms && parms != void_list_node
&& ia < nargs)
nargs = list_length (decl_arg_types);
args = XALLOCAVEC (tree, nargs);
for (arg = decl_arg_types, ix = 0;
- arg != NULL_TREE && arg != void_list_node;
+ arg != NULL_TREE;
arg = TREE_CHAIN (arg), ++ix)
args[ix] = TREE_VALUE (arg);
--- /dev/null
+template <class T>
+void f(T);
+
+template<> void f(int, ...); // { dg-error "match" }
+
+template <class T>
+void g(T, ...);
+
+template<> void g(int); // { dg-error "match" }
--- /dev/null
+// CWG 1001
+
+template<class T> struct A {
+ typedef T arr[3];
+};
+
+template<class T> void f(const typename A<T>::arr) { } // #1
+
+template void f<int>(const A<int>::arr);
+
+template <class T> struct B {
+ void g(T);
+};
+
+template <class T> void B<T>::g(const T) { } // #2
--- /dev/null
+// PR c++/51851
+
+template<class T>
+struct A
+{
+ typedef double Point[2];
+ virtual double calculate(const Point point) const = 0;
+};
+
+template<class T>
+struct B : public A<T>
+{
+ virtual double calculate(const typename A<T>::Point point) const
+ {
+ return point[0];
+ }
+};
+
+int main()
+{
+ B<int> b;
+ return 0;
+}
--- /dev/null
+// CWG 1001/1322
+
+// PR c++/101402
+// PR c++/102033
+// PR c++/102034
+// PR c++/102039
+// PR c++/102044
+
+namespace test2{
+template <class T>
+void f(const T);
+
+template<>
+void f<int[]>(const int*){}
+}
+
+namespace test3{
+template <class T>
+struct A{
+void f(T);
+};
+
+template<class T>
+void A<T>::f(const T){}
+
+template<>
+void A<int[3]>::f(const int*){}
+}
+
+namespace test4 {
+template<class TA>
+struct A{
+ template<class TB>
+ struct B{
+ typedef TB Arr3[3];
+ };
+};
+template<class TA, class TB>
+void f(const typename A<TA>::template B<TB>::Arr3){}
+template <>
+void f<int, char>(const typename A<int>::B<char>::Arr3){}
+}
+
+namespace test5
+{
+struct A{
+ typedef int Arr3[3];
+};
+
+template<class T>
+void f(const typename T::Arr3){}
+
+template<>
+void f<A>(const int[3]){}
+}
+
+namespace test6
+{
+struct A{
+ typedef int Arr3[3];
+};
+template<class T>
+void f(const typename T::Arr3){}
+template<>
+void f<A>(const int*){}
+}
+
+#if __cpp_alias_templates
+namespace test7
+{
+template<class TA>
+struct A{
+ template<class TB>
+ using Type=TB[3];
+};
+template<class TA, class TB>
+void f(const typename A<TA>::template Type<TB>){}
+template <>
+void f<int, char>(const typename A<int>::template Type<char>){}
+}
+namespace test8
+{
+template<class TA>
+struct A{
+ template<class TB>
+ struct B{
+ using TB_Alias=TB;
+ template<class TC=TB_Alias>
+ struct C{
+ typedef TC Arr3[3];
+ };
+ };
+};
+template<class TA, class TB>
+void f(const typename A<TA>::template B<TB>::template C<>::Arr3){}
+template <>
+void f<int, char>(const typename A<int>::template B<char>::template C<>::Arr3){}
+}
+#endif
+
+#if __cpp_decltype
+namespace test0
+{
+template <class T>
+struct A{
+ T arr3[3];
+};
+template <class T>
+void f(const decltype(A<T>::arr3)){}
+template <>
+void f<int>(const int[3]){}
+}
+
+#if __cpp_variable_templates
+namespace test9
+{
+template<unsigned int N, class T>
+void f(const T[N]){}
+
+template<unsigned int N, class T>
+using fPtr=decltype(f<N,T>)*;
+
+template<unsigned int N, class T>
+fPtr<N,T> af[N]={&f<N,T>};
+
+template<unsigned int N, class T>
+void g(const decltype(af<N,T>)){}
+
+template<>
+void g<1,int>(const fPtr<1,int>[1]){}
+}
+#endif
+#endif
+
+#if __cpp_concepts
+template<class T>
+concept IsLambdaAry3=__is_same(T, decltype(+[]{})[3]);
+template<IsLambdaAry3 T>
+void bar(const T){}
+template<>
+void bar<decltype(+[]{})[3]>(const decltype(+[]{})[3]){}
+#endif