[Bug c++/95158] New: Templates + Diamond Inheritance + Final = Pure Virtual Function Call

2020-05-15 Thread sudgylacmoe at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95158

Bug ID: 95158
   Summary: Templates + Diamond Inheritance + Final = Pure Virtual
Function Call
   Product: gcc
   Version: 10.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: sudgylacmoe at gmail dot com
  Target Milestone: ---

With this code:

class Base {
public:
virtual void foo()=0;
};

template 
class MiddleA : virtual public Base {
public:
virtual void foo() override {}
};

class MiddleB : virtual public Base {};

template 
class Derived final : public MiddleA, public MiddleB {
public:
void bar()
{
this->foo();
}
};

int main()
{
auto a = Derived();
a.bar(); // Instantiate the template
}

Compiling it with gcc 10.1 with just "g++ test.cpp" (and many other ways to
compile, such as optimization levels and warnings) causes gcc to try to call
Base::foo(), a pure virtual function:

/usr/bin/ld: /tmp/cce0CW5N.o: in function `Derived::bar()':
test.cpp:(.text._ZN7DerivedIvE3barEv[_ZN7DerivedIvE3barEv]+0x14): undefined
reference to `Base::foo()'
collect2: error: ld returned 1 exit status

Trying a few different versions, with gcc 9.3 and before this code compiles
correctly.  On any other compiler I tried (the most recent versions of clang,
msvc and icc on godbolt) it compiled fine.  Removing the template from either
MiddleA or Derived fixes it, removing the inheriting from MiddleB fixes it, and
removing final from Derived fixes it.  If a definition of Base::foo() is added,
the code compiles and calls it.  A workaround is to call MiddleA::foo()
directly.

Output of g++ -v:

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/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++,d --with-isl
--with-linker-hash-style=gnu --with-system-zlib --enable-__cxa_atexit
--enable-cet=auto --enable-checking=release --enable-clocale=gnu
--enable-default-pie --enable-default-ssp --enable-gnu-indirect-function
--enable-gnu-unique-object --enable-install-libiberty --enable-linker-build-id
--enable-lto --enable-multilib --enable-plugin --enable-shared
--enable-threads=posix --disable-libssp --disable-libstdcxx-pch
--disable-libunwind-exceptions --disable-werror
gdc_include_dir=/usr/include/dlang/gdc
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.1.0 (GCC)

[Bug c++/87366] New: SFINAE trait as template parameter causes incorrect application of trait to other areas

2018-09-19 Thread sudgylacmoe at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87366

Bug ID: 87366
   Summary: SFINAE trait as template parameter causes incorrect
application of trait to other areas
   Product: gcc
   Version: 8.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: sudgylacmoe at gmail dot com
  Target Milestone: ---

Created attachment 44727
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44727=edit
Compiler output when trying to compile the complete code snippet

This code should be accepted (and both clang and msvc accept it according to
godbolt), but gcc does not, on every version that I tested (7, 8, and trunk):

namespace std {
template  struct is_same {static constexpr bool
value = false;};
template  struct is_same {static constexpr bool value =
true;};
template  struct enable_if {};
template  struct enable_if {using type = T;};
template  constexpr bool is_same_v = is_same::value;
template  using enable_if_t = typename
enable_if::type;
}

struct A {};
struct B {};

template  struct wrapper {};

template >> using
ok_t = T;

template  void not_even_called(wrapper&> a);

template  int called(wrapper a);

void test(wrapper& val)
{
called(val);
}

GCC fails to compile with the following error message:

test.cpp: In function ‘void test(wrapper&)’:
test.cpp:23:15: error: no matching function for call to ‘called(wrapper&)’
 called(val);
   ^
test.cpp:19:27: note: candidate: ‘template int
called(wrapper&>)’
 template  int called(wrapper a);
   ^~
test.cpp:19:27: note:   template argument deduction/substitution failed:
test.cpp: In substitution of ‘template int called(wrapper&>)
[with T = B]’:
test.cpp:23:15:   required from here
test.cpp:19:27: error: no type named ‘type’ in ‘struct std::enable_if’

As you can see, the SFINAE trait ok_t from not_even_called got applied to the
parameter in called.  Removing not_even_called makes the code compile, and
swapping the declaration of called and not_even_called makes the code compile
(and then you can even call not_even_called with a wrapper, which
should fail).  Removing the wrapper makes it compile, and moving the enable_if
directly into the wrapper makes it compile as well.  In addition, making ok_t
work for struct B instead of struct A makes it compile.

I'm guessing what is happening is that for some reason gcc thinks that
wrapper> is the same as wrapper and starts applying whatever it saw
to the first occurrence to all future occurrences of the type.

I have attached the compiler output when run with -v trying to compile the code
I posted above.