Bug#1009081: g++-11: friend statement not used for template specialization

2022-04-07 Thread Vincent Danjean

  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

2022-04-06 Thread Vincent Danjean
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