Tested on x86_64-pc-linux-gnu, does this look OK for trunk? -- >8 --
When checking __is_complete_or_unbounded on a reference to incomplete type, we overeagerly try to instantiate/complete the referenced type which besides being unnecessary may also produce a -Wsfinae-incomplete warning (added in r16-1527) if the referenced type is later defined. This patch fixes this by effectively restricting the sizeof check to object (except unknown-bound array) types. In passing simplify the implementation by using is_object instead of is_function/reference/void. PR libstdc++/120717 libstdc++-v3/ChangeLog: * include/std/type_traits (__is_complete_or_unbounded): Don't check sizeof on a reference or unbounded array type. Simplify using is_object. Correct formatting. * testsuite/20_util/is_complete_or_unbounded/120717.cc: New test. --- libstdc++-v3/include/std/type_traits | 34 +++++++++---------- .../is_complete_or_unbounded/120717.cc | 20 +++++++++++ 2 files changed, 37 insertions(+), 17 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/120717.cc diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index abff9f880001..28960befd2c7 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -280,11 +280,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Forward declarations template<typename> - struct is_reference; - template<typename> - struct is_function; - template<typename> - struct is_void; + struct is_object; template<typename> struct remove_cv; template<typename> @@ -297,18 +293,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Helper functions that return false_type for incomplete classes, // incomplete unions and arrays of known bound from those. - template <typename _Tp, size_t = sizeof(_Tp)> - constexpr true_type __is_complete_or_unbounded(__type_identity<_Tp>) - { return {}; } - - template <typename _TypeIdentity, - typename _NestedType = typename _TypeIdentity::type> - constexpr typename __or_< - is_reference<_NestedType>, - is_function<_NestedType>, - is_void<_NestedType>, - __is_array_unknown_bounds<_NestedType> - >::type __is_complete_or_unbounded(_TypeIdentity) + // More specialized overload for complete object types. + template<typename _Tp, + typename = __enable_if_t<!__or_<__not_<is_object<_Tp>>, + __is_array_unknown_bounds<_Tp>>::value>, + size_t = sizeof(_Tp)> + constexpr true_type + __is_complete_or_unbounded(__type_identity<_Tp>) + { return {}; }; + + // Less specialized overload for reference and unknown-bound array types, and + // incomplete types. + template<typename _TypeIdentity, + typename _NestedType = typename _TypeIdentity::type> + constexpr typename __or_<__not_<is_object<_NestedType>>, + __is_array_unknown_bounds<_NestedType>>::type + __is_complete_or_unbounded(_TypeIdentity) { return {}; } // __remove_cv_t (std::remove_cv_t for C++11). diff --git a/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/120717.cc b/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/120717.cc new file mode 100644 index 000000000000..31fdf8fe9227 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/120717.cc @@ -0,0 +1,20 @@ +// PR libstdc++/120717 +// { dg-do compile { target c++11 } } +// { dg-additional-options "-Wsfinae-incomplete" } + +#include <type_traits> + +// Verify __is_complete_or_unbounded doesn't try to instantiate the underlying +// type of a reference or array of unknown bound. +template<class T> struct A { static_assert(false, "do not instantiate"); }; +static_assert(std::__is_complete_or_unbounded(std::__type_identity<A<int>&>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<A<int>&&>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<A<int>[]>{}), ""); + +// Verify __is_complete_or_unbounded doesn't produce -Wsfinae-incomplete +// warnings. +struct B; +static_assert(std::__is_complete_or_unbounded(std::__type_identity<B&>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<B&&>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<B[]>{}), ""); +struct B { }; // { dg-bogus "-Wsfinae-incomplete" } -- 2.50.0.81.gcb3b40381e