diff options
author | Anna Gringauze <annagrin@microsoft.com> | 2018-08-12 21:44:17 -0700 |
---|---|---|
committer | Neil MacIntosh <neilmac@fb.com> | 2018-08-12 21:44:17 -0700 |
commit | cea0d0ac2bd775f0fb4c7e357a089979370ae3cd (patch) | |
tree | faa0e678f606971b55ef795d507d613d40e93de2 /include | |
parent | 6a75903c79ff7109c24d281372005b622a9d9177 (diff) | |
download | platform_external_Microsoft-GSL-cea0d0ac2bd775f0fb4c7e357a089979370ae3cd.tar.gz platform_external_Microsoft-GSL-cea0d0ac2bd775f0fb4c7e357a089979370ae3cd.tar.bz2 platform_external_Microsoft-GSL-cea0d0ac2bd775f0fb4c7e357a089979370ae3cd.zip |
fix cppcorecheck warnings (#703)
* Added c++17 test configurations for clang5.0 and clang6.0
* Fixed CppCoreCheck warnings in GSL and tests
- Added CMakeSettings.json for VS Open Folder configuration
- So we can easily run CppCoreCheck in VS
- Fixed CppCorecheck warnings where it made sense
- Suppressed the rest
- Some suppression does not work due to compiler/tool bugs,
so replaced by #pragma disable
- CppCoreCheck has noise, suppressed those with comments
- Catch produces many warnings, blanket-supressed them all
- Had to fix clang formatting to keep attributes in place
- clang-format does not support attributes, so I am using
- "CommentPragmas: '^ NO-FORMAT:'" to skip formatiting on them
- Removed GSL_NOEXCEPT macro, removed incorred noexcepts
* Ignore unknown attributes
* ignore unknown attributes in noexception mode tests
* fixed C26472 in at()
* created GSL_SUPPRESS macro to allow all compilers to parse suppression attributes
* try to fix gcc compilation problems with attributes
* ignore gsl::suppress for gcc
* move suppression to function level on return statements
clang5.0 and up does not allow attributes on return statemets in constexpr functions
* move suppression to function level on return statements
* use GSL_SUPPRESS in algorithm_tests
* Addressed PR comments
Diffstat (limited to 'include')
-rw-r--r-- | include/gsl/gsl_algorithm | 8 | ||||
-rw-r--r-- | include/gsl/gsl_assert | 21 | ||||
-rw-r--r-- | include/gsl/gsl_byte | 25 | ||||
-rw-r--r-- | include/gsl/gsl_util | 40 | ||||
-rw-r--r-- | include/gsl/multi_span | 441 | ||||
-rw-r--r-- | include/gsl/span | 157 | ||||
-rw-r--r-- | include/gsl/string_span | 112 |
7 files changed, 437 insertions, 367 deletions
diff --git a/include/gsl/gsl_algorithm b/include/gsl/gsl_algorithm index 710792f..c2ba31f 100644 --- a/include/gsl/gsl_algorithm +++ b/include/gsl/gsl_algorithm @@ -31,15 +31,12 @@ #pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4996) // unsafe use of std::copy_n -// blanket turn off warnings from CppCoreCheck for now -// so people aren't annoyed by them when running the tool. -// more targeted suppressions will be added in a future update to the GSL -#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495) #endif // _MSC_VER namespace gsl { - +// Note: this will generate faster code than std::copy using span iterator in older msvc+stl +// not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915) template <class SrcElementType, std::ptrdiff_t SrcExtent, class DestElementType, std::ptrdiff_t DestExtent> void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest) @@ -51,6 +48,7 @@ void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> "Source range is longer than target range"); Expects(dest.size() >= src.size()); + GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute std::copy_n(src.data(), src.size(), dest.data()); } diff --git a/include/gsl/gsl_assert b/include/gsl/gsl_assert index 70a6eba..321bf20 100644 --- a/include/gsl/gsl_assert +++ b/include/gsl/gsl_assert @@ -21,6 +21,20 @@ #include <stdexcept> // for logic_error // +// make suppress attributes parse for some compilers +// Hopefully temporary until suppresion stardization occurs +// +#if defined (_MSC_VER) +#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] +#else +#if defined(__clang__) +#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] +#else +#define GSL_SUPPRESS(x) +#endif // __clang__ +#endif // _MSC_VER + +// // Temporary until MSVC STL supports no-exceptions mode. // Currently terminate is a no-op in this mode, so we add termination behavior back // @@ -85,6 +99,7 @@ namespace details typedef void (__cdecl *terminate_handler)(); + GSL_SUPPRESS(f.6) // NO-FORMAT: attribute [[noreturn]] inline void __cdecl default_terminate_handler() { __fastfail(RANGE_CHECKS_FAILURE); @@ -110,11 +125,7 @@ namespace details #if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) template <typename Exception> -#if defined(__clang__) || defined(__GNUC__) -#else - [[gsl::suppress(f.6)]] -#endif - [[noreturn]] void throw_exception(Exception&&) + [[noreturn]] void throw_exception(Exception&&) noexcept { gsl::details::terminate(); } diff --git a/include/gsl/gsl_byte b/include/gsl/gsl_byte index 6b770fd..bc18886 100644 --- a/include/gsl/gsl_byte +++ b/include/gsl/gsl_byte @@ -17,14 +17,28 @@ #ifndef GSL_BYTE_H #define GSL_BYTE_H +// +// make suppress attributes work for some compilers +// Hopefully temporary until suppresion standardization occurs +// +#if defined(_MSC_VER) +#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] +#else +#if defined(__clang__) +#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] +#else +#define GSL_SUPPRESS(x) +#endif // __clang__ +#endif // _MSC_VER + #include <type_traits> #ifdef _MSC_VER #pragma warning(push) -// don't warn about function style casts in byte related operators -#pragma warning(disable : 26493) +// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. +#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates does not always work #ifndef GSL_USE_STD_BYTE // this tests if we are under MSVC and the standard lib has std::byte and it is enabled @@ -57,12 +71,12 @@ #define GSL_USE_STD_BYTE 0 -#endif //defined(__cplusplus) && (__cplusplus >= 201703L) +#endif //defined(__cplusplus) && (__cplusplus >= 201703L) && // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) #endif // GSL_USE_STD_BYTE -#endif // _MSC_VER +#endif // _MSC_VER // Use __may_alias__ attribute on gcc and clang #if defined __clang__ || (__GNUC__ > 5) @@ -75,7 +89,6 @@ namespace gsl { #if GSL_USE_STD_BYTE - using std::byte; using std::to_integer; @@ -160,6 +173,8 @@ constexpr byte to_byte_impl(T t) noexcept return static_cast<byte>(t); } template <> +// NOTE: need suppression since c++14 does not allow "return {t}" +// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept { return byte(t); diff --git a/include/gsl/gsl_util b/include/gsl/gsl_util index ee61711..542bbaa 100644 --- a/include/gsl/gsl_util +++ b/include/gsl/gsl_util @@ -34,8 +34,8 @@ #if _MSC_VER < 1910 #pragma push_macro("constexpr") #define constexpr /*constexpr*/ -#endif // _MSC_VER < 1910 -#endif // _MSC_VER +#endif // _MSC_VER < 1910 +#endif // _MSC_VER namespace gsl { @@ -62,6 +62,7 @@ public: final_action& operator=(const final_action&) = delete; final_action& operator=(final_action&&) = delete; + GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws ~final_action() noexcept { if (invoke_) f_(); @@ -69,12 +70,11 @@ public: private: F f_; - bool invoke_ {true}; + bool invoke_{true}; }; // finally() - convenience function to generate a final_action template <class F> - final_action<F> finally(const F& f) noexcept { return final_action<F>(f); @@ -88,10 +88,7 @@ final_action<F> finally(F&& f) noexcept // narrow_cast(): a searchable way to do narrowing casts of values template <class T, class U> -#if defined(__clang__) || defined(__GNUC__) -#else -[[gsl::suppress(type.1)]] -#endif +GSL_SUPPRESS(type.1) // NO-FORMAT: attribute constexpr T narrow_cast(U&& u) noexcept { return static_cast<T>(std::forward<U>(u)); @@ -108,15 +105,13 @@ namespace details : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value> { }; -} +} // namespace details // narrow() : a checked version of narrow_cast() that throws if the cast changed the value template <class T, class U> -#if defined(__clang__) || defined(__GNUC__) -#else -[[gsl::suppress(type.1)]] -#endif -T narrow(U u) +GSL_SUPPRESS(type.1) // NO-FORMAT: attribute +GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false) +T narrow(U u) noexcept(false) { T t = narrow_cast<T>(u); if (static_cast<U>(t) != u) gsl::details::throw_exception(narrowing_error()); @@ -129,29 +124,26 @@ T narrow(U u) // at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector // template <class T, std::size_t N> -#if defined(__clang__) || defined(__GNUC__) -#else -[[gsl::suppress(type.1,bounds.2,bounds.4)]] -#endif +GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute +GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute constexpr T& at(T (&arr)[N], const index i) { Expects(i >= 0 && i < narrow_cast<index>(N)); - return arr[static_cast<std::size_t>(i)]; + return arr[narrow_cast<std::size_t>(i)]; } template <class Cont> -#if defined(__clang__) || defined(__GNUC__) -#else -[[gsl::suppress(type.1,bounds.4)]] -#endif +GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute +GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()]) { Expects(i >= 0 && i < narrow_cast<index>(cont.size())); using size_type = decltype(cont.size()); - return cont[static_cast<size_type>(i)]; + return cont[narrow_cast<size_type>(i)]; } template <class T> +GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr T at(const std::initializer_list<T> cont, const index i) { Expects(i >= 0 && i < narrow_cast<index>(cont.size())); diff --git a/include/gsl/multi_span b/include/gsl/multi_span index 9862d0d..a7c96ce 100644 --- a/include/gsl/multi_span +++ b/include/gsl/multi_span @@ -44,6 +44,12 @@ #pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4702) // unreachable code +// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. +#pragma warning(disable : 26495) // uninitalized member when constructor calls constructor +#pragma warning(disable : 26473) // in some instantiations we cast to the same type +#pragma warning(disable : 26490) // TODO: bug in parser - attributes and templates +#pragma warning(disable : 26465) // TODO: bug - suppression does not work on template functions + #if _MSC_VER < 1910 #pragma push_macro("constexpr") #define constexpr /*constexpr*/ @@ -52,9 +58,9 @@ #endif // _MSC_VER // GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t) -// While there is a conversion from signed to unsigned, it happens at -// compiletime, so the compiler wouldn't have to warn indiscriminently, but -// could check if the source value actually doesn't fit into the target type +// While there is a conversion from signed to unsigned, it happens at +// compiletime, so the compiler wouldn't have to warn indiscriminently, but +// could check if the source value actually doesn't fit into the target type // and only warn in those cases. #if __GNUC__ > 6 #pragma GCC diagnostic push @@ -86,7 +92,7 @@ namespace details std::is_integral<T>::value && are_integral<Ts...>::value> { }; -} +} // namespace details template <std::size_t Rank> class multi_span_index final @@ -107,20 +113,23 @@ public: constexpr multi_span_index(const value_type (&values)[Rank]) noexcept { + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute std::copy(values, values + Rank, elems); } template <typename... Ts, typename = std::enable_if_t<(sizeof...(Ts) == Rank) && details::are_integral<Ts...>::value>> constexpr multi_span_index(Ts... ds) noexcept : elems{narrow_cast<value_type>(ds)...} - { - } + {} constexpr multi_span_index(const multi_span_index& other) noexcept = default; constexpr multi_span_index& operator=(const multi_span_index& rhs) noexcept = default; // Preconditions: component_idx < rank + GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute constexpr reference operator[](std::size_t component_idx) { Expects(component_idx < Rank); // Component index must be less than rank @@ -128,18 +137,25 @@ public: } // Preconditions: component_idx < rank - constexpr const_reference operator[](std::size_t component_idx) const + GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + constexpr const_reference operator[](std::size_t component_idx) const { Expects(component_idx < Rank); // Component index must be less than rank return elems[component_idx]; } + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute constexpr bool operator==(const multi_span_index& rhs) const { return std::equal(elems, elems + rank, rhs.elems); } - constexpr bool operator!=(const multi_span_index& rhs) const { return !(*this == rhs); } + constexpr bool operator!=(const multi_span_index& rhs) const + { + return !(*this == rhs); + } constexpr multi_span_index operator+() const noexcept { return *this; } @@ -166,12 +182,17 @@ public: constexpr multi_span_index& operator+=(const multi_span_index& rhs) { - std::transform(elems, elems + rank, rhs.elems, elems, std::plus<value_type>{}); + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute + std::transform(elems, elems + rank, rhs.elems, elems, + std::plus<value_type>{}); return *this; } constexpr multi_span_index& operator-=(const multi_span_index& rhs) { + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute std::transform(elems, elems + rank, rhs.elems, elems, std::minus<value_type>{}); return *this; } @@ -197,6 +218,8 @@ public: constexpr multi_span_index& operator*=(value_type v) { + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute std::transform(elems, elems + rank, elems, [v](value_type x) { return std::multiplies<value_type>{}(x, v); }); return *this; @@ -204,6 +227,8 @@ public: constexpr multi_span_index& operator/=(value_type v) { + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute std::transform(elems, elems + rank, elems, [v](value_type x) { return std::divides<value_type>{}(x, v); }); return *this; @@ -291,16 +316,14 @@ namespace details // TODO : following signature is for work around VS bug template <typename OtherRange> BoundsRanges(const OtherRange&, bool /* firstLevel */) - { - } + {} BoundsRanges(const std::ptrdiff_t* const) {} - BoundsRanges() = default; + BoundsRanges() noexcept = default; template <typename T, std::size_t Dim> void serialize(T&) const - { - } + {} template <typename T, std::size_t Dim> size_type linearize(const T&) const @@ -335,21 +358,22 @@ namespace details size_type m_bound; public: + GSL_SUPPRESS(f.23) // NO-FORMAT: attribute // this pointer type is cannot be assigned nullptr - issue in not_null + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute BoundsRanges(const std::ptrdiff_t* const arr) : Base(arr + 1), m_bound(*arr * this->Base::totalSize()) { Expects(0 <= *arr); } - BoundsRanges() : m_bound(0) {} + BoundsRanges() noexcept : m_bound(0) {} template <std::ptrdiff_t OtherRange, std::ptrdiff_t... RestOtherRanges> BoundsRanges(const BoundsRanges<OtherRange, RestOtherRanges...>& other, bool /* firstLevel */ = true) : Base(static_cast<const BoundsRanges<RestOtherRanges...>&>(other), false) , m_bound(other.totalSize()) - { - } + {} template <typename T, std::size_t Dim = 0> void serialize(T& arr) const @@ -359,6 +383,7 @@ namespace details } template <typename T, std::size_t Dim = 0> + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute size_type linearize(const T& arr) const { const size_type index = this->Base::totalSize() * arr[Dim]; @@ -375,9 +400,17 @@ namespace details return cur < m_bound ? cur + last : -1; } - size_type totalSize() const noexcept { return m_bound; } + GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + size_type totalSize() const noexcept + { + return m_bound; + } - size_type elementNum() const noexcept { return totalSize() / this->Base::totalSize(); } + GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + size_type elementNum() const noexcept + { + return totalSize() / this->Base::totalSize(); + } size_type elementNum(std::size_t dim) const noexcept { @@ -413,6 +446,7 @@ namespace details bool firstLevel = true) : Base(static_cast<const BoundsRanges<RestOtherRanges...>&>(other), false) { + GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive (void) firstLevel; } @@ -426,7 +460,10 @@ namespace details template <typename T, std::size_t Dim = 0> size_type linearize(const T& arr) const { + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute Expects(arr[Dim] >= 0 && arr[Dim] < CurrentRange); // Index is out of range + + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute return this->Base::totalSize() * arr[Dim] + this->Base::template linearize<T, Dim + 1>(arr); } @@ -440,10 +477,19 @@ namespace details return this->Base::totalSize() * arr[Dim] + last; } - size_type totalSize() const noexcept { return CurrentRange * this->Base::totalSize(); } + GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + size_type totalSize() const noexcept + { + return CurrentRange * this->Base::totalSize(); + } - size_type elementNum() const noexcept { return CurrentRange; } + GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used + size_type elementNum() const noexcept + { + return CurrentRange; + } + GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used size_type elementNum(std::size_t dim) const noexcept { if (dim > 0) @@ -505,12 +551,14 @@ namespace details constexpr Ret shift_left(const multi_span_index<Rank>& other) noexcept { Ret ret{}; - for (std::size_t i = 0; i < Rank - 1; ++i) { - ret[i] = other[i + 1]; + for (std::size_t i = 0; i < Rank - 1; ++i) + { + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + ret[i] = other[i + 1]; } return ret; } -} +} // namespace details template <typename IndexType> class bounds_iterator; @@ -528,7 +576,7 @@ class static_bounds<FirstRange, RestRanges...> using MyRanges = details::BoundsRanges<FirstRange, RestRanges...>; MyRanges m_ranges; - constexpr static_bounds(const MyRanges& range) : m_ranges(range) {} + constexpr static_bounds(const MyRanges& range) noexcept : m_ranges(range) {} template <std::ptrdiff_t... OtherRanges> friend class static_bounds; @@ -547,7 +595,8 @@ public: using sliced_type = static_bounds<RestRanges...>; using mapping_type = contiguous_mapping_tag; - constexpr static_bounds(const static_bounds&) = default; + constexpr static_bounds(const static_bounds&) noexcept = default; + constexpr static_bounds() /*noexcept*/ = default; template <typename SourceType, typename TargetType, std::size_t Rank> struct BoundsRangeConvertible2; @@ -605,8 +654,7 @@ public: MyRanges::DynamicNum > 0 || other.m_ranges.totalSize() >= m_ranges.totalSize()); } - constexpr static_bounds(std::initializer_list<size_type> il) - : m_ranges(il.begin()) + constexpr static_bounds(std::initializer_list<size_type> il) : m_ranges(il.begin()) { // Size of the initializer list must match the rank of the array Expects((MyRanges::DynamicNum == 0 && il.size() == 1 && *il.begin() == static_size) || @@ -615,8 +663,6 @@ public: Expects(m_ranges.totalSize() <= PTRDIFF_MAX); } - constexpr static_bounds() = default; - constexpr sliced_type slice() const noexcept { return sliced_type{static_cast<const details::BoundsRanges<RestRanges...>&>(m_ranges)}; @@ -690,8 +736,7 @@ public: }; template <std::size_t Rank> -class strided_bounds -{ +class strided_bounds { template <std::size_t OtherRank> friend class strided_bounds; @@ -717,53 +762,53 @@ public: constexpr strided_bounds(const value_type (&values)[rank], index_type strides) : m_extents(values), m_strides(std::move(strides)) - { - } + {} constexpr strided_bounds(const index_type& extents, const index_type& strides) noexcept - : m_extents(extents), - m_strides(strides) + : m_extents(extents), m_strides(strides) { } constexpr index_type strides() const noexcept { return m_strides; } + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute constexpr size_type total_size() const noexcept { size_type ret = 0; - for (std::size_t i = 0; i < rank; ++i) { - ret += (m_extents[i] - 1) * m_strides[i]; - } + for (std::size_t i = 0; i < rank; ++i) { ret += (m_extents[i] - 1) * m_strides[i]; } return ret + 1; } + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute constexpr size_type size() const noexcept { size_type ret = 1; - for (std::size_t i = 0; i < rank; ++i) { - ret *= m_extents[i]; - } + for (std::size_t i = 0; i < rank; ++i) { ret *= m_extents[i]; } return ret; } constexpr bool contains(const index_type& idx) const noexcept { - for (std::size_t i = 0; i < rank; ++i) { + for (std::size_t i = 0; i < rank; ++i) + { if (idx[i] < 0 || idx[i] >= m_extents[i]) return false; } return true; } + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute constexpr size_type linearize(const index_type& idx) const { size_type ret = 0; - for (std::size_t i = 0; i < rank; i++) { + for (std::size_t i = 0; i < rank; i++) + { Expects(idx[i] < m_extents[i]); // index is out of bounds of the array ret += idx[i] * m_strides[i]; } return ret; } + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute constexpr size_type stride() const noexcept { return m_strides[0]; } template <bool Enabled = (rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>> @@ -773,6 +818,8 @@ public: } template <std::size_t Dim = 0> + + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute constexpr size_type extent() const noexcept { static_assert(Dim < Rank, @@ -781,15 +828,10 @@ public: } constexpr index_type index_bounds() const noexcept { return m_extents; } - constexpr const_iterator begin() const noexcept - { - return const_iterator{*this, index_type{}}; - } - constexpr const_iterator end() const noexcept - { - return const_iterator{*this, index_bounds()}; - } + constexpr const_iterator begin() const noexcept { return const_iterator{*this, index_type{}}; } + + constexpr const_iterator end() const noexcept { return const_iterator{*this, index_bounds()}; } private: index_type m_extents; @@ -823,8 +865,7 @@ public: using index_size_type = typename IndexType::value_type; template <typename Bounds> explicit bounds_iterator(const Bounds& bnd, value_type curr) noexcept - : boundary_(bnd.index_bounds()), - curr_(std::move(curr)) + : boundary_(bnd.index_bounds()), curr_(std::move(curr)) { static_assert(is_bounds<Bounds>::value, "Bounds type must be provided"); } @@ -833,10 +874,15 @@ public: constexpr pointer operator->() const noexcept { return &curr_; } + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute constexpr bounds_iterator& operator++() noexcept + { - for (std::size_t i = rank; i-- > 0;) { - if (curr_[i] < boundary_[i] - 1) { + for (std::size_t i = rank; i-- > 0;) + { + if (curr_[i] < boundary_[i] - 1) + { curr_[i]++; return *this; } @@ -854,17 +900,19 @@ public: return ret; } + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute constexpr bounds_iterator& operator--() { - if (!less(curr_, boundary_)) { + if (!less(curr_, boundary_)) + { // if at the past-the-end, set to last element - for (std::size_t i = 0; i < rank; ++i) { - curr_[i] = boundary_[i] - 1; - } + for (std::size_t i = 0; i < rank; ++i) { curr_[i] = boundary_[i] - 1; } return *this; } - for (std::size_t i = rank; i-- > 0;) { - if (curr_[i] >= 1) { + for (std::size_t i = rank; i-- > 0;) + { + if (curr_[i] >= 1) + { curr_[i]--; return *this; } @@ -889,15 +937,15 @@ public: return ret += n; } + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute constexpr bounds_iterator& operator+=(difference_type n) { auto linear_idx = linearize(curr_) + n; std::remove_const_t<value_type> stride = 0; stride[rank - 1] = 1; - for (std::size_t i = rank - 1; i-- > 0;) { - stride[i] = stride[i + 1] * boundary_[i + 1]; - } - for (std::size_t i = 0; i < rank; ++i) { + for (std::size_t i = rank - 1; i-- > 0;) { stride[i] = stride[i + 1] * boundary_[i + 1]; } + for (std::size_t i = 0; i < rank; ++i) + { curr_[i] = linear_idx / stride[i]; linear_idx = linear_idx % stride[i]; } @@ -926,27 +974,19 @@ public: return curr_ == rhs.curr_; } - constexpr bool operator!=(const bounds_iterator& rhs) const noexcept - { - return !(*this == rhs); - } + + constexpr bool operator!=(const bounds_iterator& rhs) const noexcept { return !(*this == rhs); } constexpr bool operator<(const bounds_iterator& rhs) const noexcept { return less(curr_, rhs.curr_); } - constexpr bool operator<=(const bounds_iterator& rhs) const noexcept - { - return !(rhs < *this); - } + constexpr bool operator<=(const bounds_iterator& rhs) const noexcept { return !(rhs < *this); } constexpr bool operator>(const bounds_iterator& rhs) const noexcept { return rhs < *this; } - constexpr bool operator>=(const bounds_iterator& rhs) const noexcept - { - return !(rhs > *this); - } + constexpr bool operator>=(const bounds_iterator& rhs) const noexcept { return !(rhs > *this); } void swap(bounds_iterator& rhs) noexcept { @@ -955,30 +995,37 @@ public: } private: + + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute constexpr bool less(index_type& one, index_type& other) const noexcept { - for (std::size_t i = 0; i < rank; ++i) { + for (std::size_t i = 0; i < rank; ++i) + { if (one[i] < other[i]) return true; } return false; } + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute constexpr index_size_type linearize(const value_type& idx) const noexcept { // TODO: Smarter impl. // Check if past-the-end index_size_type multiplier = 1; index_size_type res = 0; - if (!less(idx, boundary_)) { + if (!less(idx, boundary_)) + { res = 1; - for (std::size_t i = rank; i-- > 0;) { + for (std::size_t i = rank; i-- > 0;) + { res += (idx[i] - 1) * multiplier; multiplier *= boundary_[i]; } } else { - for (std::size_t i = rank; i-- > 0;) { + for (std::size_t i = rank; i-- > 0;) + { res += idx[i] * multiplier; multiplier *= boundary_[i]; } @@ -1019,7 +1066,10 @@ namespace details typename Bounds::size_type stride[Bounds::rank] = {}; stride[Bounds::rank - 1] = 1; - for (std::size_t i = 1; i < Bounds::rank; ++i) { + for (std::size_t i = 1; i < Bounds::rank; ++i) + { + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute + GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute stride[Bounds::rank - i - 1] = stride[Bounds::rank - i] * extents[Bounds::rank - i]; } return {stride}; @@ -1175,7 +1225,7 @@ namespace details struct is_multi_span : is_multi_span_oracle<std::remove_cv_t<T>> { }; -} +} // namespace details template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions> class multi_span @@ -1211,7 +1261,9 @@ private: public: // default constructor - same as constructing from nullptr_t - constexpr multi_span() noexcept : multi_span(nullptr, bounds_type{}) + GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive + constexpr multi_span() noexcept + : multi_span(nullptr, bounds_type{}) { static_assert(bounds_type::dynamic_rank != 0 || (bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0), @@ -1220,7 +1272,9 @@ public: } // construct from nullptr - get an empty multi_span - constexpr multi_span(std::nullptr_t) noexcept : multi_span(nullptr, bounds_type{}) + GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive + constexpr multi_span(std::nullptr_t) noexcept + : multi_span(nullptr, bounds_type{}) { static_assert(bounds_type::dynamic_rank != 0 || (bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0), @@ -1230,8 +1284,9 @@ public: // construct from nullptr with size of 0 (helps with template function calls) template <class IntType, typename = std::enable_if_t<std::is_integral<IntType>::value>> - constexpr multi_span(std::nullptr_t, IntType size) - : multi_span(nullptr, bounds_type{}) + + // GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive // TODO: parser bug + constexpr multi_span(std::nullptr_t, IntType size) : multi_span(nullptr, bounds_type{}) { static_assert(bounds_type::dynamic_rank != 0 || (bounds_type::dynamic_rank == 0 && bounds_type::static_size == 0), @@ -1241,7 +1296,10 @@ public: } // construct from a single element - constexpr multi_span(reference data) noexcept : multi_span(&data, bounds_type{1}) + + GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive + constexpr multi_span(reference data) noexcept + : multi_span(&data, bounds_type{1}) { static_assert(bounds_type::dynamic_rank > 0 || bounds_type::static_size == 0 || bounds_type::static_size == 1, @@ -1253,14 +1311,14 @@ public: constexpr multi_span(value_type&&) = delete; // construct from pointer + length + GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive constexpr multi_span(pointer ptr, size_type size) : multi_span(ptr, bounds_type{size}) - { - } + {} // construct from pointer + length - multidimensional - constexpr multi_span(pointer data, bounds_type bounds) : data_(data), - bounds_(std::move(bounds)) + constexpr multi_span(pointer data, bounds_type bounds) + : data_(data), bounds_(std::move(bounds)) { Expects((bounds_.size() > 0 && data != nullptr) || bounds_.size() == 0); } @@ -1314,8 +1372,9 @@ public: constexpr multi_span(const std::array<T, N>& arr) : multi_span(arr.data(), bounds_type{static_bounds<N>{}}) { - static_assert(std::is_convertible<T(*)[], typename std::remove_const_t<value_type>(*)[]>::value, - "Cannot convert from source type to target multi_span type."); + static_assert( + std::is_convertible<T(*)[], typename std::remove_const_t<value_type>(*)[]>::value, + "Cannot convert from source type to target multi_span type."); static_assert(std::is_convertible<static_bounds<N>, bounds_type>::value, "You cannot construct a multi_span from a std::array of smaller size."); } @@ -1337,8 +1396,7 @@ public: constexpr multi_span(Cont& cont) : multi_span(static_cast<pointer>(cont.data()), details::newBoundsHelper<bounds_type>(narrow_cast<size_type>(cont.size()))) - { - } + {} // prevent constructing from temporary containers template <typename Cont, typename DataType = typename Cont::value_type, @@ -1356,10 +1414,8 @@ public: typename = std::enable_if_t<std::is_convertible<OtherValueType, ValueType>::value && std::is_convertible<OtherBounds, bounds_type>::value>> constexpr multi_span(multi_span<OtherValueType, OtherDimensions...> other) - : data_(other.data_), - bounds_(other.bounds_) - { - } + : data_(other.data_), bounds_(other.bounds_) + {} // trivial copy and move constexpr multi_span(const multi_span&) = default; @@ -1371,6 +1427,7 @@ public: // first() - extract the first Count elements into a new multi_span template <std::ptrdiff_t Count> + constexpr multi_span<ValueType, Count> first() const { static_assert(Count >= 0, "Count must be >= 0."); @@ -1427,8 +1484,8 @@ public: // subspan() - create a subview of count elements starting at offset // supplying dynamic_range for count will consume all available elements from offset - constexpr multi_span<ValueType, dynamic_range> - subspan(size_type offset, size_type count = dynamic_range) const + constexpr multi_span<ValueType, dynamic_range> subspan(size_type offset, + size_type count = dynamic_range) const { Expects((offset >= 0 && offset <= this->size()) && (count == dynamic_range || (count <= this->size() - offset))); @@ -1439,7 +1496,7 @@ public: constexpr strided_span<ValueType, Rank> section(index_type origin, index_type extents) const { - size_type size = this->bounds().total_size() - this->bounds().linearize(origin); + const size_type size = this->bounds().total_size() - this->bounds().linearize(origin); return {&this->operator[](origin), size, strided_bounds<Rank>{extents, details::make_stride(bounds())}}; } @@ -1490,17 +1547,20 @@ public: template <typename FirstIndex, typename... OtherIndices> constexpr reference operator()(FirstIndex firstIndex, OtherIndices... indices) { - index_type idx = {narrow_cast<std::ptrdiff_t>(firstIndex), - narrow_cast<std::ptrdiff_t>(indices)...}; + const index_type idx = {narrow_cast<std::ptrdiff_t>(firstIndex), + narrow_cast<std::ptrdiff_t>(indices)...}; return this->operator[](idx); } + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr reference operator[](const index_type& idx) const { return data_[bounds_.linearize(idx)]; } template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>> + + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr Ret operator[](size_type idx) const { Expects(idx >= 0 && idx < bounds_.size()); // index is out of bounds of the array @@ -1515,6 +1575,7 @@ public: constexpr iterator end() const noexcept { return iterator{this, false}; } + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute constexpr const_iterator cbegin() const noexcept { return const_iterator{reinterpret_cast<const const_span*>(this), true}; @@ -1540,56 +1601,51 @@ public: } template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> - constexpr bool - operator==(const multi_span<OtherValueType, OtherDimensions...>& other) const noexcept + typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>, + std::remove_cv_t<OtherValueType>>::value>> + constexpr bool operator==(const multi_span<OtherValueType, OtherDimensions...>& other) const { return bounds_.size() == other.bounds_.size() && (data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin())); } template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> - constexpr bool - operator!=(const multi_span<OtherValueType, OtherDimensions...>& other) const noexcept + typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>, + std::remove_cv_t<OtherValueType>>::value>> + constexpr bool operator!=(const multi_span<OtherValueType, OtherDimensions...>& other) const { return !(*this == other); } template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> - constexpr bool - operator<(const multi_span<OtherValueType, OtherDimensions...>& other) const noexcept + typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>, + std::remove_cv_t<OtherValueType>>::value>> + constexpr bool operator<(const multi_span<OtherValueType, OtherDimensions...>& other) const { return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end()); } template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> - constexpr bool - operator<=(const multi_span<OtherValueType, OtherDimensions...>& other) const noexcept + typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>, + std::remove_cv_t<OtherValueType>>::value>> + constexpr bool operator<=(const multi_span<OtherValueType, OtherDimensions...>& other) const { return !(other < *this); } template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> - constexpr bool - operator>(const multi_span<OtherValueType, OtherDimensions...>& other) const noexcept + typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>, + std::remove_cv_t<OtherValueType>>::value>> + constexpr bool operator>(const multi_span<OtherValueType, OtherDimensions...>& other) const + noexcept { return (other < *this); } template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> - constexpr bool - operator>=(const multi_span<OtherValueType, OtherDimensions...>& other) const noexcept + typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>, + std::remove_cv_t<OtherValueType>>::value>> + constexpr bool operator>=(const multi_span<OtherValueType, OtherDimensions...>& other) const { return !(*this < other); } @@ -1610,7 +1666,7 @@ constexpr auto as_multi_span(SpanType s, Dimensions2... dims) "Variadic as_multi_span() is for reshaping existing spans."); using BoundsType = typename multi_span<typename SpanType::value_type, (Dimensions2::value)...>::bounds_type; - auto tobounds = details::static_as_multi_span_helper<BoundsType>(dims..., details::Sep{}); + const auto tobounds = details::static_as_multi_span_helper<BoundsType>(dims..., details::Sep{}); details::verifyBoundsReshape(s.bounds(), tobounds); return {s.data(), tobounds}; } @@ -1641,8 +1697,7 @@ multi_span<byte> as_writeable_bytes(multi_span<U, Dimensions...> s) noexcept // on all implementations. It should be considered an experimental extension // to the standard GSL interface. template <typename U, std::ptrdiff_t... Dimensions> -constexpr auto -as_multi_span(multi_span<const byte, Dimensions...> s) -> multi_span< +constexpr auto as_multi_span(multi_span<const byte, Dimensions...> s) -> multi_span< const U, static_cast<std::ptrdiff_t>( multi_span<const byte, Dimensions...>::bounds_type::static_size != dynamic_range ? (static_cast<std::size_t>( @@ -1677,11 +1732,10 @@ constexpr auto as_multi_span(multi_span<byte, Dimensions...> s) : dynamic_range)> { using ByteSpan = multi_span<byte, Dimensions...>; - static_assert( - std::is_trivial<std::decay_t<U>>::value && - (ByteSpan::bounds_type::static_size == dynamic_range || - ByteSpan::bounds_type::static_size % sizeof(U) == 0), - "Target type must be a trivial type and its size must match the byte array size"); + static_assert(std::is_trivial<std::decay_t<U>>::value && + (ByteSpan::bounds_type::static_size == dynamic_range || + ByteSpan::bounds_type::static_size % sizeof(U) == 0), + "Target type must be a trivial type and its size must match the byte array size"); Expects((s.size_bytes() % sizeof(U)) == 0); return {reinterpret_cast<U*>(s.data()), @@ -1747,6 +1801,7 @@ constexpr auto as_multi_span(Cont&& arr) -> std::enable_if_t< // from basic_string which doesn't have nonconst .data() member like other contiguous containers template <typename CharT, typename Traits, typename Allocator> +GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute constexpr auto as_multi_span(std::basic_string<CharT, Traits, Allocator>& str) -> multi_span<CharT, dynamic_range> { @@ -1792,6 +1847,7 @@ public: Expects((bounds_.size() > 0 && ptr != nullptr) || bounds_.size() == 0); // Bounds cross data boundaries Expects(this->bounds().total_size() <= size); + GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive (void) size; } @@ -1799,8 +1855,7 @@ public: template <size_type N> constexpr strided_span(value_type (&values)[N], bounds_type bounds) : strided_span(values, N, std::move(bounds)) - { - } + {} // from array view template <typename OtherValueType, std::ptrdiff_t... Dimensions, @@ -1809,16 +1864,14 @@ public: typename = std::enable_if_t<Enabled1 && Enabled2>> constexpr strided_span(multi_span<OtherValueType, Dimensions...> av, bounds_type bounds) : strided_span(av.data(), av.bounds().total_size(), std::move(bounds)) - { - } + {} // convertible template <typename OtherValueType, typename = std::enable_if_t<std::is_convertible< OtherValueType (*)[], value_type (*)[]>::value>> constexpr strided_span(const strided_span<OtherValueType, Rank>& other) : data_(other.data_), bounds_(other.bounds_) - { - } + {} // convert from bytes template <typename OtherValueType> @@ -1832,7 +1885,7 @@ public: "OtherValueType should have a size to contain a multiple of ValueTypes"); auto d = narrow_cast<size_type>(sizeof(OtherValueType) / sizeof(value_type)); - size_type size = this->bounds().total_size() / d; + const size_type size = this->bounds().total_size() / d; return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())), size, bounds_type{resize_extent(this->bounds().index_bounds(), d), @@ -1841,17 +1894,19 @@ public: constexpr strided_span section(index_type origin, index_type extents) const { - size_type size = this->bounds().total_size() - this->bounds().linearize(origin); + const size_type size = this->bounds().total_size() - this->bounds().linearize(origin); return {&this->operator[](origin), size, bounds_type{extents, details::make_stride(bounds())}}; } + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr reference operator[](const index_type& idx) const { return data_[bounds_.linearize(idx)]; } template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>> + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr Ret operator[](size_type idx) const { Expects(idx < bounds_.size()); // index is out of bounds of the array @@ -1901,56 +1956,50 @@ public: constexpr const_reverse_iterator crend() const { return const_reverse_iterator{cbegin()}; } template <typename OtherValueType, std::ptrdiff_t OtherRank, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> - constexpr bool - operator==(const strided_span<OtherValueType, OtherRank>& other) const + typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>, + std::remove_cv_t<OtherValueType>>::value>> + constexpr bool operator==(const strided_span<OtherValueType, OtherRank>& other) const { return bounds_.size() == other.bounds_.size() && (data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin())); } template <typename OtherValueType, std::ptrdiff_t OtherRank, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> - constexpr bool - operator!=(const strided_span<OtherValueType, OtherRank>& other) const + typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>, + std::remove_cv_t<OtherValueType>>::value>> + constexpr bool operator!=(const strided_span<OtherValueType, OtherRank>& other) const { return !(*this == other); } template <typename OtherValueType, std::ptrdiff_t OtherRank, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> - constexpr bool - operator<(const strided_span<OtherValueType, OtherRank>& other) const + typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>, + std::remove_cv_t<OtherValueType>>::value>> + constexpr bool operator<(const strided_span<OtherValueType, OtherRank>& other) const { return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end()); } template <typename OtherValueType, std::ptrdiff_t OtherRank, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> - constexpr bool - operator<=(const strided_span<OtherValueType, OtherRank>& other) const + typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>, + std::remove_cv_t<OtherValueType>>::value>> + constexpr bool operator<=(const strided_span<OtherValueType, OtherRank>& other) const { return !(other < *this); } template <typename OtherValueType, std::ptrdiff_t OtherRank, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> - constexpr bool - operator>(const strided_span<OtherValueType, OtherRank>& other) const + typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>, + std::remove_cv_t<OtherValueType>>::value>> + constexpr bool operator>(const strided_span<OtherValueType, OtherRank>& other) const { return (other < *this); } template <typename OtherValueType, std::ptrdiff_t OtherRank, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> - constexpr bool - operator>=(const strided_span<OtherValueType, OtherRank>& other) const + typename = std::enable_if_t<std::is_same<std::remove_cv_t<value_type>, + std::remove_cv_t<OtherValueType>>::value>> + constexpr bool operator>=(const strided_span<OtherValueType, OtherRank>& other) const { return !(*this < other); } @@ -1959,6 +2008,7 @@ private: static index_type resize_extent(const index_type& extent, std::ptrdiff_t d) { // The last dimension of the array needs to contain a multiple of new type elements + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute Expects(extent[Rank - 1] >= d && (extent[Rank - 1] % d == 0)); index_type ret = extent; @@ -1971,12 +2021,14 @@ private: static index_type resize_stride(const index_type& strides, std::ptrdiff_t, void* = nullptr) { // Only strided arrays with regular strides can be resized + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute Expects(strides[Rank - 1] == 1); return strides; } template <bool Enabled = (Rank > 1), typename = std::enable_if_t<Enabled>> + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute static index_type resize_stride(const index_type& strides, std::ptrdiff_t d) { // Only strided arrays with regular strides can be resized @@ -1985,7 +2037,8 @@ private: // memory that can contain a multiple of new type elements Expects(strides[Rank - 2] >= d && (strides[Rank - 2] % d == 0)); - for (std::size_t i = Rank - 1; i > 0; --i) { + for (std::size_t i = Rank - 1; i > 0; --i) + { // Only strided arrays with regular strides can be resized Expects((strides[i - 1] >= strides[i]) && (strides[i - 1] % strides[i] == 0)); } @@ -2013,16 +2066,18 @@ private: pointer data_; const Span* m_validator; - void validateThis() const - { + + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + void validateThis() const { // iterator is out of range of the array Expects(data_ >= m_validator->data_ && data_ < m_validator->data_ + m_validator->size()); } + + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute contiguous_span_iterator(const Span* container, bool isbegin) : data_(isbegin ? container->data_ : container->data_ + container->size()) , m_validator(container) - { - } + {} public: reference operator*() const @@ -2035,6 +2090,8 @@ public: validateThis(); return data_; } + + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute contiguous_span_iterator& operator++() noexcept { ++data_; @@ -2046,6 +2103,8 @@ public: ++(*this); return ret; } + + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute contiguous_span_iterator& operator--() noexcept { --data_; @@ -2072,7 +2131,8 @@ public: contiguous_span_iterator ret{*this}; return ret -= n; } - contiguous_span_iterator& operator-=(difference_type n) noexcept { return *this += -n; } + + contiguous_span_iterator& operator-=(difference_type n) { return *this += -n; } difference_type operator-(const contiguous_span_iterator& rhs) const { Expects(m_validator == rhs.m_validator); @@ -2084,24 +2144,19 @@ public: Expects(m_validator == rhs.m_validator); return data_ == rhs.data_; } - bool operator!=(const contiguous_span_iterator& rhs) const - { - return !(*this == rhs); - } + + bool operator!=(const contiguous_span_iterator& rhs) const { return !(*this == rhs); } + bool operator<(const contiguous_span_iterator& rhs) const { Expects(m_validator == rhs.m_validator); return data_ < rhs.data_; } - bool operator<=(const contiguous_span_iterator& rhs) const - { - return !(rhs < *this); - } + + bool operator<=(const contiguous_span_iterator& rhs) const { return !(rhs < *this); } bool operator>(const contiguous_span_iterator& rhs) const { return rhs < *this; } - bool operator>=(const contiguous_span_iterator& rhs) const - { - return !(rhs > *this); - } + bool operator>=(const contiguous_span_iterator& rhs) const { return !(rhs > *this); } + void swap(contiguous_span_iterator& rhs) noexcept { std::swap(data_, rhs.data_); @@ -2117,8 +2172,7 @@ contiguous_span_iterator<Span> operator+(typename contiguous_span_iterator<Span> } template <typename Span> -class general_span_iterator -{ +class general_span_iterator { public: using iterator_category = std::random_access_iterator_tag; using value_type = typename Span::value_type; @@ -2135,8 +2189,7 @@ private: general_span_iterator(const Span* container, bool isbegin) : m_container(container) , m_itr(isbegin ? m_container->bounds().begin() : m_container->bounds().end()) - { - } + {} public: reference operator*() noexcept { return (*m_container)[*m_itr]; } @@ -2184,6 +2237,8 @@ public: Expects(m_container == rhs.m_container); return m_itr - rhs.m_itr; } + + GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute value_type operator[](difference_type n) const { return (*m_container)[m_itr[n]]; } bool operator==(const general_span_iterator& rhs) const @@ -2227,7 +2282,7 @@ general_span_iterator<Span> operator+(typename general_span_iterator<Span>::diff #endif // _MSC_VER -#if __GNUC__ > 6 +#if __GNUC__ > 6 #pragma GCC diagnostic pop #endif // __GNUC__ > 6 diff --git a/include/gsl/span b/include/gsl/span index 2fa9cc5..3e5a053 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -37,10 +37,9 @@ #pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4702) // unreachable code -// blanket turn off warnings from CppCoreCheck for now -// so people aren't annoyed by them when running the tool. -// more targeted suppressions will be added in a future update to the GSL -#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495) +// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. +#pragma warning(disable : 26495) // uninitalized member when constructor calls constructor +#pragma warning(disable : 26446) // parser bug does not allow attributes on some templates #if _MSC_VER < 1910 #pragma push_macro("constexpr") @@ -48,7 +47,7 @@ #define GSL_USE_STATIC_CONSTEXPR_WORKAROUND #endif // _MSC_VER < 1910 -#else // _MSC_VER +#endif // _MSC_VER // See if we have enough C++17 power to use a static constexpr data member // without needing an out-of-line definition @@ -56,12 +55,10 @@ #define GSL_USE_STATIC_CONSTEXPR_WORKAROUND #endif // !(defined(__cplusplus) && (__cplusplus >= 201703L)) -#endif // _MSC_VER - // GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t) -// While there is a conversion from signed to unsigned, it happens at -// compiletime, so the compiler wouldn't have to warn indiscriminently, but -// could check if the source value actually doesn't fit into the target type +// While there is a conversion from signed to unsigned, it happens at +// compiletime, so the compiler wouldn't have to warn indiscriminently, but +// could check if the source value actually doesn't fit into the target type // and only warn in those cases. #if __GNUC__ > 6 #pragma GCC diagnostic push @@ -129,7 +126,6 @@ namespace details using element_type_ = typename Span::element_type; public: - #ifdef _MSC_VER // Tell Microsoft standard library that span_iterators are checked. using _Unchecked_type = typename Span::pointer; @@ -146,15 +142,17 @@ namespace details constexpr span_iterator(const Span* span, typename Span::index_type idx) noexcept : span_(span), index_(idx) - {} + { + } friend span_iterator<Span, true>; - template<bool B, std::enable_if_t<!B && IsConst>* = nullptr> + template <bool B, std::enable_if_t<!B && IsConst>* = nullptr> constexpr span_iterator(const span_iterator<Span, B>& other) noexcept : span_iterator(other.span_, other.index_) { } + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr reference operator*() const { Expects(index_ != span_->size()); @@ -227,43 +225,34 @@ namespace details return index_ - rhs.index_; } - constexpr reference operator[](difference_type n) const - { - return *(*this + n); - } + constexpr reference operator[](difference_type n) const { return *(*this + n); } - constexpr friend bool operator==(span_iterator lhs, - span_iterator rhs) noexcept + constexpr friend bool operator==(span_iterator lhs, span_iterator rhs) noexcept { return lhs.span_ == rhs.span_ && lhs.index_ == rhs.index_; } - constexpr friend bool operator!=(span_iterator lhs, - span_iterator rhs) noexcept + constexpr friend bool operator!=(span_iterator lhs, span_iterator rhs) noexcept { return !(lhs == rhs); } - constexpr friend bool operator<(span_iterator lhs, - span_iterator rhs) noexcept + constexpr friend bool operator<(span_iterator lhs, span_iterator rhs) noexcept { return lhs.index_ < rhs.index_; } - constexpr friend bool operator<=(span_iterator lhs, - span_iterator rhs) noexcept + constexpr friend bool operator<=(span_iterator lhs, span_iterator rhs) noexcept { return !(rhs < lhs); } - constexpr friend bool operator>(span_iterator lhs, - span_iterator rhs) noexcept + constexpr friend bool operator>(span_iterator lhs, span_iterator rhs) noexcept { return rhs < lhs; } - constexpr friend bool operator>=(span_iterator lhs, - span_iterator rhs) noexcept + constexpr friend bool operator>=(span_iterator lhs, span_iterator rhs) noexcept { return !(rhs > lhs); } @@ -272,21 +261,21 @@ namespace details // MSVC++ iterator debugging support; allows STL algorithms in 15.8+ // to unwrap span_iterator to a pointer type after a range check in STL // algorithm calls - friend constexpr void _Verify_range(span_iterator lhs, - span_iterator rhs) noexcept - { // test that [lhs, rhs) forms a valid range inside an STL algorithm - Expects(lhs.span_ == rhs.span_ // range spans have to match - && lhs.index_ <= rhs.index_); // range must not be transposed + friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept + { // test that [lhs, rhs) forms a valid range inside an STL algorithm + Expects(lhs.span_ == rhs.span_ // range spans have to match + && lhs.index_ <= rhs.index_); // range must not be transposed } constexpr void _Verify_offset(const difference_type n) const noexcept - { // test that the iterator *this + n is a valid range in an STL + { // test that the iterator *this + n is a valid range in an STL // algorithm call Expects((index_ + n) >= 0 && (index_ + n) <= span_->size()); } + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr pointer _Unwrapped() const noexcept - { // after seeking *this to a high water mark, or using one of the + { // after seeking *this to a high water mark, or using one of the // _Verify_xxx functions above, unwrap this span_iterator to a raw // pointer return span_->data() + index_; @@ -299,8 +288,9 @@ namespace details #else static constexpr bool _Unwrap_when_unverified = false; #endif + GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive constexpr void _Seek_to(const pointer p) noexcept - { // adjust the position of *this to previously verified location p + { // adjust the position of *this to previously verified location p // after _Unwrapped index_ = p - span_->data(); } @@ -356,7 +346,9 @@ namespace details template <class ElementType, std::ptrdiff_t Extent, std::ptrdiff_t Offset, std::ptrdiff_t Count> struct calculate_subspan_type { - using type = span<ElementType, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : Extent)>; + using type = span<ElementType, Count != dynamic_extent + ? Count + : (Extent != dynamic_extent ? Extent - Offset : Extent)>; }; } // namespace details @@ -380,9 +372,9 @@ public: using size_type = index_type; #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) - static constexpr const index_type extent { Extent }; + static constexpr const index_type extent{Extent}; #else - static constexpr index_type extent { Extent }; + static constexpr index_type extent{Extent}; #endif // [span.cons], span constructors, copy, assignment, and destructor @@ -408,12 +400,14 @@ public: } template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>> + // GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug constexpr span(std::array<ArrayElementType, N>& arr) noexcept : storage_(&arr[0], details::extent_type<N>()) { } template <std::size_t N> + // GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug constexpr span(const std::array<std::remove_const_t<element_type>, N>& arr) noexcept : storage_(&arr[0], details::extent_type<N>()) { @@ -465,6 +459,7 @@ public: } template <std::ptrdiff_t Count> + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr span<element_type, Count> last() const { Expects(Count >= 0 && size() - Count >= 0); @@ -472,7 +467,9 @@ public: } template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent> - constexpr auto subspan() const -> typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + constexpr auto subspan() const -> + typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type { Expects((Offset >= 0 && size() - Offset >= 0) && (Count == dynamic_extent || (Count >= 0 && Offset + Count <= size()))); @@ -497,7 +494,6 @@ public: return make_subspan(offset, count, subspan_selector<Extent>{}); } - // [span.obs], span observers constexpr index_type size() const noexcept { return storage_.size(); } constexpr index_type size_bytes() const noexcept @@ -507,6 +503,7 @@ public: constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute constexpr reference operator[](index_type idx) const { Expects(idx >= 0 && idx < storage_.size()); @@ -527,17 +524,26 @@ public: constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; } - constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{cend()}; } - constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator{cbegin()}; } + constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator{cend()}; + } + constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator{cbegin()}; + } #ifdef _MSC_VER // Tell MSVC how to unwrap spans in range-based-for constexpr pointer _Unchecked_begin() const noexcept { return data(); } - constexpr pointer _Unchecked_end() const noexcept { return data() + size(); } + constexpr pointer _Unchecked_end() const noexcept + { + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + return data() + size(); + } #endif // _MSC_VER private: - // Needed to remove unnecessary null check in subspans struct KnownNotNull { @@ -554,17 +560,17 @@ private: // KnownNotNull parameter is needed to remove unnecessary null check // in subspans and constructors from arrays template <class OtherExtentType> - constexpr storage_type(KnownNotNull data, OtherExtentType ext) : ExtentType(ext), data_(data.p) + constexpr storage_type(KnownNotNull data, OtherExtentType ext) + : ExtentType(ext), data_(data.p) { - Expects(ExtentType::size() >= 0); + Expects(ExtentType::size() >= 0); } - template <class OtherExtentType> constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data) { - Expects(ExtentType::size() >= 0); - Expects(data || ExtentType::size() == 0); + Expects(ExtentType::size() >= 0); + Expects(data || ExtentType::size() == 0); } constexpr pointer data() const noexcept { return data_; } @@ -580,29 +586,28 @@ private: constexpr span(KnownNotNull ptr, index_type count) : storage_(ptr, count) {} template <std::ptrdiff_t CallerExtent> - class subspan_selector {}; + class subspan_selector + { + }; template <std::ptrdiff_t CallerExtent> - span<element_type, dynamic_extent> make_subspan(index_type offset, - index_type count, + span<element_type, dynamic_extent> make_subspan(index_type offset, index_type count, subspan_selector<CallerExtent>) const { - span<element_type, dynamic_extent> tmp(*this); + const span<element_type, dynamic_extent> tmp(*this); return tmp.subspan(offset, count); } - span<element_type, dynamic_extent> make_subspan(index_type offset, - index_type count, + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + span<element_type, dynamic_extent> make_subspan(index_type offset, index_type count, subspan_selector<dynamic_extent>) const { Expects(offset >= 0 && size() - offset >= 0); - if (count == dynamic_extent) - { - return { KnownNotNull{ data() + offset }, size() - offset }; - } + + if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; } Expects(count >= 0 && size() - offset >= count); - return { KnownNotNull{ data() + offset }, count }; + return {KnownNotNull{data() + offset}, count}; } }; @@ -611,46 +616,39 @@ template <class ElementType, std::ptrdiff_t Extent> constexpr const typename span<ElementType, Extent>::index_type span<ElementType, Extent>::extent; #endif - // [span.comparison], span comparison operators template <class ElementType, std::ptrdiff_t FirstExtent, std::ptrdiff_t SecondExtent> -constexpr bool operator==(span<ElementType, FirstExtent> l, - span<ElementType, SecondExtent> r) +constexpr bool operator==(span<ElementType, FirstExtent> l, span<ElementType, SecondExtent> r) { return std::equal(l.begin(), l.end(), r.begin(), r.end()); } template <class ElementType, std::ptrdiff_t Extent> -constexpr bool operator!=(span<ElementType, Extent> l, - span<ElementType, Extent> r) +constexpr bool operator!=(span<ElementType, Extent> l, span<ElementType, Extent> r) { return !(l == r); } template <class ElementType, std::ptrdiff_t Extent> -constexpr bool operator<(span<ElementType, Extent> l, - span<ElementType, Extent> r) +constexpr bool operator<(span<ElementType, Extent> l, span<ElementType, Extent> r) { return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); } template <class ElementType, std::ptrdiff_t Extent> -constexpr bool operator<=(span<ElementType, Extent> l, - span<ElementType, Extent> r) +constexpr bool operator<=(span<ElementType, Extent> l, span<ElementType, Extent> r) { return !(l > r); } template <class ElementType, std::ptrdiff_t Extent> -constexpr bool operator>(span<ElementType, Extent> l, - span<ElementType, Extent> r) +constexpr bool operator>(span<ElementType, Extent> l, span<ElementType, Extent> r) { return r < l; } template <class ElementType, std::ptrdiff_t Extent> -constexpr bool operator>=(span<ElementType, Extent> l, - span<ElementType, Extent> r) +constexpr bool operator>=(span<ElementType, Extent> l, span<ElementType, Extent> r) { return !(l < r); } @@ -676,13 +674,14 @@ namespace details : std::integral_constant<std::ptrdiff_t, dynamic_extent> { }; -} +} // namespace details // [span.objectrep], views of object representation template <class ElementType, std::ptrdiff_t Extent> span<const byte, details::calculate_byte_size<ElementType, Extent>::value> as_bytes(span<ElementType, Extent> s) noexcept { + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()}; } @@ -691,6 +690,7 @@ template <class ElementType, std::ptrdiff_t Extent, span<byte, details::calculate_byte_size<ElementType, Extent>::value> as_writeable_bytes(span<ElementType, Extent> s) noexcept { + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute return {reinterpret_cast<byte*>(s.data()), s.size_bytes()}; } @@ -698,7 +698,8 @@ as_writeable_bytes(span<ElementType, Extent> s) noexcept // make_span() - Utility functions for creating spans // template <class ElementType> -constexpr span<ElementType> make_span(ElementType* ptr, typename span<ElementType>::index_type count) +constexpr span<ElementType> make_span(ElementType* ptr, + typename span<ElementType>::index_type count) { return span<ElementType>(ptr, count); } @@ -759,7 +760,7 @@ constexpr ElementType& at(span<ElementType, Extent> s, index i) #pragma warning(pop) #endif // _MSC_VER -#if __GNUC__ > 6 +#if __GNUC__ > 6 #pragma GCC diagnostic pop #endif // __GNUC__ > 6 diff --git a/include/gsl/string_span b/include/gsl/string_span index 2a89561..d298039 100644 --- a/include/gsl/string_span +++ b/include/gsl/string_span @@ -20,6 +20,7 @@ #include <gsl/gsl_assert> // for Ensures, Expects #include <gsl/gsl_util> // for narrow_cast #include <gsl/span> // for operator!=, operator==, dynamic_extent +#include <gsl/pointers> // for not_null #include <algorithm> // for equal, lexicographical_compare #include <array> // for array @@ -32,10 +33,9 @@ #ifdef _MSC_VER #pragma warning(push) -// blanket turn off warnings from CppCoreCheck for now -// so people aren't annoyed by them when running the tool. -// more targeted suppressions will be added in a future update to the GSL -#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495) +// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. +#pragma warning(disable : 26446) // TODO: bug in parser - attributes and templates +#pragma warning(disable : 26481) // TODO: suppress does not work inside templates sometimes #if _MSC_VER < 1910 #pragma push_macro("constexpr") @@ -98,7 +98,7 @@ namespace details return len; } -} +} // namespace details // // ensure_sentinel() @@ -111,7 +111,13 @@ namespace details template <typename T, const T Sentinel> span<T, dynamic_extent> ensure_sentinel(T* seq, std::ptrdiff_t max = PTRDIFF_MAX) { + Ensures(seq != nullptr); + + GSL_SUPPRESS(f.23) // NO-FORMAT: attribute // TODO: false positive // TODO: suppress does not work auto cur = seq; + Ensures(cur != nullptr); // workaround for removing the warning + + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // TODO: suppress does not work while ((cur - seq) < max && *cur != Sentinel) ++cur; Ensures(*cur == Sentinel); return {seq, cur - seq}; @@ -131,21 +137,20 @@ span<CharT, dynamic_extent> ensure_z(CharT* const& sz, std::ptrdiff_t max = PTRD template <typename CharT, std::size_t N> span<CharT, dynamic_extent> ensure_z(CharT (&sz)[N]) { - return ensure_z(&sz[0], static_cast<std::ptrdiff_t>(N)); + return ensure_z(&sz[0], narrow_cast<std::ptrdiff_t>(N)); } template <class Cont> span<typename std::remove_pointer<typename Cont::pointer>::type, dynamic_extent> ensure_z(Cont& cont) { - return ensure_z(cont.data(), static_cast<std::ptrdiff_t>(cont.size())); + return ensure_z(cont.data(), narrow_cast<std::ptrdiff_t>(cont.size())); } template <typename CharT, std::ptrdiff_t> class basic_string_span; -namespace details -{ +namespace details { template <typename T> struct is_basic_string_span_oracle : std::false_type { @@ -160,7 +165,7 @@ namespace details struct is_basic_string_span : is_basic_string_span_oracle<std::remove_cv_t<T>> { }; -} +} // namespace details // // string_span and relatives @@ -197,32 +202,27 @@ public: // All other containers allow 0s within the length, so we do not remove them template <std::size_t N> constexpr basic_string_span(element_type (&arr)[N]) : span_(remove_z(arr)) - { - } + {} template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>> constexpr basic_string_span(std::array<ArrayElementType, N>& arr) noexcept : span_(arr) - { - } + {} template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>> - constexpr basic_string_span(const std::array<ArrayElementType, N>& arr) noexcept - : span_(arr) - { - } + constexpr basic_string_span(const std::array<ArrayElementType, N>& arr) noexcept : span_(arr) + {} // Container signature should work for basic_string after C++17 version exists template <class Traits, class Allocator> + // GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug constexpr basic_string_span(std::basic_string<element_type, Traits, Allocator>& str) : span_(&str[0], narrow_cast<std::ptrdiff_t>(str.length())) - { - } + {} template <class Traits, class Allocator> constexpr basic_string_span(const std::basic_string<element_type, Traits, Allocator>& str) : span_(&str[0], str.length()) - { - } + {} // from containers. Containers must have a pointer type and data() function signatures template <class Container, @@ -232,8 +232,7 @@ public: std::is_convertible<typename Container::pointer, decltype(std::declval<Container>().data())>::value>> constexpr basic_string_span(Container& cont) : span_(cont) - { - } + {} template <class Container, class = std::enable_if_t< @@ -242,8 +241,7 @@ public: std::is_convertible<typename Container::pointer, decltype(std::declval<Container>().data())>::value>> constexpr basic_string_span(const Container& cont) : span_(cont) - { - } + {} // from string_span template < @@ -252,8 +250,7 @@ public: typename basic_string_span<OtherValueType, OtherExtent>::impl_type, impl_type>::value>> constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other) : span_(other.data(), other.length()) - { - } + {} template <index_type Count> constexpr basic_string_span<element_type, Count> first() const @@ -359,21 +356,22 @@ template <typename CharT, std::ptrdiff_t Extent> std::basic_string<typename std::remove_const<CharT>::type> to_string(basic_string_span<CharT, Extent> view) { - return {view.data(), static_cast<std::size_t>(view.length())}; + return {view.data(), narrow_cast<std::size_t>(view.length())}; } template <typename CharT, typename Traits = typename std::char_traits<CharT>, typename Allocator = std::allocator<CharT>, typename gCharT, std::ptrdiff_t Extent> std::basic_string<CharT, Traits, Allocator> to_basic_string(basic_string_span<gCharT, Extent> view) { - return {view.data(), static_cast<std::size_t>(view.length())}; + return {view.data(), narrow_cast<std::size_t>(view.length())}; } template <class ElementType, std::ptrdiff_t Extent> basic_string_span<const byte, details::calculate_byte_size<ElementType, Extent>::value> as_bytes(basic_string_span<ElementType, Extent> s) noexcept { - return { reinterpret_cast<const byte*>(s.data()), s.size_bytes() }; + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()}; } template <class ElementType, std::ptrdiff_t Extent, @@ -381,14 +379,14 @@ template <class ElementType, std::ptrdiff_t Extent, basic_string_span<byte, details::calculate_byte_size<ElementType, Extent>::value> as_writeable_bytes(basic_string_span<ElementType, Extent> s) noexcept { + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute return {reinterpret_cast<byte*>(s.data()), s.size_bytes()}; } // zero-terminated string span, used to convert // zero-terminated spans to legacy strings template <typename CharT, std::ptrdiff_t Extent = dynamic_extent> -class basic_zstring_span -{ +class basic_zstring_span { public: using value_type = CharT; using const_value_type = std::add_const_t<CharT>; @@ -424,10 +422,10 @@ public: constexpr string_span_type as_string_span() const noexcept { - auto sz = span_.size(); - return { span_.data(), sz > 1 ? sz - 1 : 0 }; + const auto sz = span_.size(); + return {span_.data(), sz > 1 ? sz - 1 : 0}; } - constexpr string_span_type ensure_z() const noexcept { return gsl::ensure_z(span_); } + constexpr string_span_type ensure_z() const { return gsl::ensure_z(span_); } constexpr const_zstring_type assume_z() const noexcept { return span_.data(); } @@ -464,7 +462,7 @@ template <class CharT, std::ptrdiff_t Extent, class T, class = std::enable_if_t< details::is_basic_string_span<T>::value || std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>>>::value>> -bool operator==(const gsl::basic_string_span<CharT, Extent>& one, const T& other) noexcept +bool operator==(const gsl::basic_string_span<CharT, Extent>& one, const T& other) { const gsl::basic_string_span<std::add_const_t<CharT>> tmp(other); return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end()); @@ -474,9 +472,9 @@ template <class CharT, std::ptrdiff_t Extent, class T, class = std::enable_if_t< !details::is_basic_string_span<T>::value && std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>>>::value>> -bool operator==(const T& one, const gsl::basic_string_span<CharT, Extent>& other) noexcept +bool operator==(const T& one, const gsl::basic_string_span<CharT, Extent>& other) { - gsl::basic_string_span<std::add_const_t<CharT>> tmp(one); + const gsl::basic_string_span<std::add_const_t<CharT>> tmp(one); return std::equal(tmp.begin(), tmp.end(), other.begin(), other.end()); } @@ -484,7 +482,7 @@ bool operator==(const T& one, const gsl::basic_string_span<CharT, Extent>& other template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, typename = std::enable_if_t<std::is_convertible< T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> -bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept +bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other) { return !(one == other); } @@ -494,7 +492,7 @@ template < typename = std::enable_if_t< std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && !gsl::details::is_basic_string_span<T>::value>> -bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept +bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) { return !(one == other); } @@ -503,7 +501,7 @@ bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, typename = std::enable_if_t<std::is_convertible< T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> -bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept +bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) { const gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other); return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); @@ -514,7 +512,7 @@ template < typename = std::enable_if_t< std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && !gsl::details::is_basic_string_span<T>::value>> -bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept +bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) { gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one); return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end()); @@ -533,7 +531,7 @@ template < std::is_convertible<DataType*, CharT*>::value && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>> -bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept +bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) { gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other); return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); @@ -547,7 +545,7 @@ template < std::is_convertible<DataType*, CharT*>::value && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>> -bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept +bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) { gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one); return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end()); @@ -558,7 +556,7 @@ bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) noexce template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, typename = std::enable_if_t<std::is_convertible< T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> -bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept +bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) { return !(other < one); } @@ -568,7 +566,7 @@ template < typename = std::enable_if_t< std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && !gsl::details::is_basic_string_span<T>::value>> -bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept +bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) { return !(other < one); } @@ -586,7 +584,7 @@ template < std::is_convertible<DataType*, CharT*>::value && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>> -bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept +bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) { return !(other < one); } @@ -599,7 +597,7 @@ template < std::is_convertible<DataType*, CharT*>::value && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>> -bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept +bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) { return !(other < one); } @@ -609,7 +607,7 @@ bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, typename = std::enable_if_t<std::is_convertible< T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> -bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept +bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) { return other < one; } @@ -619,7 +617,7 @@ template < typename = std::enable_if_t< std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && !gsl::details::is_basic_string_span<T>::value>> -bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept +bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) { return other < one; } @@ -637,7 +635,7 @@ template < std::is_convertible<DataType*, CharT*>::value && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>> -bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept +bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) { return other < one; } @@ -650,7 +648,7 @@ template < std::is_convertible<DataType*, CharT*>::value && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>> -bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept +bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) { return other < one; } @@ -660,7 +658,7 @@ bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexce template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, typename = std::enable_if_t<std::is_convertible< T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> -bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept +bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) { return !(one < other); } @@ -670,7 +668,7 @@ template < typename = std::enable_if_t< std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && !gsl::details::is_basic_string_span<T>::value>> -bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept +bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) { return !(one < other); } @@ -688,7 +686,7 @@ template < std::is_convertible<DataType*, CharT*>::value && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>> -bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept +bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) { return !(one < other); } @@ -701,7 +699,7 @@ template < std::is_convertible<DataType*, CharT*>::value && std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>> -bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept +bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) { return !(one < other); } |