diff --git a/stl/inc/array b/stl/inc/array index 8f9b575f8ba..209bd9e95bd 100644 --- a/stl/inc/array +++ b/stl/inc/array @@ -500,7 +500,7 @@ public: return _Elems + _Size; } - _NODISCARD constexpr size_type size() const noexcept { + _NODISCARD _Ret_range_(==, _Size) constexpr size_type size() const noexcept { return _Size; } @@ -528,7 +528,7 @@ public: return _Elems[_Pos]; } - _NODISCARD _CONSTEXPR17 reference operator[](_In_range_(0, _Size - 1) size_type _Pos) noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR17 reference operator[](_In_range_(<, _Size) size_type _Pos) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pos < _Size, "array subscript out of range"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -536,7 +536,7 @@ public: return _Elems[_Pos]; } - _NODISCARD constexpr const_reference operator[](_In_range_(0, _Size - 1) size_type _Pos) const noexcept + _NODISCARD constexpr const_reference operator[](_In_range_(<, _Size) size_type _Pos) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pos < _Size, "array subscript out of range"); diff --git a/stl/inc/mdspan b/stl/inc/mdspan index 2535e0d5cd3..ce21eb7428d 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -81,7 +81,7 @@ private: rank_type _Counter = 0; for (rank_type _Idx = 0; _Idx < _Rank; ++_Idx) { if (_Static_extents[_Idx] == dynamic_extent) { - _Analysis_assume_(_Counter < _Rank_dynamic); // TRANSITION, DevCom-923103 + _Analysis_assume_(_Counter < _Rank_dynamic); // guaranteed by how _Rank_dynamic is calculated _Result[_Counter] = _Idx; ++_Counter; } @@ -174,7 +174,7 @@ private: } public: - _NODISCARD static constexpr rank_type rank() noexcept { + _NODISCARD _Ret_range_(==, _Rank) static constexpr rank_type rank() noexcept { return _Rank; } @@ -182,14 +182,14 @@ public: return _Rank_dynamic; } - _NODISCARD static constexpr size_t static_extent(const rank_type _Idx) noexcept { + _NODISCARD static constexpr size_t static_extent(_In_range_(<, _Rank) const rank_type _Idx) noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Idx < _Rank, "Index must be less than rank() (N4950 [mdspan.extents.obs]/1)"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return _Static_extents[_Idx]; } - _NODISCARD constexpr index_type extent(const rank_type _Idx) const noexcept { + _NODISCARD constexpr index_type extent(_In_range_(<, _Rank) const rank_type _Idx) const noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Idx < _Rank, "Index must be less than rank() (N4950 [mdspan.extents.obs]/3)"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -591,7 +591,7 @@ public: return true; } - _NODISCARD constexpr index_type stride(const rank_type _Idx) const noexcept + _NODISCARD constexpr index_type stride(_In_range_(<, extents_type::_Rank) const rank_type _Idx) const noexcept requires (extents_type::rank() > 0) { #if _CONTAINER_DEBUG_LEVEL > 0 @@ -744,7 +744,7 @@ public: return true; } - _NODISCARD constexpr index_type stride(const rank_type _Idx) const noexcept + _NODISCARD constexpr index_type stride(_In_range_(<, extents_type::_Rank) const rank_type _Idx) const noexcept requires (extents_type::rank() > 0) { #if _CONTAINER_DEBUG_LEVEL > 0 @@ -975,10 +975,14 @@ public: return true; } - _NODISCARD constexpr index_type stride(const rank_type _Idx) const noexcept { + _NODISCARD constexpr index_type stride(_In_range_(<, extents_type::_Rank) const rank_type _Idx) const noexcept { if constexpr (extents_type::rank() == 0) { _STL_VERIFY(false, "The argument to stride must be nonnegative and less than extents_type::rank()."); } else { +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Idx < extents_type::_Rank, + "The argument to stride must be nonnegative and less than extents_type::rank()."); +#endif // _CONTAINER_DEBUG_LEVEL > 0 return this->_Array[_Idx]; } } @@ -1187,7 +1191,7 @@ private: "[mdspan.mdspan.overview]/2.3)."); public: - _NODISCARD static constexpr rank_type rank() noexcept { + _NODISCARD _Ret_range_(==, extents_type::_Rank) static constexpr rank_type rank() noexcept { return extents_type::_Rank; } @@ -1195,14 +1199,14 @@ public: return extents_type::_Rank_dynamic; } - _NODISCARD static constexpr size_t static_extent(const rank_type _Idx) noexcept { + _NODISCARD static constexpr size_t static_extent(_In_range_(<, extents_type::_Rank) const rank_type _Idx) noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Idx < extents_type::_Rank, "Index must be less than rank() (N4950 [mdspan.extents.obs]/1)"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return extents_type::_Static_extents[_Idx]; } - _NODISCARD constexpr index_type extent(const rank_type _Idx) const noexcept { + _NODISCARD constexpr index_type extent(_In_range_(<, extents_type::_Rank) const rank_type _Idx) const noexcept { return this->_Map.extents().extent(_Idx); } diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 5ae8f27917d..61e5c5c43ad 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -1006,22 +1006,15 @@ std/utilities/format/format.range/format.range.fmtset/format.pass.cpp FAIL std/utilities/format/format.range/format.range.fmtstr/format.pass.cpp FAIL std/utilities/format/format.tuple/format.pass.cpp FAIL -# Not analyzed. Apparent false positives from static analysis where it thinks that array indexing is out of bounds. -# warning C28020: The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call. +# Not analyzed. Static analysis thinks that array indexing is out of bounds because it can't prove otherwise. +# warning C28020: The expression '_Param_(1)<1' is not true at this call. # Note: The :1 (ASAN) configuration doesn't run static analysis. std/containers/views/mdspan/extents/ctor_default.pass.cpp:0 FAIL std/containers/views/mdspan/extents/ctor_from_array.pass.cpp:0 FAIL std/containers/views/mdspan/extents/ctor_from_integral.pass.cpp:0 FAIL std/containers/views/mdspan/extents/ctor_from_span.pass.cpp:0 FAIL -std/containers/views/mdspan/layout_left/ctor.layout_stride.pass.cpp:0 FAIL -std/containers/views/mdspan/layout_left/stride.pass.cpp:0 FAIL -std/containers/views/mdspan/layout_right/ctor.layout_stride.pass.cpp:0 FAIL -std/containers/views/mdspan/layout_right/stride.pass.cpp:0 FAIL -std/containers/views/mdspan/layout_stride/ctor.default.pass.cpp:0 FAIL -std/containers/views/mdspan/layout_stride/ctor.extents_array.pass.cpp:0 FAIL -std/containers/views/mdspan/layout_stride/ctor.extents_span.pass.cpp:0 FAIL +std/containers/views/mdspan/layout_stride/comparison.pass.cpp:0 FAIL std/containers/views/mdspan/layout_stride/ctor.strided_mapping.pass.cpp:0 FAIL -std/containers/views/mdspan/layout_stride/stride.pass.cpp:0 FAIL std/containers/views/mdspan/mdspan/conversion.pass.cpp:0 FAIL std/containers/views/mdspan/mdspan/ctor.dh_array.pass.cpp:0 FAIL std/containers/views/mdspan/mdspan/ctor.dh_span.pass.cpp:0 FAIL @@ -1099,6 +1092,8 @@ std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.ra std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.range.pass.cpp:1 SKIPPED std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp:0 SKIPPED std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp:1 SKIPPED +std/algorithms/alg.sorting/alg.lex.comparison/ranges.lexicographical_compare.pass.cpp:0 SKIPPED +std/algorithms/alg.sorting/alg.lex.comparison/ranges.lexicographical_compare.pass.cpp:1 SKIPPED std/algorithms/alg.sorting/alg.merge/ranges_merge.pass.cpp:0 SKIPPED std/algorithms/alg.sorting/alg.merge/ranges_merge.pass.cpp:1 SKIPPED std/algorithms/alg.sorting/alg.set.operations/includes/ranges_includes.pass.cpp:0 SKIPPED diff --git a/tests/std/include/test_mdspan_support.hpp b/tests/std/include/test_mdspan_support.hpp index cc09948b0ab..500d22be37a 100644 --- a/tests/std/include/test_mdspan_support.hpp +++ b/tests/std/include/test_mdspan_support.hpp @@ -251,7 +251,10 @@ MappingProperties get_mapping_properties(const Mapping& mapping) { constexpr auto rank = Mapping::extents_type::rank(); constexpr std::make_index_sequence rank_indices; - auto get_extent = [&](size_t i) { return mapping.extents().extent(i); }; + auto get_extent = [&](size_t i) { + assert(i < rank); + return mapping.extents().extent(i); + }; auto multidim_indices = [&](std::index_sequence) { return std::views::cartesian_product(std::views::iota(IndexType{0}, get_extent(Indices))...); }(rank_indices); diff --git a/tests/std/test.lst b/tests/std/test.lst index 4631d566e54..8790acf4c96 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -755,4 +755,5 @@ tests\VSO_0849827_multicontainer_emplace_hint_position tests\VSO_0938757_attribute_order tests\VSO_0961751_hash_range_erase tests\VSO_0971246_legacy_await_headers +tests\VSO_1804139_static_analysis_warning_with_single_element_array tests\VSO_1925201_iter_traits diff --git a/tests/std/tests/P0009R18_mdspan_extents_death/test.cpp b/tests/std/tests/P0009R18_mdspan_extents_death/test.cpp index 6565c43abe7..bdb9279c6af 100644 --- a/tests/std/tests/P0009R18_mdspan_extents_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_extents_death/test.cpp @@ -16,13 +16,19 @@ using namespace std; void test_static_extent_function_with_invalid_index() { using E = extents; // Index must be less than rank() +#pragma warning(push) +#pragma warning(disable : 28020) // yay, /analyze catches this mistake at compile time! (void) E::static_extent(1); +#pragma warning(pop) } void test_extent_function_with_invalid_index() { extents e; // Index must be less than rank() +#pragma warning(push) +#pragma warning(disable : 28020) // yay, /analyze catches this mistake at compile time! (void) e.extent(1); +#pragma warning(pop) } void test_construction_from_other_extents_with_invalid_values() { diff --git a/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp index 3d3d511a9e6..c48709d1875 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp @@ -90,10 +90,7 @@ constexpr void check_members(const extents& ext, index_se if constexpr (Ext::rank() > 0) { strides.front() = 1; for (size_t i = 1; i < Ext::rank(); ++i) { -#pragma warning(push) -#pragma warning(disable : 28020) // TRANSITION, DevCom-923103 strides[i] = static_cast(strides[i - 1] * ext.extent(i - 1)); -#pragma warning(pop) } } diff --git a/tests/std/tests/P0009R18_mdspan_layout_left_death/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_left_death/test.cpp index ae12da21424..b0b5f031e7d 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_left_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_left_death/test.cpp @@ -59,7 +59,10 @@ void test_call_operator() { void test_stride_function() { layout_left::mapping> m; // Value of i must be less than extents_type::rank() +#pragma warning(push) +#pragma warning(disable : 28020) // yay, /analyze catches this mistake at compile time! (void) m.stride(1); +#pragma warning(pop) } int main(int argc, char* argv[]) { diff --git a/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp index c16cff03661..ef08dd7e9a9 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp @@ -90,10 +90,7 @@ constexpr void check_members(const extents& ext, index_se if constexpr (Ext::rank() > 0) { strides.back() = 1; for (size_t i = Ext::rank() - 1; i-- > 0;) { -#pragma warning(push) -#pragma warning(disable : 28020) // TRANSITION, DevCom-923103 strides[i] = static_cast(strides[i + 1] * ext.extent(i + 1)); -#pragma warning(pop) } } diff --git a/tests/std/tests/P0009R18_mdspan_layout_right_death/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_right_death/test.cpp index 4e643353f18..ef72ed7be34 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_right_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_right_death/test.cpp @@ -59,7 +59,10 @@ void test_call_operator() { void test_stride_function() { layout_right::mapping> m; // Value of i must be less than extents_type::rank() +#pragma warning(push) +#pragma warning(disable : 28020) // yay, /analyze catches this mistake at compile time! (void) m.stride(1); +#pragma warning(pop) } int main(int argc, char* argv[]) { diff --git a/tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp index d276b22e7fb..5f34b8c1541 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp @@ -210,12 +210,9 @@ constexpr void do_check_members(const extents& ext, } { // Check 'stride' function - for (size_t i = 0; i < strs.size(); ++i) { + for (size_t i = 0; i < Ext::rank(); ++i) { same_as decltype(auto) s = m.stride(i); -#pragma warning(push) -#pragma warning(disable : 28020) // TRANSITION, DevCom-923103 assert(cmp_equal(strs[i], s)); -#pragma warning(pop) } } diff --git a/tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp index 3663f784d44..4668facbd22 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp @@ -61,7 +61,10 @@ void test_call_operator() { void test_stride_with_empty_extents() { layout_stride::mapping> m; // The argument to stride must be nonnegative and less than extents_type::rank() +#pragma warning(push) +#pragma warning(disable : 28020) // yay, /analyze catches this mistake at compile time! (void) m.stride(0); +#pragma warning(pop) } int main(int argc, char* argv[]) { diff --git a/tests/std/tests/P0218R1_filesystem/test.cpp b/tests/std/tests/P0218R1_filesystem/test.cpp index 9a26c8f0483..c1c17d97412 100644 --- a/tests/std/tests/P0218R1_filesystem/test.cpp +++ b/tests/std/tests/P0218R1_filesystem/test.cpp @@ -3859,11 +3859,12 @@ basic_ostream& operator<<(basic_ostream& ostr, const L"symlink"sv, L"block"sv, L"character"sv, L"fifo"sv, L"socket"sv, L"unknown"sv, L"junction"sv}}; const size_t index = static_cast(ft); - if (!EXPECT(index < names.size())) { + if (index < names.size()) { + return ostr << L"file_type::" << names[index]; + } else { + EXPECT(false); return ostr << L"!!! INVALID file_type(" << index << L") !!!!"; } - - return ostr << L"file_type::" << names[index]; } template diff --git a/tests/std/tests/P2321R2_views_adjacent/test.cpp b/tests/std/tests/P2321R2_views_adjacent/test.cpp index ac0647a0873..ff27008b641 100644 --- a/tests/std/tests/P2321R2_views_adjacent/test.cpp +++ b/tests/std/tests/P2321R2_views_adjacent/test.cpp @@ -352,8 +352,10 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { same_as decltype(auto) i2 = ++i; assert(&i2 == &i); if (i != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*i == expected[1]); +#pragma warning(pop) } i = r.begin(); } @@ -362,8 +364,10 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { same_as decltype(auto) i2 = i++; assert(*i2 == expected[0]); if (i != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*i == expected[1]); +#pragma warning(pop) } i = r.begin(); } @@ -391,8 +395,10 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { same_as decltype(auto) i2 = i--; if (i2 != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*i2 == expected[1]); +#pragma warning(pop) } assert(*i == expected[0]); } @@ -403,8 +409,10 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { same_as decltype(auto) i2 = (i += 1); assert(&i2 == &i); if (i != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*i == expected[1]); +#pragma warning(pop) } same_as decltype(auto) i3 = (i -= 1); @@ -442,14 +450,18 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { { // Check operator+ same_as auto i2 = i + 1; if (i2 != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*i2 == expected[1]); +#pragma warning(pop) } same_as auto i3 = 1 + i; if (i3 != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*i3 == expected[1]); +#pragma warning(pop) } } @@ -537,8 +549,10 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { same_as decltype(auto) ci2 = ++ci; assert(&ci2 == &ci); if (ci != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*ci == expected[1]); +#pragma warning(pop) } ci = r.begin(); } @@ -547,8 +561,10 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { same_as decltype(auto) ci2 = ci++; assert(*ci2 == expected[0]); if (ci != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*ci == expected[1]); +#pragma warning(pop) } ci = r.begin(); } @@ -585,8 +601,10 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { same_as decltype(auto) ci2 = ci--; if (ci2 != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*ci2 == expected[1]); +#pragma warning(pop) } assert(*ci == expected[0]); } @@ -597,8 +615,10 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { same_as decltype(auto) ci2 = (ci += 1); assert(&ci2 == &ci); if (ci != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*ci == expected[1]); +#pragma warning(pop) } same_as decltype(auto) ci3 = (ci -= 1); @@ -659,14 +679,18 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { { // Check operator+ same_as auto ci2 = ci + 1; if (ci2 != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*ci2 == expected[1]); +#pragma warning(pop) } same_as auto ci3 = 1 + ci; if (ci3 != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*ci3 == expected[1]); +#pragma warning(pop) } } diff --git a/tests/std/tests/P2321R2_views_adjacent_transform/test.cpp b/tests/std/tests/P2321R2_views_adjacent_transform/test.cpp index 3c78fd8ee59..26c0e892c5b 100644 --- a/tests/std/tests/P2321R2_views_adjacent_transform/test.cpp +++ b/tests/std/tests/P2321R2_views_adjacent_transform/test.cpp @@ -427,8 +427,10 @@ constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { same_as decltype(auto) i2 = ++i; assert(&i2 == &i); if (i != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*i == expected_rng[1]); +#pragma warning(pop) } i = r.begin(); } @@ -437,8 +439,10 @@ constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { same_as decltype(auto) i2 = i++; assert(*i2 == expected_rng[0]); if (i != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*i == expected_rng[1]); +#pragma warning(pop) } i = r.begin(); } @@ -466,8 +470,10 @@ constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { same_as decltype(auto) i2 = i--; if (i2 != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*i2 == expected_rng[1]); +#pragma warning(pop) } assert(*i == expected_rng[0]); } @@ -478,8 +484,10 @@ constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { same_as decltype(auto) i2 = (i += 1); assert(&i2 == &i); if (i != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*i == expected_rng[1]); +#pragma warning(pop) } same_as decltype(auto) i3 = (i -= 1); @@ -517,14 +525,18 @@ constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { { // Check operator+ same_as auto i2 = i + 1; if (i2 != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*i2 == expected_rng[1]); +#pragma warning(pop) } same_as auto i3 = 1 + i; if (i3 != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*i3 == expected_rng[1]); +#pragma warning(pop) } } @@ -609,8 +621,10 @@ constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { same_as decltype(auto) ci2 = ++ci; assert(&ci2 == &ci); if (ci != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*ci == expected_rng[1]); +#pragma warning(pop) } ci = r.begin(); } @@ -619,8 +633,10 @@ constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { same_as decltype(auto) ci2 = ci++; assert(*ci2 == expected_rng[0]); if (ci != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*ci == expected_rng[1]); +#pragma warning(pop) } ci = r.begin(); } @@ -657,8 +673,10 @@ constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { same_as decltype(auto) ci2 = ci--; if (ci2 != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*ci2 == expected_rng[1]); +#pragma warning(pop) } assert(*ci == expected_rng[0]); } @@ -669,8 +687,10 @@ constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { same_as decltype(auto) ci2 = (ci += 1); assert(&ci2 == &ci); if (ci != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*ci == expected_rng[1]); +#pragma warning(pop) } same_as decltype(auto) ci3 = (ci -= 1); @@ -732,14 +752,18 @@ constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { { // Check operator+ same_as auto ci2 = ci + 1; if (ci2 != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*ci2 == expected_rng[1]); +#pragma warning(pop) } same_as auto ci3 = 1 + ci; if (ci3 != r.end()) { -#pragma warning(suppress : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#pragma warning(push) +#pragma warning(disable : 28020) // The expression '_Param_(1)<1' is not true at this call. assert(*ci3 == expected_rng[1]); +#pragma warning(pop) } } diff --git a/tests/std/tests/VSO_1804139_static_analysis_warning_with_single_element_array/env.lst b/tests/std/tests/VSO_1804139_static_analysis_warning_with_single_element_array/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/VSO_1804139_static_analysis_warning_with_single_element_array/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/VSO_1804139_static_analysis_warning_with_single_element_array/test.compile.pass.cpp b/tests/std/tests/VSO_1804139_static_analysis_warning_with_single_element_array/test.compile.pass.cpp new file mode 100644 index 00000000000..27984b68284 --- /dev/null +++ b/tests/std/tests/VSO_1804139_static_analysis_warning_with_single_element_array/test.compile.pass.cpp @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// DevCom-10342063 VSO-1804139 False positive C28020 iterating over single element std::array + +#include +#include +using namespace std; + +bool IsSmallPrime(const int val) { + static constexpr array small_primes{2}; + + for (size_t i = 0; i < small_primes.size(); ++i) { + if (val == small_primes[i]) { + return true; + } + } + + return false; +} + +bool IsPrime(const int val) { + static constexpr array primes{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; + + for (size_t i = 0; i < primes.size(); ++i) { + if (val == primes[i]) { + return true; + } + } + + return false; +}