Re: [PATCH] PR libstdc++/91371 make std::is_function handle other calling conventions
On 16/08/19 16:35 +0100, Jonathan Wakely wrote: The x86 attributes such as ms_abi, stdcall, fastcall etc. alter the function type, which means that functions with one of those attributes do not match any of the partial specializations of std::is_function. Rather than duplicating the list for every calling convention, this adds a fallback to the std::is_function primary template which identifies other function types. The fallback works by assuming that all function types fall into one of two categories: referenceable and abominable. The former can be detected by testing for function-to-pointer decay, and the latter are non-referenceable types that are not cv void. In order to detect referenceable types it's necessary to replace the current definition of __is_referenceable with one that doesn't depend on std::is_function, to avoid a cycle. The definition of std::decay can also be modified to only act on referenceable function types, because abominable function types do not decay. PR libstdc++/91371 * include/std/type_traits (__declval, declval, __void_t): Declare earlier in the file. (__is_referenceable): Rewrite to not depend on is_function. (__is_referenceable_function): New trait to identify non-abominable function types. (__is_qualified_function): New alias to identify abominable function types. (is_function): Make primary template use __is_referenceable_function and __is_qualified_function to detect function types not covered by the partial specializations. (__decay_selector): Use __is_referenceable_function instead of is_function. (__decay_selector<_Up, false, true>): Do not use add_pointer. * testsuite/20_util/bind/91371.cc: New test. * testsuite/20_util/is_function/91371.cc: New test. * testsuite/20_util/is_function/value.cc: Check more pointer types. * testsuite/20_util/is_member_function_pointer/91371.cc: New test. Tested x86_64-linux. Not committed yet. I'd like to hear Daniel's thoughts on this approach, as he wrote the original __is_referenceable trait, and much of . This new __is_referenceable simply uses void_t to detect whether forming T& is valid. The detection for function-to-pointer decay works by checking whether static_cast(declval()) is well-formed. If T is not a class type (which could have a conversion operator) and is not nullptr or cv void*cv (which can convert to nullptr* and cv void*cv* repectively) then it must be a function. The detection for abominable function types assumes that all types are referenceable except functions with cv- or ref-qualifiers and cv void types. So if it's not referenceable and not void, it's an abominable function type. Alisdair pointed out a much simpler implementation of is_function: /// is_function template struct is_function : public __bool_constant::value> { }; template struct is_function<_Tp&> : public false_type { }; template struct is_function<_Tp&&> : public false_type { }; I'm testing the attached patch which uses the above trick and keeps my earlier simplification for __is_referenceable. I plan to commit this, probably tomorrow. commit 310eae1386a8410682b86aef3fa5391018583577 Author: Jonathan Wakely Date: Mon Aug 19 22:04:58 2019 +0100 PR libstdc++/91371 make std::is_function handle other calling conventions The x86 attributes such as ms_abi, stdcall, fastcall etc. alter the function type, which means that functions with one of those attributes do not match any of the partial specializations of std::is_function. Rather than duplicating the list for every calling convention, use a much simpler definition of std::is_function. Also redefine __is_referenceable to not rely on partial specializations for each type of referenceable function. PR libstdc++/91371 * include/std/type_traits (is_function): Simplify definition. Remove partial specializations for function types. (__is_referenceable): Simplify definition. * testsuite/20_util/bind/91371.cc: New test. * testsuite/20_util/is_function/91371.cc: New test. * testsuite/20_util/is_function/value.cc: Check more pointer types. * testsuite/20_util/is_member_function_pointer/91371.cc: New test. * testsuite/20_util/is_object/91371.cc: New test. diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 44db2cade5d..443208813b1 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -223,11 +223,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __failure_type { }; - // Primary type categories. - template struct remove_cv; + template +struct is_const; + + // Primary type categories. + template struct __is_void_helper : public false_type { }; @@ -481,105
[PATCH] PR libstdc++/91371 make std::is_function handle other calling conventions
The x86 attributes such as ms_abi, stdcall, fastcall etc. alter the function type, which means that functions with one of those attributes do not match any of the partial specializations of std::is_function. Rather than duplicating the list for every calling convention, this adds a fallback to the std::is_function primary template which identifies other function types. The fallback works by assuming that all function types fall into one of two categories: referenceable and abominable. The former can be detected by testing for function-to-pointer decay, and the latter are non-referenceable types that are not cv void. In order to detect referenceable types it's necessary to replace the current definition of __is_referenceable with one that doesn't depend on std::is_function, to avoid a cycle. The definition of std::decay can also be modified to only act on referenceable function types, because abominable function types do not decay. PR libstdc++/91371 * include/std/type_traits (__declval, declval, __void_t): Declare earlier in the file. (__is_referenceable): Rewrite to not depend on is_function. (__is_referenceable_function): New trait to identify non-abominable function types. (__is_qualified_function): New alias to identify abominable function types. (is_function): Make primary template use __is_referenceable_function and __is_qualified_function to detect function types not covered by the partial specializations. (__decay_selector): Use __is_referenceable_function instead of is_function. (__decay_selector<_Up, false, true>): Do not use add_pointer. * testsuite/20_util/bind/91371.cc: New test. * testsuite/20_util/is_function/91371.cc: New test. * testsuite/20_util/is_function/value.cc: Check more pointer types. * testsuite/20_util/is_member_function_pointer/91371.cc: New test. Tested x86_64-linux. Not committed yet. I'd like to hear Daniel's thoughts on this approach, as he wrote the original __is_referenceable trait, and much of . This new __is_referenceable simply uses void_t to detect whether forming T& is valid. The detection for function-to-pointer decay works by checking whether static_cast(declval()) is well-formed. If T is not a class type (which could have a conversion operator) and is not nullptr or cv void*cv (which can convert to nullptr* and cv void*cv* repectively) then it must be a function. The detection for abominable function types assumes that all types are referenceable except functions with cv- or ref-qualifiers and cv void types. So if it's not referenceable and not void, it's an abominable function type. commit 2c8c1d0ef4b9ed6e80abf3694618c0e63859de78 Author: Jonathan Wakely Date: Fri Aug 16 15:03:54 2019 +0100 PR libstdc++/91371 make std::is_function handle other calling conventions The x86 attributes such as ms_abi, stdcall, fastcall etc. alter the function type, which means that functions with one of those attributes do not match any of the partial specializations of std::is_function. Rather than duplicating the list for every calling convention, add a fallback to the std::is_function primary template which identifies other function types. The fallback works by assuming that all function types fall into one of two categories: referenceable and abominable. The former can be detected by testing for function-to-pointer decay, and the latter are non-referenceable types that are not cv void. In order to detect referenceable types it's necessary to replace the current definition of __is_referenceable with one that doesn't depend on std::is_function, to avoid a cycle. The definition of std::decay can also be modified to only act on referenceable function types, because abominable function types do not decay. PR libstdc++/91371 * include/std/type_traits (__declval, declval, __void_t): Declare earlier in the file. (__is_referenceable): Rewrite to not depend on is_function. (__is_referenceable_function): New trait to identify non-abominable function types. (__is_qualified_function): New alias to identify abominable function types. (is_function): Make primary template use __is_referenceable_function and __is_qualified_function to detect function types not covered by the partial specializations. (__decay_selector): Use __is_referenceable_function instead of is_function. (__decay_selector<_Up, false, true>): Do not use add_pointer. * testsuite/20_util/bind/91371.cc: New test. * testsuite/20_util/is_function/91371.cc: New test. * testsuite/20_util/is_function/value.cc: Check more pointer types. *