This patch introduces some black magic to detect const and volatile qualified function types such as void () const.
The patch works in the following way:
We first rule out any type that satisfies on of the following. These restrictions are important so that the test below works properly.
- is_class<_Tp>::value
- is_union<_Tp>::value
- is_void<_Tp>::value
- is_reference<_Tp>::value
- __is_nullptr_t<_Tp>::value
If none of the above is true we perform overload resolution on __source<_Tp>(0) to determine the return type.
- If _Tp& is well-formed we select _Tp& __source(int). _Tp& is only ill formed for cv void types and cv/ref qualified function types.
- Otherwise we select __dummy_type __source(...). Since we know _Tp cannot be void then it must be a function type.
let R be the returned from __source<_Tp>(0).
We perform overload resolution on __test<_Tp>(R).
- If R is __dummy_type we call true_type __test(__dummy_type).
- if R is _Tp& and _Tp& decays to _Tp* we call true_type __test(_Tp*). Only references to function types decay to a pointer of the same type.
- In all other cases we call false_type __test(...).
__source<_Tp>(0) will try and form _Tp& in the return type. if _Tp& is not well formed the return type of __source<_Tp>(0) will be dummy type. _Tp& is only ill-formed for cv/ref qualified function types (and void which is dealt with elsewhere).
This fixes PR20084 - http://llvm.org/bugs/show_bug.cgi?id=20084
Makes sense to me ;-) Though I'd use __source(...) as a more "canonical" way of writing a less-preferred overload, as we do in the declaration of __test.
We'll use the __dummy_type path for both cv-/ref-qualified function types and for void, but it looks like we're handling the void case in __libcpp_is_function, so that's OK.