Implicitly declaring a function through a friend declaration in a class definition where the class and the function are members of the same namespace doesn't compile. Release: 3.0 Environment: System: Linux stoic 2.2.19 #1 Thu Apr 5 15:18:02 EST 2001 i686 unknown Architecture: i686 host: i686-pc-linux-gnu build: i686-pc-linux-gnu target: i686-pc-linux-gnu configured with: ../gcc-3.0/configure --prefix=/usr/local/opt/gcc-3.0 How-To-Repeat: source that produces the bug: // BEGIN: friendBug.cpp namespace N { class A; } class N::A { friend void func(void); }; void N::func(void) { } int main() { return 0; } // END: friendBug.cpp Compile with: gcc friendBug.cpp gcc output: friendBug.cpp:13: `void N::func()' should have been declared inside `N'
Fix: Workaround: // BEGIN: friendFixed.cpp namespace N { class A; void func(void); } class N::A { friend void func(void); }; void N::func(void) { } int main() { return 0; } // END: friendFixed.cpp
State-Changed-From-To: open->analyzed State-Changed-Why: confirmed. I think this is well-formed. [7.3.1.2]/3 seems to be relevant. The question to answer is 'in the defintion of N::A, what is the innermost enclosing namespace?'. Is it '::' - that being the one that is 'open', or is it '::N' - that being the one containing 'A'. It would be bizzare if the answer was '::'.
State-Changed-From-To: analyzed->suspended State-Changed-Why: FWIW Comeau rejects this testcase
Responsible-Changed-From-To: unassigned->nathan Responsible-Changed-Why: gcc3.4, icc, como and cxx all agree that the code is not valid, if put into strict standard mode. That is also my interpretation. Nathan, do you still stand to your reading of the standard? W.
From: "Giovanni Bajo" <giovannibajo@libero.it> To: <aroach@stoic.electriceyeball.com>, <gcc-gnats@gcc.gnu.org>, <gcc-bugs@gcc.gnu.org>, <nathan@gcc.gnu.org>, <gcc-prs@gcc.gnu.org> Cc: Subject: Re: c++/3332: [2003-05-06] friend function declaration in a class in a namespace causes error Date: Fri, 9 May 2003 00:59:44 +0200 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=3332 FWIW, I agree with Nathan. Giovanni Bajo
Seems like there should be a DR for this one since it looks like everyone is reading the standard wrong, right?
Taking this bug. The code void N::func(void) is rejected because the declaration friend void func(void); doesn't declare 'func' inside namespace 'N'. A separate declaration is necessary before the qualified ID form 'N::func' can be used. The following code, compiles under como, confirmed the above idea. namespace N { class A; } class N::A { void x(); friend void func(void); }; namespace N { void func(void); // declare func } void N::func(void) // after declaration // can now defined using qualified name { N::A a; a.x(); // access private function } int main() { return 0; } The bug will be fixed when problematic codes in libjava (it assumes friends are in '::') are corrected.
Patch submitted (both are required): (Friend lookup part 2/n) http://gcc.gnu.org/ml/gcc-patches/2004-10/msg01372.html (Friend lookup part 3/n) http://gcc.gnu.org/ml/gcc-patches/2004-11/msg01495.html
Subject: Bug 3332 CVSROOT: /cvs/gcc Module name: gcc Changes by: lerdsuwa@gcc.gnu.org 2004-11-25 17:05:38 Modified files: gcc/cp : ChangeLog name-lookup.c name-lookup.h parser.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/g++.dg/lookup: friend3.C friend4.C friend5.C Log message: Friend class name lookup 3/n, PR c++/3332 * name-lookup.c (push_inner_scope, pop_inner_scope): New functions. (lookup_type_scope): Don't deal with name from user declaration specially. * name-lookup.h (push_inner_scope, pop_inner_scope): Add declarations. * parser.c (cp_parser_class_specifier): Use push_inner_scope and pop_inner_scope. * g++.dg/lookup/friend3.C: New test. * g++.dg/lookup/friend4.C: Likewise. * g++.dg/lookup/friend5.C: Likewise. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4497&r2=1.4498 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/name-lookup.c.diff?cvsroot=gcc&r1=1.94&r2=1.95 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/name-lookup.h.diff?cvsroot=gcc&r1=1.31&r2=1.32 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/parser.c.diff?cvsroot=gcc&r1=1.282&r2=1.283 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.4647&r2=1.4648 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/lookup/friend3.C.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/lookup/friend4.C.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/lookup/friend5.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
Fixed in the mainline by revised patch: http://gcc.gnu.org/ml/gcc-patches/2004-11/msg02149.html