From 998979e6dc20eb1b72f6f9a1a818ae28d07d8721 Mon Sep 17 00:00:00 2001
From: Mark Mitchell <mark@codesourcery.com>
Date: Fri, 30 Nov 2001 03:14:56 +0000
Subject: [PATCH] re PR c++/3048 (Lookup problem (gcc 2.95 regression))

2001-11-29  Mark Mitchell  <mark@codesourcery.com>

	PR c++/3048
	* cp-tree.h (ovl_member): Remove.
	* decl2.c (merge_functions): Handle extern "C" functions
	specially.
	* tree.c (ovl_member): Remove.

From-SVN: r47474
---
 gcc/cp/ChangeLog                              |  8 +++++++
 gcc/cp/cp-tree.h                              |  1 -
 gcc/cp/decl2.c                                | 23 ++++++++++++++++---
 gcc/cp/tree.c                                 | 17 --------------
 .../g++.old-deja/g++.other/externC5.C         | 19 +++++++++++++++
 5 files changed, 47 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.old-deja/g++.other/externC5.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0177bc9f4170..be2515372f89 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2001-11-29  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/3048
+	* cp-tree.h (ovl_member): Remove.
+	* decl2.c (merge_functions): Handle extern "C" functions 
+	specially.
+	* tree.c (ovl_member): Remove.
+
 2001-11-29  Mark Mitchell  <mark@codesourcery.com>
 
 	PR c++/4842
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b7cfa7060185..4b6dd33ff79f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4194,7 +4194,6 @@ extern int is_overloaded_fn			PARAMS ((tree));
 extern tree get_first_fn			PARAMS ((tree));
 extern int bound_pmf_p				PARAMS ((tree));
 extern tree ovl_cons                            PARAMS ((tree, tree));
-extern int ovl_member                           PARAMS ((tree, tree));
 extern tree build_overload                      PARAMS ((tree, tree));
 extern tree function_arg_chain			PARAMS ((tree));
 extern int promotes_to_aggr_type		PARAMS ((tree, enum tree_code));
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index c316da034fa0..737d2959c215 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4146,9 +4146,26 @@ merge_functions (s1, s2)
 {
   for (; s2; s2 = OVL_NEXT (s2))
     {
-      tree fn = OVL_CURRENT (s2);
-      if (! ovl_member (fn, s1))
-	s1 = build_overload (fn, s1);
+      tree fn2 = OVL_CURRENT (s2);
+      tree fns1;
+
+      for (fns1 = s1; fns1; fns1 = OVL_NEXT (fns1))
+	{
+	  tree fn1 = OVL_CURRENT (fns1);
+
+	  /* If the function from S2 is already in S1, there is no
+	     need to add it again.  For `extern "C"' functions, we
+	     might have two FUNCTION_DECLs for the same function, in
+	     different namespaces; again, we only need one of them.  */
+	  if (fn1 == fn2 
+	      || (DECL_EXTERN_C_P (fn1) && DECL_EXTERN_C_P (fn2)
+		  && DECL_NAME (fn1) == DECL_NAME (fn2)))
+	    break;
+	}
+      
+      /* If we exhausted all of the functions in S1, FN2 is new.  */
+      if (!fns1)
+	s1 = build_overload (fn2, s1);
     }
   return s1;
 }
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 99d2eab4fd9a..600c6e3746d3 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -981,23 +981,6 @@ build_overload (decl, chain)
   return ovl_cons (decl, chain);
 }
 
-/* True if fn is in ovl. */
-
-int
-ovl_member (fn, ovl)
-     tree fn;
-     tree ovl;
-{
-  if (ovl == NULL_TREE)
-    return 0;
-  if (TREE_CODE (ovl) != OVERLOAD)
-    return ovl == fn;
-  for (; ovl; ovl = OVL_CHAIN (ovl))
-    if (OVL_FUNCTION (ovl) == fn)
-      return 1;
-  return 0;
-}
-
 int
 is_aggr_type_2 (t1, t2)
      tree t1, t2;
diff --git a/gcc/testsuite/g++.old-deja/g++.other/externC5.C b/gcc/testsuite/g++.old-deja/g++.other/externC5.C
new file mode 100644
index 000000000000..aadbc5a46fe1
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/externC5.C
@@ -0,0 +1,19 @@
+// Build don't link:
+// Origin: schmid@snake.iap.physik.tu-darmstadt.de
+
+extern "C" int rand (void) throw ();
+
+namespace std
+{ 
+extern "C" int rand(void) throw(); 
+template <class T> void f(T a) {}
+}
+
+using namespace std;
+
+int main()
+{
+  f(rand);
+  f(std::rand);
+  f(::rand);
+}
-- 
GitLab