From 713101a65e1ebfc829f030bd68f32a8f91703ac0 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Wed, 2 Mar 2005 19:55:52 +0000 Subject: [PATCH] name-lookup.c (push_overloaded_decl): Don't error if the new decl matches the old one. 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 | 6 ++ gcc/cp/decl.c | 3 +- gcc/cp/name-lookup.c | 3 +- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/g++.dg/overload/using2.C | 87 ++++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/overload/using2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 55ec85461c3..0fc67aad137 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2005-03-02 Alexandre Oliva + + * 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 * decl.c (finish_function): Use SET_EXPR_LOCATION instead of diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index bfe503f30d3..dfc1790a175 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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 diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 7d944d05451..accd35210ec 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5351064c549..19f3404a4fb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2005-03-02 Alexandre Oliva + + * g++.dg/overload/using2.C: New. + 2005-03-02 Mark Mitchell 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 index 00000000000..2ecb5fad6b0 --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/using2.C @@ -0,0 +1,87 @@ +// { dg-do compile } + +// Copyright 2005 Free Software Foundation +// by Alexandre Oliva +// 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); +}