template <typename T> class rp { }; template <template <typename> class P> struct b { template <class, template <typename> class FriendP> friend void f(b<FriendP> from); }; template <class, template <typename> class P> void f(b<P> from) { } int main() { b<rp> v; f<int>(v); return 0; } ----- > gcc map.cpp main.cpp: In function 'int main()': main.cpp:17:13: error: call of overloaded 'f(b<rp>&)' is ambiguous f<int>(v); ^ main.cpp:17:13: note: candidates are: main.cpp:12:6: note: void f(b<P>) [with <template-parameter-1-1> = int; P = rp] void f(b<P> from) { ^ main.cpp:8:17: note: void f(b<FriendP>) [with <template-parameter-2-1> = int; FriendP = rp; P = rp] friend void f(b<FriendP> from); ^ ----- I can't see an overload here.
> gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: /build/src/gcc-4.8-20130411/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --enable-gnu-unique-object --enable-linker-build-id --enable-cloog-backend=isl --disable-cloog-version-check --enable-lto --enable-gold --enable-ld=default --enable-plugin --with-plugin-ld=ld.gold --with-linker-hash-style=gnu --disable-install-libiberty --disable-multilib --disable-libssp --disable-werror --enable-checking=release Thread model: posix gcc version 4.8.0 20130411 (prerelease) (GCC)
For gcc 4.9.0 20130421 (experimental) this gives me an ICE: "main.cpp|8|internal compiler error: canonical types differ for identical types b<P> and b<FriendP>|"
ICE confirmed with trunk, which is a regression: ice.c: In instantiation of 'struct b<rp>': ice.c:16:11: required from here ice.c:8:17: internal compiler error: canonical types differ for identical types b<P> and b<FriendP> friend void f(b<FriendP> from); ^ 0x64861b comptypes ../../gcc-4.9/gcc/cp/typeck.c:1395 0x64861b comptypes ../../gcc-4.9/gcc/cp/typeck.c:1369 0x649b33 compparms(tree_node const*, tree_node const*) ../../gcc-4.9/gcc/cp/typeck.c:1501 0x54526b decls_match(tree_node*, tree_node*) ../../gcc-4.9/gcc/cp/decl.c:1026 0x545cc4 duplicate_decls(tree_node*, tree_node*, bool) ../../gcc-4.9/gcc/cp/decl.c:1241 0x6e9801 push_overloaded_decl_1 ../../gcc-4.9/gcc/cp/name-lookup.c:2288 0x6e9801 push_overloaded_decl ../../gcc-4.9/gcc/cp/name-lookup.c:2383 0x6eb1ed pushdecl_maybe_friend_1 ../../gcc-4.9/gcc/cp/name-lookup.c:885 0x6eb1ed pushdecl_maybe_friend(tree_node*, bool) ../../gcc-4.9/gcc/cp/name-lookup.c:1219 0x6eca79 pushdecl_with_scope_1 ../../gcc-4.9/gcc/cp/name-lookup.c:2206 0x6ed7ab pushdecl_with_scope(tree_node*, cp_binding_level*, bool) ../../gcc-4.9/gcc/cp/name-lookup.c:2220 0x6ed86d pushdecl_namespace_level(tree_node*, bool) ../../gcc-4.9/gcc/cp/name-lookup.c:3761 0x5b9e69 tsubst_friend_function ../../gcc-4.9/gcc/cp/pt.c:8137 0x5bb493 instantiate_class_template_1 ../../gcc-4.9/gcc/cp/pt.c:8997 0x5bb493 instantiate_class_template(tree_node*) ../../gcc-4.9/gcc/cp/pt.c:9081 0x6439bb complete_type ../../gcc-4.9/gcc/cp/typeck.c:131 0x6439bb complete_type ../../gcc-4.9/gcc/cp/typeck.c:105 0x534f27 start_decl_1(tree_node*, bool) ../../gcc-4.9/gcc/cp/decl.c:4666 0x558990 start_decl(cp_declarator const*, cp_decl_specifier_seq*, int, tree_node*, tree_node*, tree_node**) ../../gcc-4.9/gcc/cp/decl.c:4629 0x618430 cp_parser_init_declarator ../../gcc-4.9/gcc/cp/parser.c:16138 4.6, 4.7 and 4.8 reject it, which is better than an ICE but possibly still wrong.
Fixed for 4.9.