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)