[PATCH] libstdc++: Unnecessary type completion in __is_complete_or_unbounded [PR120717]
Tomasz Kaminski
tkaminsk@redhat.com
Tue Jun 24 06:16:36 GMT 2025
On Tue, Jun 24, 2025 at 4:19 AM Patrick Palka <ppalka@redhat.com> wrote:
> 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
>
LGTM. Thanks.
>
> 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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250624/e185c90b/attachment.htm>
More information about the Libstdc++
mailing list