[Bug c++/95158] New: Templates + Diamond Inheritance + Final = Pure Virtual Function Call
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
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.