aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAnna Gringauze <annagrin@microsoft.com>2018-08-12 21:44:17 -0700
committerNeil MacIntosh <neilmac@fb.com>2018-08-12 21:44:17 -0700
commitcea0d0ac2bd775f0fb4c7e357a089979370ae3cd (patch)
treefaa0e678f606971b55ef795d507d613d40e93de2 /include
parent6a75903c79ff7109c24d281372005b622a9d9177 (diff)
downloadplatform_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_algorithm8
-rw-r--r--include/gsl/gsl_assert21
-rw-r--r--include/gsl/gsl_byte25
-rw-r--r--include/gsl/gsl_util40
-rw-r--r--include/gsl/multi_span441
-rw-r--r--include/gsl/span157
-rw-r--r--include/gsl/string_span112
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);
}