This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++, RFA] correctly detect conflicts between function and using decls


A bug report was filed into Red Hat's bugzilla system (URL in the
testcase below) regarding an inconsistency in detecting and reporting
conflicts between function and using declarations.  We'd reject extern
"C" matching declarations should the function declaration appear after
the using declaration, but would accept them in reverse order.

Here's the patch, containing a testcase that covers all possibilities
I could think of.  Ok to install?

Index: gcc/cp/ChangeLog
from  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.

Index: gcc/cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1367
diff -u -p -r1.1367 decl.c
--- gcc/cp/decl.c 21 Feb 2005 23:12:25 -0000 1.1367
+++ gcc/cp/decl.c 22 Feb 2005 22:48:19 -0000
@@ -1920,7 +1920,8 @@ redeclaration_error_message (tree newdec
       /* 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: gcc/cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.109
diff -u -p -r1.109 name-lookup.c
--- gcc/cp/name-lookup.c 12 Feb 2005 15:40:15 -0000 1.109
+++ gcc/cp/name-lookup.c 22 Feb 2005 22:48:22 -0000
@@ -1875,7 +1875,8 @@ push_overloaded_decl (tree decl, int fla
 	      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: gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* g++.dg/overload/using2.C: New.

Index: gcc/testsuite/g++.dg/overload/using2.C
===================================================================
RCS file: gcc/testsuite/g++.dg/overload/using2.C
diff -N gcc/testsuite/g++.dg/overload/using2.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/g++.dg/overload/using2.C 22 Feb 2005 22:48:37 -0000
@@ -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);
+}
-- 
Alexandre Oliva             http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]