http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57388
Bug ID: 57388 Summary: [C++11] ICE when function types with ref-qualifiers meet other function types Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: daniel.kruegler at googlemail dot com While attempting to upgrade std::function for functions with ref-qualifiers I found that the following code gives an ICE for gcc 4.9.0 20130519 (experimental). The compiler flags are: -std=c++11 -Wall -pedantic //------------------------------------------------------ template<class> struct A { static constexpr bool value = false; }; template<class Res, class... Args> struct A<Res(Args...)> { static constexpr bool value = true; }; template<class Res, class... Args> struct A<Res(Args...) const &> { static constexpr bool value = true; }; template<class Res, class... Args> struct A<Res(Args...) const &&> { static constexpr bool value = true; }; static_assert(A<void()>::value, "Ouch"); static_assert(A<void() const &>::value, ""); // #1 static_assert(A<void() const &&>::value, ""); // #2 //------------------------------------------------------ The error being (at line #1 or if this is commented on line #2): "main.cpp|25|internal compiler error: canonical types differ for identical types void() const && and void() const &&" The conditions seem to depend on type ordering. The ICE doesn't occur, when the last three lines are inverted to static_assert(A<void() const &>::value, ""); static_assert(A<void() const &&>::value, ""); static_assert(A<void()>::value, "Ouch"); or if typedefs are introduces for functions with ref-qualifiers up-front such as in the following replacement of the last three lines: typedef void FClref() const &; static_assert(A<void()>::value, "Ouch"); static_assert(A<void() const &>::value, ""); static_assert(A<void() const &&>::value, ""); Interestingly the following variant typedef void FClref() const &&; static_assert(A<void()>::value, "Ouch"); static_assert(A<void() const &>::value, ""); // #1 static_assert(A<void() const &&>::value, ""); still ICEs for #1 (but the previous one didn't ICE on the last line)