Bug 3332

Summary: friend function declaration in a class in a namespace causes error
Product: gcc Reporter: aroach
Component: c++Assignee: Kriang Lerdsuwanakij <lerdsuwa>
Status: RESOLVED FIXED    
Severity: normal CC: gcc-bugs, giovannibajo, lerdsuwa
Priority: P3 Keywords: patch, rejects-valid
Version: 3.0   
Target Milestone: 4.0.0   
Host: i686-pc-linux-gnu Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu Known to work:
Known to fail: Last reconfirmed: 2004-05-25 14:03:57
Bug Depends on:    
Bug Blocks: 12944    

Description aroach 2001-06-21 08:46:01 UTC
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'
Comment 1 aroach 2001-06-21 08:46:01 UTC
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
Comment 2 Nathan Sidwell 2002-10-22 02:59:51 UTC
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 '::'.
Comment 3 Neil Booth 2003-01-02 11:33:51 UTC
State-Changed-From-To: analyzed->suspended
State-Changed-Why: FWIW Comeau rejects this testcase
Comment 4 Wolfgang Bangerth 2003-05-08 21:54:36 UTC
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.
Comment 5 Giovanni Bajo 2003-05-09 00:59:44 UTC
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
Comment 6 Andrew Pinski 2003-08-24 18:01:17 UTC
Seems like there should be a DR for this one since it looks like everyone is reading the 
standard wrong, right?
Comment 7 Kriang Lerdsuwanakij 2004-11-11 12:37:14 UTC
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.
Comment 8 Kriang Lerdsuwanakij 2004-11-18 17:04:45 UTC
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
Comment 9 GCC Commits 2004-11-25 17:05:53 UTC
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

Comment 10 Kriang Lerdsuwanakij 2004-11-25 17:06:27 UTC
Fixed in the mainline by revised patch:
  http://gcc.gnu.org/ml/gcc-patches/2004-11/msg02149.html