Patchwork [C++] PR 21682 (DR 565) (Take 2)

login
register
mail settings
Submitter Paolo Carlini
Date Sept. 1, 2013, 9:31 p.m.
Message ID <5223B228.1020304@oracle.com>
Download mbox | patch
Permalink /patch/271652/
State New
Headers show

Comments

Paolo Carlini - Sept. 1, 2013, 9:31 p.m.
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.carlini@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.carlini@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.
Jason Merrill - Sept. 2, 2013, 6:09 a.m.
OK.

Jason

Patch

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;