From 91bac9fed5d082f0b180834110ebc0f46f97599a Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Mon, 1 Nov 2021 11:06:51 +0000 Subject: libstdc++: Fix range access for empty std::valarray [PR103022] The std::begin and std::end overloads for std::valarray are defined in terms of std::addressof(v[0]) which is undefined for an empty valarray. libstdc++-v3/ChangeLog: PR libstdc++/103022 * include/std/valarray (begin, end): Do not dereference an empty valarray. Add noexcept and [[nodiscard]]. * testsuite/26_numerics/valarray/range_access.cc: Check empty valarray. Check iterator properties. Run as well as compiling. * testsuite/26_numerics/valarray/range_access2.cc: Likewise. * testsuite/26_numerics/valarray/103022.cc: New test. --- libstdc++-v3/include/std/valarray | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'libstdc++-v3/include/std/valarray') diff --git a/libstdc++-v3/include/std/valarray b/libstdc++-v3/include/std/valarray index 5adc942..c6242eb 100644 --- a/libstdc++-v3/include/std/valarray +++ b/libstdc++-v3/include/std/valarray @@ -1210,9 +1210,10 @@ _DEFINE_BINARY_OPERATOR(>=, __greater_equal) * @param __va valarray. */ template + [[__nodiscard__]] inline _Tp* - begin(valarray<_Tp>& __va) - { return std::__addressof(__va[0]); } + begin(valarray<_Tp>& __va) noexcept + { return __va.size() ? std::__addressof(__va[0]) : nullptr; } /** * @brief Return an iterator pointing to the first element of @@ -1220,9 +1221,10 @@ _DEFINE_BINARY_OPERATOR(>=, __greater_equal) * @param __va valarray. */ template + [[__nodiscard__]] inline const _Tp* - begin(const valarray<_Tp>& __va) - { return std::__addressof(__va[0]); } + begin(const valarray<_Tp>& __va) noexcept + { return __va.size() ? std::__addressof(__va[0]) : nullptr; } /** * @brief Return an iterator pointing to one past the last element of @@ -1230,9 +1232,15 @@ _DEFINE_BINARY_OPERATOR(>=, __greater_equal) * @param __va valarray. */ template + [[__nodiscard__]] inline _Tp* - end(valarray<_Tp>& __va) - { return std::__addressof(__va[0]) + __va.size(); } + end(valarray<_Tp>& __va) noexcept + { + if (auto __n = __va.size()) + return std::__addressof(__va[0]) + __n; + else + return nullptr; + } /** * @brief Return an iterator pointing to one past the last element of @@ -1240,9 +1248,15 @@ _DEFINE_BINARY_OPERATOR(>=, __greater_equal) * @param __va valarray. */ template + [[__nodiscard__]] inline const _Tp* - end(const valarray<_Tp>& __va) - { return std::__addressof(__va[0]) + __va.size(); } + end(const valarray<_Tp>& __va) noexcept + { + if (auto __n = __va.size()) + return std::__addressof(__va[0]) + __n; + else + return nullptr; + } #endif // C++11 /// @} group numeric_arrays -- cgit v1.1