From: Patrick Palka Date: Tue, 24 Jun 2025 13:33:25 +0000 (-0400) Subject: libstdc++: Unnecessary type completion in __is_complete_or_unbounded [PR120717] X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bc8f5424977b74e107543b34af00768cdbb3a3cf;p=thirdparty%2Fgcc.git libstdc++: Unnecessary type completion in __is_complete_or_unbounded [PR120717] 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 an unexpected -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 and introducing a __maybe_complete_object_type helper. PR libstdc++/120717 libstdc++-v3/ChangeLog: * include/std/type_traits (__maybe_complete_object_type): New helper trait, factored out from ... (__is_complete_or_unbounded): ... here. Only check sizeof on a __maybe_complete_object_type type. Fix formatting. * testsuite/20_util/is_complete_or_unbounded/120717.cc: New test. Reviewed-by: Tomasz KamiƄski Co-authored-by: Jonathan Wakely Reviewed-by: Jonathan Wakely --- diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index abff9f88000..055411195f1 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 - struct is_reference; - template - struct is_function; - template - struct is_void; + struct is_object; template struct remove_cv; template @@ -294,21 +290,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct __is_array_unknown_bounds; + // An object type which is not an unbounded array. + // It might still be an incomplete type, but if this is false_type + // then we can be certain it's not a complete object type. + template + using __maybe_complete_object_type + = __and_, __not_<__is_array_unknown_bounds<_Tp>>>; + // Helper functions that return false_type for incomplete classes, // incomplete unions and arrays of known bound from those. - template - constexpr true_type __is_complete_or_unbounded(__type_identity<_Tp>) - { return {}; } - - template - 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 (returning true_type). + template::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 + // (returning true_type), and incomplete types (returning false_type). + template + constexpr typename __not_<__maybe_complete_object_type<_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 00000000000..4c07683d494 --- /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 + +// Verify __is_complete_or_unbounded doesn't try to instantiate the underlying +// type of a reference or array of unknown bound. +template struct A { static_assert(false, "do not instantiate"); }; +static_assert(std::__is_complete_or_unbounded(std::__type_identity&>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity&&>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity[]>{}), ""); + +// Verify __is_complete_or_unbounded doesn't produce unexpected +// -Wsfinae-incomplete warnings. +struct B; +static_assert(std::__is_complete_or_unbounded(std::__type_identity{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity{}), ""); +struct B { }; // { dg-bogus "-Wsfinae-incomplete" }