Bug 41960 - g++: friend introduce name into namespace, violate standard
Summary: g++: friend introduce name into namespace, violate standard
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.3.4
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-11-06 03:51 UTC by Nan Wang
Modified: 2009-11-06 04:40 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nan Wang 2009-11-06 03:51:09 UTC
below code cannot be compiled:

-----------
#define TYPE	N::C
#define ASSIGN	do {} while(0)
//#define ASSIGN	do { x->i = 0;} while(0)
//#define TYPE	N::B
namespace N {
	class B;
	class C;
}
void func(TYPE * x);
namespace N {
	class B { int i; };
	class C {
		int i;
		friend void func(TYPE * x);
	};
}
void func(TYPE * x) { ASSIGN; }
int main()
{
	TYPE x;
	func(&x);
	return 0;
}
-----------

g++ report:

------------
/test-cpp.cpp: In function 'int main()':
./test-cpp.cpp:22: error: call of overloaded 'func(N::C*)' is ambiguous
./test-cpp.cpp:18: note: candidates are: void func(N::C*)
./test-cpp.cpp:15: note:                 void N::func(N::C*)
------------

change

#define TYPE  N::C

to 

#define TYPE    N::B

then the code can be compiled.

According to [namespace.memdef] and [basic.scope.pdecl]:

---------------
friend declarations refer to functions or classes that are members of the nearest enclosing namespace, but they do not introduce new names into that namespace (7.3.1.2).
---------------

According to standard, ::func(N::C * x) shouldn't become friend of N::C, but there should no ambiguous, because 'friend void func(TYPE * x);' look for N::func(N::C *), and it doesn't exist at all. According to [namespace.memdef], the names introduced by 'friend' is invisible until its real declaration.

It seems that, g++ wrongly introduces a name: N::func(N::C*) into namespace N, and when calling func(N::C*), it follows koenig lookup and finds N::func(N::C*). In the situation of 'friend void N::func(N::B*)', g++ works correctly.
Comment 1 Nan Wang 2009-11-06 03:52:10 UTC
following is my g++ -v:

Using built-in specs.
Target: i686-pc-linux-gnu
Configured with: /var/tmp/portage/sys-devel/gcc-4.3.4/work/gcc-4.3.4/configure --prefix=/usr --bindir=/usr/i686-pc-linux-gnu/gcc-bin/4.3.4 --includedir=/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include --datadir=/usr/share/gcc-data/i686-pc-linux-gnu/4.3.4 --mandir=/usr/share/gcc-data/i686-pc-linux-gnu/4.3.4/man --infodir=/usr/share/gcc-data/i686-pc-linux-gnu/4.3.4/info --with-gxx-include-dir=/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4 --host=i686-pc-linux-gnu --build=i686-pc-linux-gnu --disable-altivec --disable-fixed-point --enable-nls --without-included-gettext --with-system-zlib --disable-checking --disable-werror --enable-secureplt --disable-multilib --enable-libmudflap --disable-libssp --enable-libgomp --disable-libgcj --with-arch=i686 --enable-languages=c,c++,treelang,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.3.4 p1.0, pie-10.1.5'
Thread model: posix
gcc version 4.3.4 (Gentoo 4.3.4 p1.0, pie-10.1.5) 
Comment 2 Andrew Pinski 2009-11-06 03:59:30 UTC
This is correct argument dependent lookup is supposed to find N::func for N::C.  You just cannot call N::func directly.
Comment 3 Nan Wang 2009-11-06 04:09:06 UTC
Then why

#define TYPE  N::B

works?

why argument dependent lookup doesn't take effect? Both B and func are in namespace N.

Comment 4 Andrew Pinski 2009-11-06 04:19:48 UTC
(In reply to comment #3)
> Then why
> 
> #define TYPE  N::B
> 
> works?
> 
> why argument dependent lookup doesn't take effect? Both B and func are in
> namespace N.

Because N::func is only a friend of N::C so it is only found for N::C.
Comment 5 Nan Wang 2009-11-06 04:40:36 UTC
I find a clause in the standard:

[basic.lookup.argdep]:

Any namespace-scope friend functions or friend function templates declared in associated classes are visible within their respective namespaces even if they are not visible during an ordinary lookup.

g++ is right.