google / googletest

GoogleTest - Google Testing and Mocking Framework
https://google.github.io/googletest/
BSD 3-Clause "New" or "Revised" License
33.82k stars 10k forks source link

Including header with overloaded std::ostream& operator<<(std::ostream&, typename T) causes build failure on gcc 10.2 #3384

Open jralls opened 3 years ago

jralls commented 3 years ago

Describe the bug

Build fails:

In file included from /home/john/googletest/googletest/include/gtest/gtest.h:58,
                 from /home/john/gnucash-git/libgnucash/engine/test/gtest-gnc-rational.cpp:24:
/usr/include/c++/10.2.0/ostream:773:5: note: candidate: ‘template<class _Ostream, class _Tp> typename std::enable_if<std::__and_<std::__not_<std::is_lvalue_reference<_Tp> >, std::__is_convertible_to_basic_ostream<_Ostream>, std::__is_insertable<typename std::__is_convertible_to_basic_ostream<_Tp>::__ostream_type, const _Tp&, void> >::value, typename std::__is_convertible_to_basic_ostream<_Tp>::__ostream_type>::type std::operator<<(_Ostream&&, const _Tp&)’
  773 |     operator<<(_Ostream&& __os, const _Tp& __x)
      |     ^~~~~~~~
/usr/include/c++/10.2.0/ostream:773:5: note:   template argument deduction/substitution failed:
/usr/include/c++/10.2.0/ostream: In substitution of ‘template<class _Ostream, class _Tp> typename std::enable_if<std::__and_<std::__not_<std::is_lvalue_reference<_Tp> >, std::__is_convertible_to_basic_ostream<_Ostream>, std::__is_insertable<typename std::__is_convertible_to_basic_ostream<_Tp>::__ostream_type, const _Tp&, void> >::value, typename std::__is_convertible_to_basic_ostream<_Tp>::__ostream_type>::type std::operator<<(_Ostream&&, const _Tp&) [with _Ostream = std::basic_ostream<char>&; _Tp = std::type_index]’:
/home/john/googletest/googletest/include/gtest/gtest-printers.h:216:33:   required from ‘void testing::internal::PrintWithFallback(const T&, std::ostream*) [with T = std::type_index; std::ostream = std::basic_ostream<char>]’
/home/john/googletest/googletest/include/gtest/gtest-printers.h:446:30:   required from ‘void testing::internal::PrintTo(const T&, std::ostream*) [with T = std::type_index; std::ostream = std::basic_ostream<char>]’
/home/john/googletest/googletest/include/gtest/gtest-printers.h:682:49:   required from here
/usr/include/c++/10.2.0/ostream:773:5: error: no type named ‘type’ in ‘struct std::enable_if<false, std::basic_ostream<char>&>’
In file included from /home/john/googletest/googletest/include/gtest/internal/gtest-internal.h:57,
                 from /home/john/googletest/googletest/include/gtest/gtest.h:62,
                 from /home/john/gnucash-git/libgnucash/engine/test/gtest-gnc-rational.cpp:24:
/home/john/googletest/googletest/include/gtest/gtest-printers.h: In instantiation of ‘void testing::internal::PrintWithFallback(const T&, std::ostream*) [with T = std::type_index; std::ostream = std::basic_ostream<char>]’:
/home/john/googletest/googletest/include/gtest/gtest-printers.h:446:30:   required from ‘void testing::internal::PrintTo(const T&, std::ostream*) [with T = std::type_index; std::ostream = std::basic_ostream<char>]’
/home/john/googletest/googletest/include/gtest/gtest-printers.h:682:49:   required from here
/usr/include/c++/10.2.0/iomanip:79:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_Ch, _Tr>& std::operator<<(std::basic_ostream<_Ch, _Tr>&, std::_Resetiosflags)’
   79 |     operator<<(basic_ostream<_CharT, _Traits>& __os, _Resetiosflags __f)
      |     ^~~~~~~~
/usr/include/c++/10.2.0/iomanip:79:5: note:   template argument deduction/substitution failed:
In file included from /home/john/googletest/googletest/include/gtest/gtest-matchers.h:44,
                 from /home/john/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h:39,
                 from /home/john/googletest/googletest/include/gtest/gtest-death-test.h:41,
                 from /home/john/googletest/googletest/include/gtest/gtest.h:64,
                 from /home/john/gnucash-git/libgnucash/engine/test/gtest-gnc-rational.cpp:24:
/home/john/googletest/googletest/include/gtest/gtest-printers.h:216:33: note:   cannot convert ‘std::declval<const std::type_index&>()’ (type ‘const std::type_index’) to type ‘std::_Resetiosflags’
  215 |             typename = decltype(std::declval<std::ostream&>()
      |                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  216 |                                 << std::declval<const T&>())>
      |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~

Followed by a long list of SFINAE failure messages for every other overload of operator<<.

Steps to reproduce the bug

Get https://raw.githubusercontent.com/Gnucash/gnucash/maint/libgnucash/engine/gnc-int128.hpp Create the following gtest-test.cpp:

#include <gtest/gtest.h>
#include <engine/gnc-int128.hpp>

int main()
{
    GncInt128 f;
    std::cout << f << std::endl;
}

compile with

g++ -I googletest/googletest/include/  gtest-test.cpp

Making any adjustments needed to find the two includes.

Commenting out line 279

std::ostream& operator<< (std::ostream&, const GncInt128&) noexcept;

will allow the compilation to succeed.

Does the bug persist in the most recent commit?

Yes.

What operating system and version are you using?

Arch Linux, fully updated yesterday. The problem was first discovered using Ubuntu 21.04 with their packaged googletest.

The problem does not reproduce on macOS 11.2 with Xcode 12.3's clang.

What compiler and version are you using?

$ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.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.2.0 (GCC) What build system are you using?

N/A

Additional context

I have bisected the problem, it is caused by commit ac3c2a8d0496893787015014a5abd397b766cce2 "overload PrintTo for std::type_info and std::type_index" and reverting it allows compilation to complete normally.

jralls commented 3 years ago

Here's a godbolt demonstrating the problem. Note that I've ifdefed out everything except the constructors and the overloaded operator<<.

N-Dekker commented 3 years ago

Thank you for reporting this issue so extensively, John. I seen now, it appears reproducible, even without using GncInt128, by:

#include <gtest/gtest-printers.h>
#include <iosfwd>

struct Foo {
    template <typename T> Foo(T);
};
void operator<<(std::ostream&, const Foo&);

https://godbolt.org/z/d3MKb1cKd

dinord commented 3 years ago

Thanks for reporting! We'll revert https://github.com/google/googletest/commit/ac3c2a8d0496893787015014a5abd397b766cce2.

N-Dekker commented 3 years ago

@dinord Would it still make sense to you to look what goes on here? Is it a compiler bug? Could there be a workaround?

Commit ac3c2a8d0496893787015014a5abd397b766cce2 (pull request #3184) simply just adds two PrintTo overloads. Wasn't the whole idea of PrintTo that it could be customized for specific types by adding overloads?

dinord commented 3 years ago

@N-Dekker Sure, but I'd prefer to revert first in order to unblock users building from head.

jralls commented 3 years ago

I tried the Intel and Microsoft compilers on godbolt and they both compiled the code without error; I already noted that clang does too. That surely suggests that there's at least a difference with gcc so it's worth trying to get the gcc devs to look at it.

dev0x13 commented 1 year ago

Pending PR fixing this (for visibility): https://github.com/google/googletest/pull/3993