Bug 1542254 - gcc: failure to resolve overload
Summary: gcc: failure to resolve overload
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: gcc
Version: rawhide
Hardware: x86_64
OS: Linux
unspecified
unspecified
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2018-02-05 22:41 UTC by Jerry James
Modified: 2018-02-12 14:13 UTC (History)
8 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2018-02-12 14:13:16 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)
C++ source file showing failure to resolve overload (735 bytes, text/x-csrc)
2018-02-05 22:41 UTC, Jerry James
no flags Details


Links
System ID Private Priority Status Summary Last Updated
GNU Compiler Collection 84283 0 None None None 2018-02-08 13:58:24 UTC

Description Jerry James 2018-02-05 22:41:35 UTC
Created attachment 1391759 [details]
C++ source file showing failure to resolve overload

Description of problem:
The openfst package is failing to build in Rawhide.  I have distilled the problem down to the attached file.  With GCC 7, compiling that file with "g++ -c overload.cpp" succeeds.  With GCC 8 in Rawhide, this output is produced:

overload.cpp: In static member function 'static void fst::AddOnImpl<FST, T>::Read(std::istream&)':
overload.cpp:30:33: error: call of overloaded 'ReadType(std::istream&, int32_t*)' is ambiguous
     ReadType(strm, &magic_number);
                                 ^
overload.cpp:7:22: note: candidate: 'std::istream& fst::ReadType(std::istream&, T*) [with T = int; typename std::enable_if<std::is_class<_Tp>::value, T>::type* <anonymous> = ((typename std::enable_if<std::is_class<int>::value, int>::type*)nullptr)]'
 inline std::istream &ReadType(std::istream &strm, T *t) {
                      ^~~~~~~~
overload.cpp:13:22: note: candidate: 'std::istream& fst::ReadType(std::istream&, T*) [with T = int; typename std::enable_if<std::is_arithmetic<_Tp>::value, T>::type* <anonymous> = ((typename std::enable_if<std::is_arithmetic<int>::value, int>::type*)nullptr)]'
 inline std::istream &ReadType(std::istream &strm, T *t) {
                      ^~~~~~~~
Simply removing the parent class declaration from AddOnImpl makes the compile succeed with GCC 8.

Version-Release number of selected component (if applicable):
gcc-8.0.1-0.9.fc28.x86_64

How reproducible:
Always

Steps to Reproduce:
1. Download the attached C++ source file
2. Run "g++ -c overload.cpp"

Actual results:
The error shown above.

Expected results:
Successful build.

Additional info:

Comment 1 Jakub Jelinek 2018-02-06 15:11:11 UTC
This changed with http://gcc.gnu.org/r256866 .

Comment 2 Jonathan Wakely 2018-02-06 16:50:47 UTC
Clang accepts it even if we instantiate that function, by adding:


struct X { using Arc = int; };

int main()
{
  fst::AddOnImpl<X, void> a;
  a.Read(std::cin);
}


But all compilers reject this reduced example as ambiguous:

namespace std
{
  struct istream { };

  struct true_type { static constexpr bool value = true; };
  struct false_type { static constexpr bool value = false; };

  template<bool, typename T = void> struct enable_if { using type = T; };
  template<> struct enable_if<false> { };

  template<typename> struct is_class : false_type { };
  template<typename> struct is_arithmetic : false_type { };
  template<> struct is_arithmetic<int> : true_type { };
} // std

template <class T,
          typename std::enable_if<std::is_class<T>::value, T>::type* = nullptr>
inline std::istream&
ReadType(std::istream &strm, T *) {
  return strm;
}

template <class T,
          typename std::enable_if<std::is_arithmetic<T>::value, T>::type* = nullptr>
inline std::istream&
ReadType(std::istream &strm, T *) {
  return strm;
 }

void Read(std::istream &strm) {
  int magic_number = 0;
  ReadType(strm, &magic_number);
}

So I'm not sure what the right behaviour is.

The code can be easily made to compile by using enable_if on the return types instead of as default template arguments:

template <class T>
inline typename std::enable_if<std::is_class<T>::value, std::istream&>::type
ReadType(std::istream &strm, T *) {
  ...
}

This definitely isn't ambiguous, as the other overload gets a substitution failure sooner.

Comment 3 Jakub Jelinek 2018-02-06 16:53:11 UTC
CCing Jason.

Comment 4 Jonathan Wakely 2018-02-08 13:47:26 UTC
If the new G++ behaviour is correct then we need to fix libstdc++:

https://gcc.gnu.org/ml/gcc-help/2018-02/msg00065.html

Comment 5 Jonathan Wakely 2018-02-08 14:16:11 UTC
Oops, comment 2 was a bad reduction, the enable_if<false> specialization was wrong. This is a correct reduction which fails with GCC trunk and passes with other compilers:

struct istream { };

struct true_type { static constexpr bool value = true; };
struct false_type { static constexpr bool value = false; };

template<bool, typename T = void> struct enable_if { using type = T; };
template<typename T> struct enable_if<false, T> { };

template<typename> struct is_class : false_type { };
template<typename> struct is_arithmetic : false_type { };
template<> struct is_arithmetic<int> : true_type { };

template <class T,
          typename enable_if<is_class<T>::value, T>::type* = nullptr>
inline istream&
ReadType(istream &strm, T *) {
  return strm;
}

template <class T,
          typename enable_if<is_arithmetic<T>::value, T>::type* = nullptr>
inline istream&
ReadType(istream &strm, T *) {
  return strm;
 }

void Read(istream &strm) {
  int magic_number = 0;
  ReadType(strm, &magic_number);
}

Comment 6 Jonathan Wakely 2018-02-08 14:17:24 UTC
Bah still not right, I tested the wrong file, please ignore that one too!

Comment 7 Jonathan Wakely 2018-02-08 14:25:07 UTC
The upstream bug now has a minimal reproducer.

Comment 8 Jonathan Wakely 2018-02-09 20:38:01 UTC
This has now been fixed upstream, so should get fixed next time GCC is updated in rawhide.

Comment 9 Jonathan Wakely 2018-02-12 14:13:16 UTC
Fixed in gcc-8.0.1-0.13.fc28


Note You need to log in before you can comment on or make changes to this bug.