name-lookup.c (push_overloaded_decl): Don't error if the new decl matches the old...
authorAlexandre Oliva <aoliva@redhat.com>
Wed, 2 Mar 2005 19:55:52 +0000 (19:55 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Wed, 2 Mar 2005 19:55:52 +0000 (19:55 +0000)
gcc/cp/ChangeLog:
* name-lookup.c (push_overloaded_decl): Don't error if the new
decl matches the old one.
* decl.c (redeclaration_error_message): Likewise.
gcc/testsuite/ChangeLog:
* g++.dg/overload/using2.C: New.

From-SVN: r95798

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/name-lookup.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/overload/using2.C [new file with mode: 0644]

index 55ec85461c33e5a6e1cf6a02f4f596b97c7be6c2..0fc67aad13751a11bd2df14990fbb8b2a2a4fe5c 100644 (file)
@@ -1,3 +1,9 @@
+2005-03-02  Alexandre Oliva  <aoliva@redhat.com>
+
+       * name-lookup.c (push_overloaded_decl): Don't error if the new
+       decl matches the old one.
+       * decl.c (redeclaration_error_message): Likewise.
+
 2005-03-01  Per Bothner  <per@bothner.com>
 
        * decl.c (finish_function): Use SET_EXPR_LOCATION instead of
index bfe503f30d3820933482095a10ef67aff83bfd8b..dfc1790a175ad6fe842c62b36b691a5901ffb65d 100644 (file)
@@ -1920,7 +1920,8 @@ redeclaration_error_message (tree newdecl, tree olddecl)
       /* If both functions come from different namespaces, this is not
         a redeclaration - this is a conflict with a used function.  */
       if (DECL_NAMESPACE_SCOPE_P (olddecl)
-         && DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl))
+         && DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl)
+         && ! decls_match (olddecl, newdecl))
        return "%qD conflicts with used function";
 
       /* We'll complain about linkage mismatches in
index 7d944d054518d765b6bda43799ac436e9fbcba3a..accd35210ec556a995178167f8edbf4caf7b1e0f 100644 (file)
@@ -1875,7 +1875,8 @@ push_overloaded_decl (tree decl, int flags)
              if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp)
                  && !(flags & PUSH_USING)
                  && compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
-                               TYPE_ARG_TYPES (TREE_TYPE (decl))))
+                               TYPE_ARG_TYPES (TREE_TYPE (decl)))
+                 && ! decls_match (fn, decl))
                error ("%q#D conflicts with previous using declaration %q#D",
                        decl, fn);
 
index 5351064c549402163d02067cdc00e8898cb019ab..19f3404a4fbb612689ec445518457d6051534f63 100644 (file)
@@ -1,3 +1,7 @@
+2005-03-02  Alexandre Oliva  <aoliva@redhat.com>
+
+       * g++.dg/overload/using2.C: New.
+
 2005-03-02  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/19916
diff --git a/gcc/testsuite/g++.dg/overload/using2.C b/gcc/testsuite/g++.dg/overload/using2.C
new file mode 100644 (file)
index 0000000..2ecb5fa
--- /dev/null
@@ -0,0 +1,87 @@
+// { dg-do compile }
+
+// Copyright 2005 Free Software Foundation
+// by Alexandre Oliva <aoliva@redhat.com>
+// based on https://bugzilla.redhat.com/beta/show_bug.cgi?id=149098
+
+// Per the ISO C++ 90 Standard, using declarations before of after a
+// declaration of the same function name and prototype should be
+// errors (7.3.3/11).  However, DR 101's resolution recommends
+// accepting such duplicates if they denote the same function, which
+// means extern "C" declarations are supposed to match and be
+// accepted.
+
+// This test makes sure we reject or accept regular and using
+// declarations regardless of order as appropriate, and that having
+// built-in declarations or overloads doesn't affet the outcome.
+
+namespace std {
+  extern "C" void exit (int) throw (); // these are built-in (extern "C")
+  extern "C" void *malloc (__SIZE_TYPE__) throw () __attribute__((malloc));
+
+  void abort (void) throw (); // these aren't
+  void _exit (int) throw (); // { dg-error "std::_exit" }
+
+  extern "C" void c1 (void) throw ();
+  void C1 (void) throw (); // { dg-error "std::C1" }
+
+  extern "C" void c2 (void) throw ();
+  void C2 (void) throw ();
+
+  extern "C" void c3 (void) throw ();
+  void C3 (void) throw (); // { dg-error "std::C3" }
+}
+
+namespace other {
+  extern "C" void c3 (void) throw ();
+  void C3 (void) throw (); // { dg-error "other::C3" }
+}
+
+using std::exit;
+using std::_exit;
+using std::c1;
+using std::C1;
+
+  extern "C" void exit (int) throw ();
+  extern "C" void *malloc (__SIZE_TYPE__) throw () __attribute__((malloc));
+
+  void abort (void) throw ();
+  void _exit (int) throw (); // { dg-error "conflicts|void _exit" }
+
+  extern "C" void c1 (void) throw ();
+  void C1 (void) throw (); // { dg-error "conflicts|void C1" }
+
+  extern "C" void c2 (void) throw ();
+  void C2 (void) throw ();
+
+  int C3 (int) throw ();
+
+using std::malloc;
+using std::abort; // { dg-error "already declared" }
+using std::c2;
+using std::C2; // { dg-error "already declared" }
+
+using std::c3; using other::c3;
+using std::C3; using other::C3;
+
+  long C3 (long) throw ();
+
+int main () {
+  malloc (0);
+  exit (0);
+
+  _exit (0); // { dg-error "ambiguous" }
+  abort ();
+
+  c1 ();
+  C1 (); // { dg-error "ambiguous" }
+
+  c2 ();
+  C2 (); // one might expect an ambiguous call error here as well, but
+        // we don't add the using decl if we find it to be in error.
+
+  c3 ();
+  C3 (); // { dg-error "ambiguous" }
+  C3 (0);
+  C3 (0l);
+}