Bug#1009081: g++-11: friend statement not used for template specialization
Hi, More strange: by adding an unused static method, the behavior of the previous templates change. $ cat toto6.cpp #include struct X { template struct check_is_map { static constexpr bool value = false; }; template struct check_is_map { static constexpr bool value = true; }; template struct check_is_map2 { static constexpr bool value = check_is_map::value; }; static void func(); }; template struct check_is_map { static constexpr bool value = false; }; template struct check_is_map { static constexpr bool value = true; }; struct Config { using is_map=void; }; struct ConfigBis { private: template friend struct check_is_map; friend struct X; using is_map=void; }; #ifdef FOO void X::func() { std::cerr << "* Through method" << std::endl; std::cerr << "X::VALUE (public): " << X::check_is_map::value << std::endl; std::cerr << "X::VALUE (private+friend): " << X::check_is_map::value << std::endl; std::cerr << "** By proxy template" << std::endl; std::cerr << "X::Proxy::VALUE (public): " << X::check_is_map2::value << std::endl; std::cerr << "X::Proxy::VALUE (private+friend): " << X::check_is_map2::value << std::endl; } #endif int main() { std::cerr << "* From main" << std::endl; std::cerr << "VALUE (public): " << check_is_map::value << std::endl; std::cerr << "VALUE (private+friend): " << check_is_map::value << std::endl; std::cerr << "X::VALUE (public): " << X::check_is_map::value << std::endl; std::cerr << "X::VALUE (private+friend): " << X::check_is_map::value << std::endl; std::cerr << "** By proxy template" << std::endl; std::cerr << "X::Proxy::VALUE (public): " << X::check_is_map2::value << std::endl; std::cerr << "X::Proxy::VALUE (private+friend): " << X::check_is_map2::value << std::endl; } $ g++ -std=gnu++17 -Wall -Wextra toto6.cpp $ ./a.out * From main VALUE (public): 1 VALUE (private+friend): 0 X::VALUE (public): 1 X::VALUE (private+friend): 0 ** By proxy template X::Proxy::VALUE (public): 1 X::Proxy::VALUE (private+friend): 0 $ g++ -std=gnu++17 -Wall -Wextra toto6.cpp -DFOO $ ./a.out * From main VALUE (public): 1 VALUE (private+friend): 0 X::VALUE (public): 1 X::VALUE (private+friend): 1 ** By proxy template X::Proxy::VALUE (public): 1 X::Proxy::VALUE (private+friend): 1 Regards, Vincent
Bug#1009081: g++-11: friend statement not used for template specialization
Package: g++-11 Version: 11.2.0-19 Severity: normal Contrary to clang++, g++ does not honor "friend" statement when evaluating template specialization Here is a short example: $ cat toto6.cpp #include struct X { template struct check_is_map { static constexpr bool value = false; }; template struct check_is_map { static constexpr bool value = true; }; }; template struct check_is_map { static constexpr bool value = false; }; template struct check_is_map { static constexpr bool value = true; }; struct Config { using is_map=void; }; struct ConfigBis { private: template friend struct check_is_map; // friend of the template friend struct X; // friend of the surrounding class using is_map=void; }; int main() { std::cerr << "VALUE (public): " << check_is_map::value << std::endl; std::cerr << "VALUE (private+friend): " << check_is_map::value << std::endl; std::cerr << "X::VALUE (public): " << X::check_is_map::value << std::endl; std::cerr << "X::VALUE (private+friend): " << X::check_is_map::value << std::endl; } $ clang++ -std=gnu++17 -Wall -Wextra toto6.cpp $ ./a.out VALUE (public): 1 VALUE (private+friend): 1 X::VALUE (public): 1 X::VALUE (private+friend): 1 $ g++ -std=gnu++17 -Wall -Wextra toto6.cpp $ ./a.out VALUE (public): 1 VALUE (private+friend): 0 X::VALUE (public): 1 X::VALUE (private+friend): 0 Regards, Vincent -- System Information: Debian Release: bookworm/sid APT prefers stable-updates APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 'oldstable-updates'), (500, 'unstable'), (500, 'testing'), (500, 'stable'), (500, 'oldstable'), (1, 'experimental') Architecture: amd64 (x86_64) Foreign Architectures: i386, armel, mipsel Kernel: Linux 5.16.0-6-amd64 (SMP w/4 CPU threads; PREEMPT) Kernel taint flags: TAINT_OOT_MODULE Locale: LANG=fr_FR.utf8, LC_CTYPE=fr_FR.utf8 (charmap=UTF-8), LANGUAGE not set Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) Versions of packages g++-11 depends on: ii gcc-1111.2.0-19 ii gcc-11-base 11.2.0-19 ii libc6 2.33-7 ii libgmp10 2:6.2.1+dfsg-3 ii libisl23 0.24-2 ii libmpc3 1.2.1-2 ii libmpfr6 4.1.0-3 ii libstdc++-11-dev 11.2.0-19 ii libzstd1 1.4.10+dfsg-1 ii zlib1g1:1.2.11.dfsg-4 g++-11 recommends no packages. Versions of packages g++-11 suggests: pn g++-11-multilib ii gcc-11-doc 11.2.0-1 -- no debconf information