Hi again,
... thus Take 2: the extended comparison per DR 565 must be used in
push_overloaded_decl_1 too, in order to handle correctly the case of an
using decl *followed* by a decl. I added a testcase too.
Again booted and tested x86_64-linux.
Thanks,
Paolo.
//////////////////////
/cp
2013-09-01 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/21682, implement DR 565
* name-lookup.c (compparms_for_decl_and_using_decl): New.
(push_overloaded_decl_1, do_nonmember_using_decl): Use it.
/testsuite
2013-09-01 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/21682, implement DR 565
* g++.dg/template/using24.C: New.
* g++.dg/template/using25.C: Likewise.
* g++.dg/template/using26.C: Likewise.
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c (revision 202141)
+++ cp/name-lookup.c (working copy)
@@ -2267,7 +2267,28 @@ pushdecl_with_scope (tree x, cp_binding_level *lev
return ret;
}
+/* Helper function for push_overloaded_decl_1 and do_nonmember_using_decl.
+ Compares the parameter-type-lists of DECL1 and DECL2 and returns false
+ if they are different. If the DECLs are template functions, the return
+ types and the template parameter lists are compared too (DR 565). */
+static bool
+compparms_for_decl_and_using_decl (tree decl1, tree decl2)
+{
+ if (!compparms (TYPE_ARG_TYPES (TREE_TYPE (decl1)),
+ TYPE_ARG_TYPES (TREE_TYPE (decl2))))
+ return false;
+
+ if (! DECL_FUNCTION_TEMPLATE_P (decl1)
+ || ! DECL_FUNCTION_TEMPLATE_P (decl2))
+ return true;
+
+ return (comp_template_parms (DECL_TEMPLATE_PARMS (decl1),
+ DECL_TEMPLATE_PARMS (decl2))
+ && same_type_p (TREE_TYPE (TREE_TYPE (decl1)),
+ TREE_TYPE (TREE_TYPE (decl2))));
+}
+
/* DECL is a FUNCTION_DECL for a non-member function, which may have
other definitions already in place. We get around this by making
the value of the identifier point to a list of all the things that
@@ -2324,8 +2345,7 @@ push_overloaded_decl_1 (tree decl, int flags, bool
if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp)
&& !(flags & PUSH_USING)
- && compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
- TYPE_ARG_TYPES (TREE_TYPE (decl)))
+ && compparms_for_decl_and_using_decl (fn, decl)
&& ! decls_match (fn, decl))
diagnose_name_conflict (decl, fn);
@@ -2561,8 +2581,7 @@ do_nonmember_using_decl (tree scope, tree name, tr
break;
else if (TREE_CODE (tmp1) == OVERLOAD && OVL_USED (tmp1))
continue; /* this is a using decl */
- else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
- TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
+ else if (compparms_for_decl_and_using_decl (new_fn, old_fn))
{
gcc_assert (!DECL_ANTICIPATED (old_fn)
|| DECL_HIDDEN_FRIEND_P (old_fn));
Index: testsuite/g++.dg/template/using24.C
===================================================================
--- testsuite/g++.dg/template/using24.C (revision 0)
+++ testsuite/g++.dg/template/using24.C (working copy)
@@ -0,0 +1,30 @@
+// PR c++/21682
+
+template <class T>
+struct t
+{
+ typedef typename T::type type;
+};
+template<> class t<int>{};
+
+template <class T> struct t1{ };
+template<> struct t1<int>
+{
+ typedef int type;
+};
+
+namespace name1
+{
+ template <class S> typename t<S>::type begin(S const& s);
+ namespace name2
+ {
+ template <class S> typename t1<S>::type begin(S const& s);
+ }
+ using name2::begin;
+}
+
+/* Test calling the function. */
+int f(int a) { return name1::begin(a); }
+
+struct aa { typedef double type; };
+double g(aa t) { return name1::begin(t); }
Index: testsuite/g++.dg/template/using25.C
===================================================================
--- testsuite/g++.dg/template/using25.C (revision 0)
+++ testsuite/g++.dg/template/using25.C (working copy)
@@ -0,0 +1,17 @@
+// PR c++/21682
+
+namespace one {
+ template<typename T> void fun(T);
+}
+
+using one::fun;
+
+template<typename T> void fun(T); // { dg-error "conflicts" }
+
+template<typename T> void funr(T);
+
+namespace oner {
+ template<typename T> void funr(T);
+}
+
+using oner::funr; // { dg-error "conflicts" }
Index: testsuite/g++.dg/template/using26.C
===================================================================
--- testsuite/g++.dg/template/using26.C (revision 0)
+++ testsuite/g++.dg/template/using26.C (working copy)
@@ -0,0 +1,49 @@
+// PR c++/21682
+
+namespace one {
+ template<typename T> int bar1(T);
+}
+
+using one::bar1;
+
+template<typename T> void bar1(T);
+
+template<typename T> void bar1r(T);
+
+namespace oner {
+ template<typename T> int bar1r(T);
+}
+
+using oner::bar1r;
+
+namespace two {
+ template<typename T, typename U> void bar2(T);
+}
+
+using two::bar2;
+
+template<typename T> void bar2(T);
+
+template<typename T> void bar2r(T);
+
+namespace twor {
+ template<typename T, typename U> void bar2r(T);
+}
+
+using twor::bar2r;
+
+namespace three {
+ template<int i> void bar3();
+}
+
+using three::bar3;
+
+template<typename T> void bar3();
+
+template<typename T> void bar3r();
+
+namespace threer {
+ template<int i> void bar3r();
+}
+
+using threer::bar3r;