Bug 1542254
| Summary: | gcc: failure to resolve overload | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [Fedora] Fedora | Reporter: | Jerry James <loganjerry> | ||||
| Component: | gcc | Assignee: | Jakub Jelinek <jakub> | ||||
| Status: | CLOSED RAWHIDE | QA Contact: | Fedora Extras Quality Assurance <extras-qa> | ||||
| Severity: | unspecified | Docs Contact: | |||||
| Priority: | unspecified | ||||||
| Version: | rawhide | CC: | aoliva, davejohansen, fweimer, jakub, jason, jwakely, law, mpolacek | ||||
| Target Milestone: | --- | ||||||
| Target Release: | --- | ||||||
| Hardware: | x86_64 | ||||||
| OS: | Linux | ||||||
| Whiteboard: | |||||||
| Fixed In Version: | Doc Type: | If docs needed, set a value | |||||
| Doc Text: | Story Points: | --- | |||||
| Clone Of: | Environment: | ||||||
| Last Closed: | 2018-02-12 14:13:16 UTC | Type: | Bug | ||||
| Regression: | --- | Mount Type: | --- | ||||
| Documentation: | --- | CRM: | |||||
| Verified Versions: | Category: | --- | |||||
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
| Cloudforms Team: | --- | Target Upstream Version: | |||||
| Embargoed: | |||||||
| Attachments: |
|
||||||
This changed with http://gcc.gnu.org/r256866 . 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.
CCing Jason. If the new G++ behaviour is correct then we need to fix libstdc++: https://gcc.gnu.org/ml/gcc-help/2018-02/msg00065.html 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); } Bah still not right, I tested the wrong file, please ignore that one too! The upstream bug now has a minimal reproducer. This has now been fixed upstream, so should get fixed next time GCC is updated in rawhide. Fixed in gcc-8.0.1-0.13.fc28 |
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: