From a81e6834521e5e1a4e0ac2abd16d8e6ae483c7aa Mon Sep 17 00:00:00 2001
From: nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Tue, 24 Dec 2002 22:12:17 +0000
Subject: [PATCH] cp:         PR c++/9053         * decl.c (duplicate_decls):
 Templates may be disambiguated by         return type.

        PR c++/8702
        * decl2.c (check_classfn): Use lookup_fnfield_1. List all
        conversion operators on failure.
testsuite
        * g++.dg/lookup/decl1.C: New test.
        * g++.dg/lookup/decl2.C: New test.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@60482 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/ChangeLog                    |  10 ++
 gcc/cp/decl.c                       |   6 +-
 gcc/cp/decl2.c                      | 143 ++++++++++++++--------------
 gcc/testsuite/ChangeLog             |   9 +-
 gcc/testsuite/g++.dg/lookup/decl1.C |  32 +++++++
 gcc/testsuite/g++.dg/lookup/decl2.C |  27 ++++++
 6 files changed, 155 insertions(+), 72 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/lookup/decl1.C
 create mode 100644 gcc/testsuite/g++.dg/lookup/decl2.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5776e5c470e3..921550ed4b2f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2002-12-24  Nathan Sidwell  <nathan@codesourcery.com>
+
+	PR c++/9053
+	* decl.c (duplicate_decls): Templates may be disambiguated by
+	return type.
+	
+	PR c++/8702
+	* decl2.c (check_classfn): Use lookup_fnfield_1. List all
+	conversion operators on failure.
+
 2002-12-23  Gabriel Dos Reis  <gdr@integrable-solutions.net>
 
 	* call.c (tourney, build_field_call, equal_functions, joust) 
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index eef5335fb5fe..95680dd60fa1 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3212,7 +3212,11 @@ duplicate_decls (newdecl, olddecl)
 		   && compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
 				 TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
 		   && comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
-					   DECL_TEMPLATE_PARMS (olddecl)))
+					   DECL_TEMPLATE_PARMS (olddecl))
+		   /* Template functions can be disambiguated by
+		      return type.  */
+		   && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
+				   TREE_TYPE (TREE_TYPE (olddecl))))
 	    {
 	      error ("new declaration `%#D'", newdecl);
 	      cp_error_at ("ambiguates old declaration `%#D'", olddecl);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index d305ee5813e5..afb8693a6b73 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -676,11 +676,7 @@ tree
 check_classfn (ctype, function)
      tree ctype, function;
 {
-  tree fn_name = DECL_NAME (function);
-  tree fndecl, fndecls;
-  tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
-  tree *methods = 0;
-  tree *end = 0;
+  int ix;
   
   if (DECL_USE_TEMPLATE (function)
       && !(TREE_CODE (function) == TEMPLATE_DECL
@@ -697,81 +693,90 @@ check_classfn (ctype, function)
        reason we should, either.  We let our callers know we didn't
        find the method, but we don't complain.  */
     return NULL_TREE;
-      
-  if (method_vec != 0)
+
+  ix = lookup_fnfields_1 (complete_type (ctype),
+			  DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
+			  DECL_DESTRUCTOR_P (function) ? dtor_identifier :
+			  DECL_NAME (function));
+
+  if (ix >= 0)
     {
-      methods = &TREE_VEC_ELT (method_vec, 0);
-      end = TREE_VEC_END (method_vec);
-
-      /* First suss out ctors and dtors.  */
-      if (*methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
-	  && DECL_CONSTRUCTOR_P (function))
-	goto got_it;
-      if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
-	  && DECL_DESTRUCTOR_P (function))
-	goto got_it;
-
-      while (++methods != end && *methods)
+      tree methods = CLASSTYPE_METHOD_VEC (ctype);
+      tree fndecls, fndecl;
+      bool is_conv_op;
+      const char *format = NULL;
+      
+      for (fndecls = TREE_VEC_ELT (methods, ix);
+	   fndecls; fndecls = OVL_NEXT (fndecls))
+	{
+	  tree p1, p2;
+	  
+	  fndecl = OVL_CURRENT (fndecls);
+	  p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
+	  p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+
+	  /* We cannot simply call decls_match because this doesn't
+	     work for static member functions that are pretending to
+	     be methods, and because the name may have been changed by
+	     asm("new_name").  */ 
+	      
+	   /* Get rid of the this parameter on functions that become
+	      static.  */
+	  if (DECL_STATIC_FUNCTION_P (fndecl)
+	      && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
+	    p1 = TREE_CHAIN (p1);
+	      
+	  if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
+			   TREE_TYPE (TREE_TYPE (fndecl)))
+	      && compparms (p1, p2)
+	      && (DECL_TEMPLATE_SPECIALIZATION (function)
+		  == DECL_TEMPLATE_SPECIALIZATION (fndecl))
+	      && (!DECL_TEMPLATE_SPECIALIZATION (function)
+		  || (DECL_TI_TEMPLATE (function) 
+		      == DECL_TI_TEMPLATE (fndecl))))
+	    return fndecl;
+	}
+      error ("prototype for `%#D' does not match any in class `%T'",
+	     function, ctype);
+      is_conv_op = DECL_CONV_FN_P (fndecl);
+
+      if (is_conv_op)
+	ix = CLASSTYPE_FIRST_CONVERSION_SLOT;
+      fndecls = TREE_VEC_ELT (methods, ix);
+      while (fndecls)
 	{
-	  fndecl = *methods;
-	  if (fn_name == DECL_NAME (OVL_CURRENT (*methods)))
+	  fndecl = OVL_CURRENT (fndecls);
+	  fndecls = OVL_NEXT (fndecls);
+
+	  if (!fndecls && is_conv_op)
 	    {
-	    got_it:
-	      for (fndecls = *methods; fndecls != NULL_TREE;
-		   fndecls = OVL_NEXT (fndecls))
+	      if (TREE_VEC_LENGTH (methods) > ix)
 		{
-		  fndecl = OVL_CURRENT (fndecls);
-
-		  /* We cannot simply call decls_match because this
-		     doesn't work for static member functions that are 
-                     pretending to be methods, and because the name
-		     may have been changed by asm("new_name").  */ 
-		  if (DECL_NAME (function) == DECL_NAME (fndecl))
+		  ix++;
+		  fndecls = TREE_VEC_ELT (methods, ix);
+		  if (!DECL_CONV_FN_P (OVL_CURRENT (fndecls)))
 		    {
-		      tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
-		      tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
-
-		      /* Get rid of the this parameter on functions that become
-			 static.  */
-		      if (DECL_STATIC_FUNCTION_P (fndecl)
-			  && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
-			p1 = TREE_CHAIN (p1);
-
-		      if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
-				       TREE_TYPE (TREE_TYPE (fndecl)))
-			  && compparms (p1, p2)
-			  && (DECL_TEMPLATE_SPECIALIZATION (function)
-			      == DECL_TEMPLATE_SPECIALIZATION (fndecl))
-			  && (!DECL_TEMPLATE_SPECIALIZATION (function)
-			      || (DECL_TI_TEMPLATE (function) 
-				  == DECL_TI_TEMPLATE (fndecl))))
-			return fndecl;
+		      fndecls = NULL_TREE;
+		      is_conv_op = false;
 		    }
 		}
-	      break;		/* loser */
+	      else
+		is_conv_op = false;
 	    }
+	  if (format)
+	    format = "                %#D";
+	  else if (fndecls)
+	    format = "candidates are: %#D";
+	  else
+	    format = "candidate is: %#D";
+	  cp_error_at (format, fndecl);
 	}
     }
-
-  if (methods != end && *methods)
-    {
-      tree fndecl = *methods;
-      error ("prototype for `%#D' does not match any in class `%T'",
-		function, ctype);
-      cp_error_at ("candidate%s: %+#D", OVL_NEXT (fndecl) ? "s are" : " is",
-		   OVL_CURRENT (fndecl));
-      while (fndecl = OVL_NEXT (fndecl), fndecl)
-	cp_error_at ("                %#D", OVL_CURRENT(fndecl));
-    }
+  else if (!COMPLETE_TYPE_P (ctype))
+    cxx_incomplete_type_error (function, ctype);
   else
-    {
-      methods = 0;
-      if (!COMPLETE_TYPE_P (ctype))
-        cxx_incomplete_type_error (function, ctype);
-      else
-        error ("no `%#D' member function declared in class `%T'",
-		  function, ctype);
-    }
+    error ("no `%#D' member function declared in class `%T'",
+	   function, ctype);
 
   /* If we did not find the method in the class, add it to avoid
      spurious errors (unless the CTYPE is not yet defined, in which
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7771c26a1d51..b40420e24c3d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2002-12-24  Nathan Sidwell  <nathan@codesourcery.com>
+
+	* g++.dg/lookup/decl1.C: New test.
+	* g++.dg/lookup/decl2.C: New test.
+
 2002-12-24  Joseph S. Myers  <jsm@polyomino.org.uk>
 
 	* g++.dg/init/new1.C, g++.dg/template/alignof1.C,
@@ -12,9 +17,9 @@
 
 2002-12-23  Mark Mitchell  <mark@codesourcery.com>
 
-	* testsuite/gcc.dg/i386-bitfield3.c: New test.
+	* gcc.dg/i386-bitfield3.c: New test.
 	
-	* testsuite/gcc.dg/i386-bitfield2.c: New test.
+	* gcc.dg/i386-bitfield2.c: New test.
 	
 2002-12-22  Nathan Sidwell  <nathan@codesourcery.com>
 
diff --git a/gcc/testsuite/g++.dg/lookup/decl1.C b/gcc/testsuite/g++.dg/lookup/decl1.C
new file mode 100644
index 000000000000..d9af65604cb2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/decl1.C
@@ -0,0 +1,32 @@
+// { dg-do compile }
+
+// Copyright (C) 2002 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 24 Dec 2002 <nathan@codesourcery.com>
+
+// PR 8702. Failure to match templates.
+
+template <typename X> struct C1{};
+
+template <typename X>
+struct C2 {
+  template<typename Y> operator C1<Y>();
+  template<typename Y> operator C2<Y>();
+};
+
+template<typename X> template<typename Y>
+C2<X>::operator C1<Y>()
+{
+  return C1<Y>();
+}
+
+struct A
+{
+  operator int ();			// { dg-error "operator" "" }
+  operator float ();			// { dg-error "operator" "" }
+  operator float () const;		// { dg-error "operator" "" }
+  template <typename T> operator T * (); // { dg-error "candidates" "" }
+};
+
+A::operator short () { // { dg-error "prototype for" "" }
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/lookup/decl2.C b/gcc/testsuite/g++.dg/lookup/decl2.C
new file mode 100644
index 000000000000..75ce0967a4b4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/decl2.C
@@ -0,0 +1,27 @@
+// { dg-do compile }
+
+// Copyright (C) 2002 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 24 Dec 2002 <nathan@codesourcery.com>
+// Source Martin Buchholz martin@xemacs.org
+
+// PR 9053. Failed to consider templates that are disambiguated by
+// return type.
+
+template <typename T> class bar;
+template <> struct bar<const char*> { typedef void type; };
+template <typename T> class qux;
+template <> struct qux<int> { typedef void type; };
+
+template <typename T>
+typename bar<T>::type foo (T t) { }
+
+template <typename T>
+typename qux<T>::type foo (T t) { }
+
+
+int
+main (int argc, char *argv[])
+{
+  foo ("foo");
+  foo (7);
+}
-- 
GitLab