Merge branch 'master' into hunterization

This commit is contained in:
Stefan Reinhold 2018-09-07 17:27:31 +02:00
commit 8428e083e4
28 changed files with 1534 additions and 719 deletions

View File

@ -5,7 +5,19 @@ IndentWidth: 4
AccessModifierOffset: -4 AccessModifierOffset: -4
NamespaceIndentation: Inner NamespaceIndentation: Inner
BreakBeforeBraces: Allman BreakBeforeBraces: Custom
BraceWrapping:
AfterNamespace: true
AfterEnum: true
AfterStruct: true
AfterClass: true
SplitEmptyFunction: false
AfterControlStatement: true
AfterFunction: true
AfterUnion: true
BeforeElse: true
AlwaysBreakTemplateDeclarations: true AlwaysBreakTemplateDeclarations: true
BreakConstructorInitializersBeforeComma: true BreakConstructorInitializersBeforeComma: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true
@ -19,3 +31,4 @@ AlignConsecutiveAssignments: false
AlignTrailingComments: true AlignTrailingComments: true
SpaceAfterCStyleCast: true SpaceAfterCStyleCast: true
CommentPragmas: '^ NO-FORMAT:'

18
CMakeSettings.json Normal file
View File

@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [
"msvc_x64_x64"
],
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
"cmakeCommandArgs": "-DGSL_CXX_STANDARD=17",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"codeAnalysisRuleset": "CppCoreCheckRules.ruleset"
}
]
}

View File

@ -31,15 +31,12 @@
#pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4996) // unsafe use of std::copy_n #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 #endif // _MSC_VER
namespace gsl 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, template <class SrcElementType, std::ptrdiff_t SrcExtent, class DestElementType,
std::ptrdiff_t DestExtent> std::ptrdiff_t DestExtent>
void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest) 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"); "Source range is longer than target range");
Expects(dest.size() >= src.size()); Expects(dest.size() >= src.size());
GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute
std::copy_n(src.data(), src.size(), dest.data()); std::copy_n(src.data(), src.size(), dest.data());
} }

View File

@ -20,12 +20,28 @@
#include <exception> #include <exception>
#include <stdexcept> // for logic_error #include <stdexcept> // for logic_error
//
// make suppress attributes parse 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
// //
// Temporary until MSVC STL supports no-exceptions mode. // Temporary until MSVC STL supports no-exceptions mode.
// Currently terminate is a no-op in this mode, so we add termination behavior back // Currently terminate is a no-op in this mode, so we add termination behavior back
// //
#if defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS #if defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND #define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
#include <intrin.h>
#define RANGE_CHECKS_FAILURE 0
#endif #endif
// //
@ -83,9 +99,15 @@ namespace details
typedef void (__cdecl *terminate_handler)(); typedef void (__cdecl *terminate_handler)();
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute
[[noreturn]] inline void __cdecl default_terminate_handler()
{
__fastfail(RANGE_CHECKS_FAILURE);
}
inline gsl::details::terminate_handler& get_terminate_handler() noexcept inline gsl::details::terminate_handler& get_terminate_handler() noexcept
{ {
static terminate_handler handler = &abort; static terminate_handler handler = &default_terminate_handler;
return handler; return handler;
} }
@ -103,7 +125,7 @@ namespace details
#if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) #if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
template <typename Exception> template <typename Exception>
[[noreturn]] void throw_exception(Exception&&) [[noreturn]] void throw_exception(Exception&&) noexcept
{ {
gsl::details::terminate(); gsl::details::terminate();
} }

View File

@ -17,14 +17,28 @@
#ifndef GSL_BYTE_H #ifndef GSL_BYTE_H
#define 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> #include <type_traits>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
// don't warn about function style casts in byte related operators // Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
#pragma warning(disable : 26493) #pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates does not always work
#ifndef GSL_USE_STD_BYTE #ifndef GSL_USE_STD_BYTE
// this tests if we are under MSVC and the standard lib has std::byte and it is enabled // this tests if we are under MSVC and the standard lib has std::byte and it is enabled
@ -43,16 +57,23 @@
#ifndef GSL_USE_STD_BYTE #ifndef GSL_USE_STD_BYTE
// this tests if we are under GCC or Clang with enough -std:c++1z power to get us std::byte // this tests if we are under GCC or Clang with enough -std:c++1z power to get us std::byte
#if defined(__cplusplus) && (__cplusplus >= 201703L) // also check if libc++ version is sufficient (> 5.0) or libstc++ actually contains std::byte
#if defined(__cplusplus) && (__cplusplus >= 201703L) && \
(defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \
defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#define GSL_USE_STD_BYTE 1 #define GSL_USE_STD_BYTE 1
#include <cstddef> #include <cstddef>
#else // defined(__cplusplus) && (__cplusplus >= 201703L) #else // defined(__cplusplus) && (__cplusplus >= 201703L) &&
// (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
// defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#define GSL_USE_STD_BYTE 0 #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 // GSL_USE_STD_BYTE
#endif // _MSC_VER #endif // _MSC_VER
@ -68,7 +89,6 @@ namespace gsl
{ {
#if GSL_USE_STD_BYTE #if GSL_USE_STD_BYTE
using std::byte; using std::byte;
using std::to_integer; using std::to_integer;
@ -153,6 +173,8 @@ constexpr byte to_byte_impl(T t) noexcept
return static_cast<byte>(t); return static_cast<byte>(t);
} }
template <> 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 constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept
{ {
return byte(t); return byte(t);

View File

@ -62,6 +62,7 @@ public:
final_action& operator=(const final_action&) = delete; final_action& operator=(const final_action&) = delete;
final_action& operator=(final_action&&) = delete; final_action& operator=(final_action&&) = delete;
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws
~final_action() noexcept ~final_action() noexcept
{ {
if (invoke_) f_(); if (invoke_) f_();
@ -69,12 +70,11 @@ public:
private: private:
F f_; F f_;
bool invoke_ {true}; bool invoke_{true};
}; };
// finally() - convenience function to generate a final_action // finally() - convenience function to generate a final_action
template <class F> template <class F>
final_action<F> finally(const F& f) noexcept final_action<F> finally(const F& f) noexcept
{ {
return final_action<F>(f); return final_action<F>(f);
@ -88,6 +88,7 @@ final_action<F> finally(F&& f) noexcept
// narrow_cast(): a searchable way to do narrowing casts of values // narrow_cast(): a searchable way to do narrowing casts of values
template <class T, class U> template <class T, class U>
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
constexpr T narrow_cast(U&& u) noexcept constexpr T narrow_cast(U&& u) noexcept
{ {
return static_cast<T>(std::forward<U>(u)); return static_cast<T>(std::forward<U>(u));
@ -104,11 +105,13 @@ namespace details
: public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value> : 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 // narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template <class T, class U> template <class T, class U>
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); T t = narrow_cast<T>(u);
if (static_cast<U>(t) != u) gsl::details::throw_exception(narrowing_error()); if (static_cast<U>(t) != u) gsl::details::throw_exception(narrowing_error());
@ -121,21 +124,26 @@ T narrow(U u)
// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector // at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector
// //
template <class T, std::size_t N> template <class T, std::size_t N>
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
constexpr T& at(T (&arr)[N], const index i) constexpr T& at(T (&arr)[N], const index i)
{ {
Expects(i >= 0 && i < narrow_cast<index>(N)); 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> template <class Cont>
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()]) constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()])
{ {
Expects(i >= 0 && i < narrow_cast<index>(cont.size())); Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
using size_type = decltype(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> template <class T>
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
constexpr T at(const std::initializer_list<T> cont, const index i) constexpr T at(const std::initializer_list<T> cont, const index i)
{ {
Expects(i >= 0 && i < narrow_cast<index>(cont.size())); Expects(i >= 0 && i < narrow_cast<index>(cont.size()));

File diff suppressed because it is too large Load Diff

View File

@ -119,6 +119,11 @@ private:
T ptr_; T ptr_;
}; };
template <class T>
auto make_not_null(T&& t) {
return gsl::not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
}
template <class T> template <class T>
std::ostream& operator<<(std::ostream& os, const not_null<T>& val) std::ostream& operator<<(std::ostream& os, const not_null<T>& val)
{ {

View File

@ -29,6 +29,7 @@
#include <stdexcept> #include <stdexcept>
#include <type_traits> // for enable_if_t, declval, is_convertible, inte... #include <type_traits> // for enable_if_t, declval, is_convertible, inte...
#include <utility> #include <utility>
#include <memory> // for std::addressof
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
@ -37,10 +38,9 @@
#pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4702) // unreachable code #pragma warning(disable : 4702) // unreachable code
// blanket turn off warnings from CppCoreCheck for now // Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
// so people aren't annoyed by them when running the tool. #pragma warning(disable : 26495) // uninitalized member when constructor calls constructor
// more targeted suppressions will be added in a future update to the GSL #pragma warning(disable : 26446) // parser bug does not allow attributes on some templates
#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#pragma push_macro("constexpr") #pragma push_macro("constexpr")
@ -48,7 +48,7 @@
#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND #define GSL_USE_STATIC_CONSTEXPR_WORKAROUND
#endif // _MSC_VER < 1910 #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 // See if we have enough C++17 power to use a static constexpr data member
// without needing an out-of-line definition // without needing an out-of-line definition
@ -56,8 +56,6 @@
#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND #define GSL_USE_STATIC_CONSTEXPR_WORKAROUND
#endif // !(defined(__cplusplus) && (__cplusplus >= 201703L)) #endif // !(defined(__cplusplus) && (__cplusplus >= 201703L))
#endif // _MSC_VER
// GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t) // 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 // While there is a conversion from signed to unsigned, it happens at
// compiletime, so the compiler wouldn't have to warn indiscriminently, but // compiletime, so the compiler wouldn't have to warn indiscriminently, but
@ -129,7 +127,6 @@ namespace details
using element_type_ = typename Span::element_type; using element_type_ = typename Span::element_type;
public: public:
#ifdef _MSC_VER #ifdef _MSC_VER
// Tell Microsoft standard library that span_iterators are checked. // Tell Microsoft standard library that span_iterators are checked.
using _Unchecked_type = typename Span::pointer; using _Unchecked_type = typename Span::pointer;
@ -149,12 +146,12 @@ namespace details
{} {}
friend span_iterator<Span, true>; 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 constexpr span_iterator(const span_iterator<Span, B>& other) noexcept
: span_iterator(other.span_, other.index_) : span_iterator(other.span_, other.index_)
{ {}
}
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
constexpr reference operator*() const constexpr reference operator*() const
{ {
Expects(index_ != span_->size()); Expects(index_ != span_->size());
@ -227,43 +224,34 @@ namespace details
return index_ - rhs.index_; return index_ - rhs.index_;
} }
constexpr reference operator[](difference_type n) const constexpr reference operator[](difference_type n) const { return *(*this + n); }
{
return *(*this + n);
}
constexpr friend bool operator==(span_iterator lhs, constexpr friend bool operator==(span_iterator lhs, span_iterator rhs) noexcept
span_iterator rhs) noexcept
{ {
return lhs.span_ == rhs.span_ && lhs.index_ == rhs.index_; return lhs.span_ == rhs.span_ && lhs.index_ == rhs.index_;
} }
constexpr friend bool operator!=(span_iterator lhs, constexpr friend bool operator!=(span_iterator lhs, span_iterator rhs) noexcept
span_iterator rhs) noexcept
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
constexpr friend bool operator<(span_iterator lhs, constexpr friend bool operator<(span_iterator lhs, span_iterator rhs) noexcept
span_iterator rhs) noexcept
{ {
return lhs.index_ < rhs.index_; return lhs.index_ < rhs.index_;
} }
constexpr friend bool operator<=(span_iterator lhs, constexpr friend bool operator<=(span_iterator lhs, span_iterator rhs) noexcept
span_iterator rhs) noexcept
{ {
return !(rhs < lhs); return !(rhs < lhs);
} }
constexpr friend bool operator>(span_iterator lhs, constexpr friend bool operator>(span_iterator lhs, span_iterator rhs) noexcept
span_iterator rhs) noexcept
{ {
return rhs < lhs; return rhs < lhs;
} }
constexpr friend bool operator>=(span_iterator lhs, constexpr friend bool operator>=(span_iterator lhs, span_iterator rhs) noexcept
span_iterator rhs) noexcept
{ {
return !(rhs > lhs); return !(rhs > lhs);
} }
@ -272,8 +260,7 @@ namespace details
// MSVC++ iterator debugging support; allows STL algorithms in 15.8+ // MSVC++ iterator debugging support; allows STL algorithms in 15.8+
// to unwrap span_iterator to a pointer type after a range check in STL // to unwrap span_iterator to a pointer type after a range check in STL
// algorithm calls // algorithm calls
friend constexpr void _Verify_range(span_iterator lhs, friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept
span_iterator rhs) noexcept
{ // test that [lhs, rhs) forms a valid range inside an STL algorithm { // test that [lhs, rhs) forms a valid range inside an STL algorithm
Expects(lhs.span_ == rhs.span_ // range spans have to match Expects(lhs.span_ == rhs.span_ // range spans have to match
&& lhs.index_ <= rhs.index_); // range must not be transposed && lhs.index_ <= rhs.index_); // range must not be transposed
@ -285,6 +272,7 @@ namespace details
Expects((index_ + n) >= 0 && (index_ + n) <= span_->size()); Expects((index_ + n) >= 0 && (index_ + n) <= span_->size());
} }
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
constexpr pointer _Unwrapped() const noexcept 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 // _Verify_xxx functions above, unwrap this span_iterator to a raw
@ -299,6 +287,7 @@ namespace details
#else #else
static constexpr bool _Unwrap_when_unverified = false; static constexpr bool _Unwrap_when_unverified = false;
#endif #endif
GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive
constexpr void _Seek_to(const pointer p) noexcept 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 // after _Unwrapped
@ -342,8 +331,7 @@ namespace details
template <index_type Other> template <index_type Other>
explicit constexpr extent_type(extent_type<Other> ext) : size_(ext.size()) explicit constexpr extent_type(extent_type<Other> ext) : size_(ext.size())
{ {}
}
explicit constexpr extent_type(index_type size) : size_(size) { Expects(size >= 0); } explicit constexpr extent_type(index_type size) : size_(size) { Expects(size >= 0); }
@ -356,7 +344,9 @@ namespace details
template <class ElementType, std::ptrdiff_t Extent, std::ptrdiff_t Offset, std::ptrdiff_t Count> template <class ElementType, std::ptrdiff_t Extent, std::ptrdiff_t Offset, std::ptrdiff_t Count>
struct calculate_subspan_type 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 } // namespace details
@ -380,9 +370,9 @@ public:
using size_type = index_type; using size_type = index_type;
#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
static constexpr const index_type extent { Extent }; static constexpr const index_type extent{Extent};
#else #else
static constexpr index_type extent { Extent }; static constexpr index_type extent{Extent};
#endif #endif
// [span.cons], span constructors, copy, assignment, and destructor // [span.cons], span constructors, copy, assignment, and destructor
@ -391,33 +381,30 @@ public:
// since "std::enable_if_t<Extent <= 0>" is ill-formed when Extent is greater than 0. // since "std::enable_if_t<Extent <= 0>" is ill-formed when Extent is greater than 0.
class = std::enable_if_t<(Dependent || Extent <= 0)>> class = std::enable_if_t<(Dependent || Extent <= 0)>>
constexpr span() noexcept : storage_(nullptr, details::extent_type<0>()) constexpr span() noexcept : storage_(nullptr, details::extent_type<0>())
{ {}
}
constexpr span(pointer ptr, index_type count) : storage_(ptr, count) {} constexpr span(pointer ptr, index_type count) : storage_(ptr, count) {}
constexpr span(pointer firstElem, pointer lastElem) constexpr span(pointer firstElem, pointer lastElem)
: storage_(firstElem, std::distance(firstElem, lastElem)) : storage_(firstElem, std::distance(firstElem, lastElem))
{ {}
}
template <std::size_t N> template <std::size_t N>
constexpr span(element_type (&arr)[N]) noexcept constexpr span(element_type (&arr)[N]) noexcept
: storage_(KnownNotNull{&arr[0]}, details::extent_type<N>()) : storage_(KnownNotNull{std::addressof(arr[0])}, details::extent_type<N>())
{ {}
}
template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>> 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 constexpr span(std::array<ArrayElementType, N>& arr) noexcept
: storage_(&arr[0], details::extent_type<N>()) : storage_(arr.data(), details::extent_type<N>())
{ {}
}
template <std::size_t 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 constexpr span(const std::array<std::remove_const_t<element_type>, N>& arr) noexcept
: storage_(&arr[0], details::extent_type<N>()) : storage_(arr.data(), details::extent_type<N>())
{ {}
}
// NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement // NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement
// on Container to be a contiguous sequence container. // on Container to be a contiguous sequence container.
@ -428,8 +415,7 @@ public:
std::is_convertible<typename Container::pointer, std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>> decltype(std::declval<Container>().data())>::value>>
constexpr span(Container& cont) : span(cont.data(), narrow<index_type>(cont.size())) constexpr span(Container& cont) : span(cont.data(), narrow<index_type>(cont.size()))
{ {}
}
template <class Container, template <class Container,
class = std::enable_if_t< class = std::enable_if_t<
@ -438,8 +424,7 @@ public:
std::is_convertible<typename Container::pointer, std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>> decltype(std::declval<Container>().data())>::value>>
constexpr span(const Container& cont) : span(cont.data(), narrow<index_type>(cont.size())) constexpr span(const Container& cont) : span(cont.data(), narrow<index_type>(cont.size()))
{ {}
}
constexpr span(const span& other) noexcept = default; constexpr span(const span& other) noexcept = default;
@ -450,8 +435,7 @@ public:
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value>> details::is_allowed_element_type_conversion<OtherElementType, element_type>::value>>
constexpr span(const span<OtherElementType, OtherExtent>& other) constexpr span(const span<OtherElementType, OtherExtent>& other)
: storage_(other.data(), details::extent_type<OtherExtent>(other.size())) : storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
{ {}
}
~span() noexcept = default; ~span() noexcept = default;
constexpr span& operator=(const span& other) noexcept = default; constexpr span& operator=(const span& other) noexcept = default;
@ -465,6 +449,7 @@ public:
} }
template <std::ptrdiff_t Count> template <std::ptrdiff_t Count>
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
constexpr span<element_type, Count> last() const constexpr span<element_type, Count> last() const
{ {
Expects(Count >= 0 && size() - Count >= 0); Expects(Count >= 0 && size() - Count >= 0);
@ -472,7 +457,9 @@ public:
} }
template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent> 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) && Expects((Offset >= 0 && size() - Offset >= 0) &&
(Count == dynamic_extent || (Count >= 0 && Offset + Count <= size()))); (Count == dynamic_extent || (Count >= 0 && Offset + Count <= size())));
@ -497,7 +484,6 @@ public:
return make_subspan(offset, count, subspan_selector<Extent>{}); return make_subspan(offset, count, subspan_selector<Extent>{});
} }
// [span.obs], span observers // [span.obs], span observers
constexpr index_type size() const noexcept { return storage_.size(); } constexpr index_type size() const noexcept { return storage_.size(); }
constexpr index_type size_bytes() const noexcept constexpr index_type size_bytes() const noexcept
@ -507,9 +493,10 @@ public:
constexpr bool empty() const noexcept { return size() == 0; } constexpr bool empty() const noexcept { return size() == 0; }
// [span.elem], span element access // [span.elem], span element access
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
constexpr reference operator[](index_type idx) const constexpr reference operator[](index_type idx) const
{ {
Expects(idx >= 0 && idx < storage_.size()); Expects(CheckRange(idx, storage_.size()));
return data()[idx]; return data()[idx];
} }
@ -527,16 +514,47 @@ public:
constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }
constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; } 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 crbegin() const noexcept
constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator{cbegin()}; } {
return const_reverse_iterator{cend()};
}
constexpr const_reverse_iterator crend() const noexcept
{
return const_reverse_iterator{cbegin()};
}
#ifdef _MSC_VER #ifdef _MSC_VER
// Tell MSVC how to unwrap spans in range-based-for // Tell MSVC how to unwrap spans in range-based-for
constexpr pointer _Unchecked_begin() const noexcept { return data(); } 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 #endif // _MSC_VER
private: private:
static bool CheckRange(index_type idx, index_type size)
{
// Optimization:
//
// idx >= 0 && idx < size
// =>
// static_cast<size_t>(idx) < static_cast<size_t>(size)
//
// because size >=0 by span construction, and negative idx will
// wrap around to a value always greater than size when casted.
// check if we have enough space to wrap around
if (sizeof(index_type) <= sizeof(size_t))
{
return narrow_cast<size_t>(idx) < narrow_cast<size_t>(size);
}
else
{
return idx >= 0 && idx < size;
}
}
// Needed to remove unnecessary null check in subspans // Needed to remove unnecessary null check in subspans
struct KnownNotNull struct KnownNotNull
@ -554,12 +572,12 @@ private:
// KnownNotNull parameter is needed to remove unnecessary null check // KnownNotNull parameter is needed to remove unnecessary null check
// in subspans and constructors from arrays // in subspans and constructors from arrays
template <class OtherExtentType> 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> template <class OtherExtentType>
constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data) constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data)
{ {
@ -580,29 +598,28 @@ private:
constexpr span(KnownNotNull ptr, index_type count) : storage_(ptr, count) {} constexpr span(KnownNotNull ptr, index_type count) : storage_(ptr, count) {}
template <std::ptrdiff_t CallerExtent> template <std::ptrdiff_t CallerExtent>
class subspan_selector {}; class subspan_selector
{
};
template <std::ptrdiff_t CallerExtent> template <std::ptrdiff_t CallerExtent>
span<element_type, dynamic_extent> make_subspan(index_type offset, span<element_type, dynamic_extent> make_subspan(index_type offset, index_type count,
index_type count,
subspan_selector<CallerExtent>) const subspan_selector<CallerExtent>) const
{ {
span<element_type, dynamic_extent> tmp(*this); const span<element_type, dynamic_extent> tmp(*this);
return tmp.subspan(offset, count); return tmp.subspan(offset, count);
} }
span<element_type, dynamic_extent> make_subspan(index_type offset, GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
index_type count, span<element_type, dynamic_extent> make_subspan(index_type offset, index_type count,
subspan_selector<dynamic_extent>) const subspan_selector<dynamic_extent>) const
{ {
Expects(offset >= 0 && size() - offset >= 0); Expects(offset >= 0 && size() - offset >= 0);
if (count == dynamic_extent)
{ if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; }
return { KnownNotNull{ data() + offset }, size() - offset };
}
Expects(count >= 0 && size() - offset >= count); Expects(count >= 0 && size() - offset >= count);
return { KnownNotNull{ data() + offset }, count }; return {KnownNotNull{data() + offset}, count};
} }
}; };
@ -611,46 +628,39 @@ template <class ElementType, std::ptrdiff_t Extent>
constexpr const typename span<ElementType, Extent>::index_type span<ElementType, Extent>::extent; constexpr const typename span<ElementType, Extent>::index_type span<ElementType, Extent>::extent;
#endif #endif
// [span.comparison], span comparison operators // [span.comparison], span comparison operators
template <class ElementType, std::ptrdiff_t FirstExtent, std::ptrdiff_t SecondExtent> template <class ElementType, std::ptrdiff_t FirstExtent, std::ptrdiff_t SecondExtent>
constexpr bool operator==(span<ElementType, FirstExtent> l, constexpr bool operator==(span<ElementType, FirstExtent> l, span<ElementType, SecondExtent> r)
span<ElementType, SecondExtent> r)
{ {
return std::equal(l.begin(), l.end(), r.begin(), r.end()); return std::equal(l.begin(), l.end(), r.begin(), r.end());
} }
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
constexpr bool operator!=(span<ElementType, Extent> l, constexpr bool operator!=(span<ElementType, Extent> l, span<ElementType, Extent> r)
span<ElementType, Extent> r)
{ {
return !(l == r); return !(l == r);
} }
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
constexpr bool operator<(span<ElementType, Extent> l, constexpr bool operator<(span<ElementType, Extent> l, span<ElementType, Extent> r)
span<ElementType, Extent> r)
{ {
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
} }
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
constexpr bool operator<=(span<ElementType, Extent> l, constexpr bool operator<=(span<ElementType, Extent> l, span<ElementType, Extent> r)
span<ElementType, Extent> r)
{ {
return !(l > r); return !(l > r);
} }
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
constexpr bool operator>(span<ElementType, Extent> l, constexpr bool operator>(span<ElementType, Extent> l, span<ElementType, Extent> r)
span<ElementType, Extent> r)
{ {
return r < l; return r < l;
} }
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
constexpr bool operator>=(span<ElementType, Extent> l, constexpr bool operator>=(span<ElementType, Extent> l, span<ElementType, Extent> r)
span<ElementType, Extent> r)
{ {
return !(l < r); return !(l < r);
} }
@ -676,13 +686,14 @@ namespace details
: std::integral_constant<std::ptrdiff_t, dynamic_extent> : std::integral_constant<std::ptrdiff_t, dynamic_extent>
{ {
}; };
} } // namespace details
// [span.objectrep], views of object representation // [span.objectrep], views of object representation
template <class ElementType, std::ptrdiff_t Extent> template <class ElementType, std::ptrdiff_t Extent>
span<const byte, details::calculate_byte_size<ElementType, Extent>::value> span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
as_bytes(span<ElementType, Extent> s) noexcept as_bytes(span<ElementType, Extent> s) noexcept
{ {
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()}; return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
} }
@ -691,6 +702,7 @@ template <class ElementType, std::ptrdiff_t Extent,
span<byte, details::calculate_byte_size<ElementType, Extent>::value> span<byte, details::calculate_byte_size<ElementType, Extent>::value>
as_writeable_bytes(span<ElementType, Extent> s) noexcept as_writeable_bytes(span<ElementType, Extent> s) noexcept
{ {
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return {reinterpret_cast<byte*>(s.data()), s.size_bytes()}; return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
} }
@ -698,7 +710,8 @@ as_writeable_bytes(span<ElementType, Extent> s) noexcept
// make_span() - Utility functions for creating spans // make_span() - Utility functions for creating spans
// //
template <class ElementType> 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); return span<ElementType>(ptr, count);
} }

View File

@ -20,6 +20,7 @@
#include <gsl/gsl_assert> // for Ensures, Expects #include <gsl/gsl_assert> // for Ensures, Expects
#include <gsl/gsl_util> // for narrow_cast #include <gsl/gsl_util> // for narrow_cast
#include <gsl/span> // for operator!=, operator==, dynamic_extent #include <gsl/span> // for operator!=, operator==, dynamic_extent
#include <gsl/pointers> // for not_null
#include <algorithm> // for equal, lexicographical_compare #include <algorithm> // for equal, lexicographical_compare
#include <array> // for array #include <array> // for array
@ -32,10 +33,9 @@
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
// blanket turn off warnings from CppCoreCheck for now // Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
// so people aren't annoyed by them when running the tool. #pragma warning(disable : 26446) // TODO: bug in parser - attributes and templates
// more targeted suppressions will be added in a future update to the GSL #pragma warning(disable : 26481) // TODO: suppress does not work inside templates sometimes
#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#pragma push_macro("constexpr") #pragma push_macro("constexpr")
@ -44,13 +44,6 @@
#endif // _MSC_VER < 1910 #endif // _MSC_VER < 1910
#endif // _MSC_VER #endif // _MSC_VER
// In order to test the library, we need it to throw exceptions that we can catch
#ifdef GSL_THROW_ON_CONTRACT_VIOLATION
#define GSL_NOEXCEPT /*noexcept*/
#else
#define GSL_NOEXCEPT noexcept
#endif // GSL_THROW_ON_CONTRACT_VIOLATION
namespace gsl namespace gsl
{ {
// //
@ -105,7 +98,7 @@ namespace details
return len; return len;
} }
} } // namespace details
// //
// ensure_sentinel() // ensure_sentinel()
@ -118,7 +111,13 @@ namespace details
template <typename T, const T Sentinel> template <typename T, const T Sentinel>
span<T, dynamic_extent> ensure_sentinel(T* seq, std::ptrdiff_t max = PTRDIFF_MAX) 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; 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; while ((cur - seq) < max && *cur != Sentinel) ++cur;
Ensures(*cur == Sentinel); Ensures(*cur == Sentinel);
return {seq, cur - seq}; return {seq, cur - seq};
@ -138,21 +137,20 @@ span<CharT, dynamic_extent> ensure_z(CharT* const& sz, std::ptrdiff_t max = PTRD
template <typename CharT, std::size_t N> template <typename CharT, std::size_t N>
span<CharT, dynamic_extent> ensure_z(CharT (&sz)[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> template <class Cont>
span<typename std::remove_pointer<typename Cont::pointer>::type, dynamic_extent> span<typename std::remove_pointer<typename Cont::pointer>::type, dynamic_extent>
ensure_z(Cont& cont) 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> template <typename CharT, std::ptrdiff_t>
class basic_string_span; class basic_string_span;
namespace details namespace details {
{
template <typename T> template <typename T>
struct is_basic_string_span_oracle : std::false_type struct is_basic_string_span_oracle : std::false_type
{ {
@ -167,7 +165,7 @@ namespace details
struct is_basic_string_span : is_basic_string_span_oracle<std::remove_cv_t<T>> struct is_basic_string_span : is_basic_string_span_oracle<std::remove_cv_t<T>>
{ {
}; };
} } // namespace details
// //
// string_span and relatives // string_span and relatives
@ -189,13 +187,13 @@ public:
using const_reverse_iterator = typename impl_type::const_reverse_iterator; using const_reverse_iterator = typename impl_type::const_reverse_iterator;
// default (empty) // default (empty)
constexpr basic_string_span() GSL_NOEXCEPT = default; constexpr basic_string_span() noexcept = default;
// copy // copy
constexpr basic_string_span(const basic_string_span& other) GSL_NOEXCEPT = default; constexpr basic_string_span(const basic_string_span& other) noexcept = default;
// assign // assign
constexpr basic_string_span& operator=(const basic_string_span& other) GSL_NOEXCEPT = default; constexpr basic_string_span& operator=(const basic_string_span& other) noexcept = default;
constexpr basic_string_span(pointer ptr, index_type length) : span_(ptr, length) {} constexpr basic_string_span(pointer ptr, index_type length) : span_(ptr, length) {}
constexpr basic_string_span(pointer firstElem, pointer lastElem) : span_(firstElem, lastElem) {} constexpr basic_string_span(pointer firstElem, pointer lastElem) : span_(firstElem, lastElem) {}
@ -204,32 +202,27 @@ public:
// All other containers allow 0s within the length, so we do not remove them // All other containers allow 0s within the length, so we do not remove them
template <std::size_t N> template <std::size_t N>
constexpr basic_string_span(element_type (&arr)[N]) : span_(remove_z(arr)) 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>> template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
constexpr basic_string_span(std::array<ArrayElementType, N>& arr) GSL_NOEXCEPT : span_(arr) 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>> template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
constexpr basic_string_span(const std::array<ArrayElementType, N>& arr) GSL_NOEXCEPT constexpr basic_string_span(const std::array<ArrayElementType, N>& arr) noexcept : span_(arr)
: span_(arr) {}
{
}
// Container signature should work for basic_string after C++17 version exists // Container signature should work for basic_string after C++17 version exists
template <class Traits, class Allocator> 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) constexpr basic_string_span(std::basic_string<element_type, Traits, Allocator>& str)
: span_(&str[0], narrow_cast<std::ptrdiff_t>(str.length())) : span_(&str[0], narrow_cast<std::ptrdiff_t>(str.length()))
{ {}
}
template <class Traits, class Allocator> template <class Traits, class Allocator>
constexpr basic_string_span(const std::basic_string<element_type, Traits, Allocator>& str) constexpr basic_string_span(const std::basic_string<element_type, Traits, Allocator>& str)
: span_(&str[0], str.length()) : span_(&str[0], str.length())
{ {}
}
// from containers. Containers must have a pointer type and data() function signatures // from containers. Containers must have a pointer type and data() function signatures
template <class Container, template <class Container,
@ -239,8 +232,7 @@ public:
std::is_convertible<typename Container::pointer, std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>> decltype(std::declval<Container>().data())>::value>>
constexpr basic_string_span(Container& cont) : span_(cont) constexpr basic_string_span(Container& cont) : span_(cont)
{ {}
}
template <class Container, template <class Container,
class = std::enable_if_t< class = std::enable_if_t<
@ -249,8 +241,7 @@ public:
std::is_convertible<typename Container::pointer, std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>> decltype(std::declval<Container>().data())>::value>>
constexpr basic_string_span(const Container& cont) : span_(cont) constexpr basic_string_span(const Container& cont) : span_(cont)
{ {}
}
// from string_span // from string_span
template < template <
@ -259,8 +250,7 @@ public:
typename basic_string_span<OtherValueType, OtherExtent>::impl_type, impl_type>::value>> typename basic_string_span<OtherValueType, OtherExtent>::impl_type, impl_type>::value>>
constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other) constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other)
: span_(other.data(), other.length()) : span_(other.data(), other.length())
{ {}
}
template <index_type Count> template <index_type Count>
constexpr basic_string_span<element_type, Count> first() const constexpr basic_string_span<element_type, Count> first() const
@ -301,23 +291,23 @@ public:
constexpr pointer data() const { return span_.data(); } constexpr pointer data() const { return span_.data(); }
constexpr index_type length() const GSL_NOEXCEPT { return span_.size(); } constexpr index_type length() const noexcept { return span_.size(); }
constexpr index_type size() const GSL_NOEXCEPT { return span_.size(); } constexpr index_type size() const noexcept { return span_.size(); }
constexpr index_type size_bytes() const GSL_NOEXCEPT { return span_.size_bytes(); } constexpr index_type size_bytes() const noexcept { return span_.size_bytes(); }
constexpr index_type length_bytes() const GSL_NOEXCEPT { return span_.length_bytes(); } constexpr index_type length_bytes() const noexcept { return span_.length_bytes(); }
constexpr bool empty() const GSL_NOEXCEPT { return size() == 0; } constexpr bool empty() const noexcept { return size() == 0; }
constexpr iterator begin() const GSL_NOEXCEPT { return span_.begin(); } constexpr iterator begin() const noexcept { return span_.begin(); }
constexpr iterator end() const GSL_NOEXCEPT { return span_.end(); } constexpr iterator end() const noexcept { return span_.end(); }
constexpr const_iterator cbegin() const GSL_NOEXCEPT { return span_.cbegin(); } constexpr const_iterator cbegin() const noexcept { return span_.cbegin(); }
constexpr const_iterator cend() const GSL_NOEXCEPT { return span_.cend(); } constexpr const_iterator cend() const noexcept { return span_.cend(); }
constexpr reverse_iterator rbegin() const GSL_NOEXCEPT { return span_.rbegin(); } constexpr reverse_iterator rbegin() const noexcept { return span_.rbegin(); }
constexpr reverse_iterator rend() const GSL_NOEXCEPT { return span_.rend(); } constexpr reverse_iterator rend() const noexcept { return span_.rend(); }
constexpr const_reverse_iterator crbegin() const GSL_NOEXCEPT { return span_.crbegin(); } constexpr const_reverse_iterator crbegin() const noexcept { return span_.crbegin(); }
constexpr const_reverse_iterator crend() const GSL_NOEXCEPT { return span_.crend(); } constexpr const_reverse_iterator crend() const noexcept { return span_.crend(); }
private: private:
static impl_type remove_z(pointer const& sz, std::ptrdiff_t max) static impl_type remove_z(pointer const& sz, std::ptrdiff_t max)
@ -366,21 +356,22 @@ template <typename CharT, std::ptrdiff_t Extent>
std::basic_string<typename std::remove_const<CharT>::type> std::basic_string<typename std::remove_const<CharT>::type>
to_string(basic_string_span<CharT, Extent> view) 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>, template <typename CharT, typename Traits = typename std::char_traits<CharT>,
typename Allocator = std::allocator<CharT>, typename gCharT, std::ptrdiff_t Extent> 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) 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> template <class ElementType, std::ptrdiff_t Extent>
basic_string_span<const byte, details::calculate_byte_size<ElementType, Extent>::value> basic_string_span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
as_bytes(basic_string_span<ElementType, Extent> s) noexcept 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, template <class ElementType, std::ptrdiff_t Extent,
@ -388,14 +379,14 @@ template <class ElementType, std::ptrdiff_t Extent,
basic_string_span<byte, details::calculate_byte_size<ElementType, Extent>::value> basic_string_span<byte, details::calculate_byte_size<ElementType, Extent>::value>
as_writeable_bytes(basic_string_span<ElementType, Extent> s) noexcept 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()}; return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
} }
// zero-terminated string span, used to convert // zero-terminated string span, used to convert
// zero-terminated spans to legacy strings // zero-terminated spans to legacy strings
template <typename CharT, std::ptrdiff_t Extent = dynamic_extent> template <typename CharT, std::ptrdiff_t Extent = dynamic_extent>
class basic_zstring_span class basic_zstring_span {
{
public: public:
using value_type = CharT; using value_type = CharT;
using const_value_type = std::add_const_t<CharT>; using const_value_type = std::add_const_t<CharT>;
@ -409,7 +400,7 @@ public:
using impl_type = span<value_type, Extent>; using impl_type = span<value_type, Extent>;
using string_span_type = basic_string_span<value_type, Extent>; using string_span_type = basic_string_span<value_type, Extent>;
constexpr basic_zstring_span(impl_type s) GSL_NOEXCEPT : span_(s) constexpr basic_zstring_span(impl_type s) : span_(s)
{ {
// expects a zero-terminated span // expects a zero-terminated span
Expects(s[s.size() - 1] == '\0'); Expects(s[s.size() - 1] == '\0');
@ -427,16 +418,16 @@ public:
// move assign // move assign
constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default; constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default;
constexpr bool empty() const GSL_NOEXCEPT { return span_.size() == 0; } constexpr bool empty() const noexcept { return span_.size() == 0; }
constexpr string_span_type as_string_span() const GSL_NOEXCEPT constexpr string_span_type as_string_span() const noexcept
{ {
auto sz = span_.size(); const auto sz = span_.size();
return { span_.data(), sz > 1 ? sz - 1 : 0 }; return {span_.data(), sz > 1 ? sz - 1 : 0};
} }
constexpr string_span_type ensure_z() const GSL_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 GSL_NOEXCEPT { return span_.data(); } constexpr const_zstring_type assume_z() const noexcept { return span_.data(); }
private: private:
impl_type span_; impl_type span_;
@ -471,7 +462,7 @@ template <class CharT, std::ptrdiff_t Extent, class T,
class = std::enable_if_t< class = std::enable_if_t<
details::is_basic_string_span<T>::value || details::is_basic_string_span<T>::value ||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>>>::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) GSL_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); const gsl::basic_string_span<std::add_const_t<CharT>> tmp(other);
return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end()); return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end());
@ -481,9 +472,9 @@ template <class CharT, std::ptrdiff_t Extent, class T,
class = std::enable_if_t< class = std::enable_if_t<
!details::is_basic_string_span<T>::value && !details::is_basic_string_span<T>::value &&
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>>>::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) GSL_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()); return std::equal(tmp.begin(), tmp.end(), other.begin(), other.end());
} }
@ -491,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, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible< typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{ {
return !(one == other); return !(one == other);
} }
@ -501,7 +492,7 @@ template <
typename = std::enable_if_t< typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>> !gsl::details::is_basic_string_span<T>::value>>
bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{ {
return !(one == other); return !(one == other);
} }
@ -510,7 +501,7 @@ bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_N
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible< typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_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); 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()); return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end());
@ -521,7 +512,7 @@ template <
typename = std::enable_if_t< typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>> !gsl::details::is_basic_string_span<T>::value>>
bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_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); gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one);
return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end()); return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end());
@ -540,7 +531,7 @@ template <
std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>> DataType>::value>>
bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_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); gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other);
return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end());
@ -554,7 +545,7 @@ template <
std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>> DataType>::value>>
bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_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); gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one);
return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end()); return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end());
@ -565,7 +556,7 @@ bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NO
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible< typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{ {
return !(other < one); return !(other < one);
} }
@ -575,7 +566,7 @@ template <
typename = std::enable_if_t< typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>> !gsl::details::is_basic_string_span<T>::value>>
bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{ {
return !(other < one); return !(other < one);
} }
@ -593,7 +584,7 @@ template <
std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>> DataType>::value>>
bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{ {
return !(other < one); return !(other < one);
} }
@ -606,7 +597,7 @@ template <
std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>> DataType>::value>>
bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{ {
return !(other < one); return !(other < one);
} }
@ -616,7 +607,7 @@ bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_N
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible< typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other)
{ {
return other < one; return other < one;
} }
@ -626,7 +617,7 @@ template <
typename = std::enable_if_t< typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>> !gsl::details::is_basic_string_span<T>::value>>
bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other)
{ {
return other < one; return other < one;
} }
@ -644,7 +635,7 @@ template <
std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>> DataType>::value>>
bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other)
{ {
return other < one; return other < one;
} }
@ -657,7 +648,7 @@ template <
std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>> DataType>::value>>
bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other)
{ {
return other < one; return other < one;
} }
@ -667,7 +658,7 @@ bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NO
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible< typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{ {
return !(one < other); return !(one < other);
} }
@ -677,7 +668,7 @@ template <
typename = std::enable_if_t< typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>> !gsl::details::is_basic_string_span<T>::value>>
bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{ {
return !(one < other); return !(one < other);
} }
@ -695,7 +686,7 @@ template <
std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>> DataType>::value>>
bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) GSL_NOEXCEPT bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other)
{ {
return !(one < other); return !(one < other);
} }
@ -708,15 +699,13 @@ template <
std::is_convertible<DataType*, CharT*>::value && std::is_convertible<DataType*, CharT*>::value &&
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
DataType>::value>> DataType>::value>>
bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) GSL_NOEXCEPT bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other)
{ {
return !(one < other); return !(one < other);
} }
#endif #endif
} // namespace gsl } // namespace gsl
#undef GSL_NOEXCEPT
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)

130
samples/gsl_transition Normal file
View File

@ -0,0 +1,130 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_TRANSITION_H
#define GSL_TRANSITION_H
#include <gsl/gsl_assert> // for Ensures, Expects
#include <gsl/pointers> // for gsl::not_null
#if defined(_MSC_VER) && _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
#endif // defined(_MSC_VER) && _MSC_VER < 1910
namespace gsl_helpers
{
//
// sloppy_not_null
//
// Restricts a pointer or smart pointer to only hold non-null values,
//
// - provides a sloppy (i.e. no explicit contructor from T) wrapper of gsl::not_null
// - is temporary, only to be used to incrementally transition of code
// using older version of gsl::not_null to the new one that made the constructor explicit
//
// To make the transition:
//
// - replace all occurences of gsl::not_null in your code by sloppy_not_null
// variant: rename gsl::not_null by NotNull by including the following in your code,
// foe example, in a common include file:
//
// template<typename T>
// using NotNull = gsl::not_null<T>;
//
// compile using old version of GSL
// change GSL version and replace gsl::not_null by gsl_helpers::sloppy_not_null
// in the added code lines above
//
// - compile - compilation should be successful
// - replace some sloppy_not_nulls by gsl::not_null, fix compilation erros,
// redesign as needed, compile and test
// - repeat until no sloppy_not_nulls remain
//
template <class T>
class sloppy_not_null: public gsl::not_null<T>
{
public:
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr sloppy_not_null(U&& u) :
gsl::not_null<T>(std::forward<U>(u))
{}
template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
constexpr sloppy_not_null(T u) :
gsl::not_null<T>(u)
{}
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr sloppy_not_null(const gsl::not_null<U>& other) :
gsl::not_null<T>(other)
{}
sloppy_not_null(sloppy_not_null&& other) = default;
sloppy_not_null(const sloppy_not_null& other) = default;
sloppy_not_null& operator=(const sloppy_not_null& other) = default;
sloppy_not_null& operator=(const gsl::not_null<T>& other)
{
gsl::not_null<T>::operator=(other);
return *this;
}
// prevents compilation when someone attempts to assign a null pointer constant
sloppy_not_null(std::nullptr_t) = delete;
sloppy_not_null& operator=(std::nullptr_t) = delete;
// unwanted operators...pointers only point to single objects!
sloppy_not_null& operator++() = delete;
sloppy_not_null& operator--() = delete;
sloppy_not_null operator++(int) = delete;
sloppy_not_null operator--(int) = delete;
sloppy_not_null& operator+=(std::ptrdiff_t) = delete;
sloppy_not_null& operator-=(std::ptrdiff_t) = delete;
void operator[](std::ptrdiff_t) const = delete;
};
// more unwanted operators
template <class T, class U>
std::ptrdiff_t operator-(const sloppy_not_null<T>&, const sloppy_not_null<U>&) = delete;
template <class T>
sloppy_not_null<T> operator-(const sloppy_not_null<T>&, std::ptrdiff_t) = delete;
template <class T>
sloppy_not_null<T> operator+(const sloppy_not_null<T>&, std::ptrdiff_t) = delete;
template <class T>
sloppy_not_null<T> operator+(std::ptrdiff_t, const sloppy_not_null<T>&) = delete;
} // namespace gsl
namespace std
{
template <class T>
struct hash<gsl_helpers::sloppy_not_null<T>>
{
std::size_t operator()(const gsl_helpers::sloppy_not_null<T>& value) const { return hash<T>{}(value); }
};
} // namespace std
#if defined(_MSC_VER) && _MSC_VER < 1910
#undef constexpr
#pragma pop_macro("constexpr")
#endif // defined(_MSC_VER) && _MSC_VER < 1910
#endif // GSL_TRANSITION_H

View File

@ -27,7 +27,7 @@ else()
endif() endif()
if (MSVC AND (GSL_CXX_STANDARD EQUAL 17)) if (MSVC AND (GSL_CXX_STANDARD EQUAL 17))
set(GSL_CPLUSPLUS_OPT -Zc:__cplusplus) set(GSL_CPLUSPLUS_OPT -Zc:__cplusplus -permissive-)
endif() endif()
# this interface adds compile options to how the tests are run # this interface adds compile options to how the tests are run
@ -49,6 +49,7 @@ target_compile_options(gsl_tests_config INTERFACE
-Werror -Werror
-Wextra -Wextra
-Wno-missing-braces -Wno-missing-braces
-Wno-unknown-attributes
-Wnon-virtual-dtor -Wnon-virtual-dtor
-Wold-style-cast -Wold-style-cast
-Woverloaded-virtual -Woverloaded-virtual
@ -106,6 +107,7 @@ add_gsl_test(utils_tests)
add_gsl_test(owner_tests) add_gsl_test(owner_tests)
add_gsl_test(byte_tests) add_gsl_test(byte_tests)
add_gsl_test(algorithm_tests) add_gsl_test(algorithm_tests)
add_gsl_test(sloppy_notnull_tests)
# No exception tests # No exception tests
@ -138,6 +140,7 @@ target_compile_options(gsl_tests_config_noexcept INTERFACE
-Werror -Werror
-Wextra -Wextra
-Wno-missing-braces -Wno-missing-braces
-Wno-unknown-attributes
-Wnon-virtual-dtor -Wnon-virtual-dtor
-Wold-style-cast -Wold-style-cast
-Woverloaded-virtual -Woverloaded-virtual

View File

@ -14,6 +14,12 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHE... #include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHE...
#include <gsl/gsl_algorithm> // for copy #include <gsl/gsl_algorithm> // for copy
@ -29,6 +35,8 @@ struct fail_fast;
using namespace std; using namespace std;
using namespace gsl; using namespace gsl;
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("same_type") TEST_CASE("same_type")
{ {
// dynamic source and destination span // dynamic source and destination span
@ -36,8 +44,8 @@ TEST_CASE("same_type")
std::array<int, 5> src{1, 2, 3, 4, 5}; std::array<int, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{}; std::array<int, 10> dst{};
span<int> src_span(src); const span<int> src_span(src);
span<int> dst_span(dst); const span<int> dst_span(dst);
copy(src_span, dst_span); copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size())); copy(src_span, dst_span.subspan(src_span.size()));
@ -53,8 +61,8 @@ TEST_CASE("same_type")
std::array<int, 5> src{1, 2, 3, 4, 5}; std::array<int, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{}; std::array<int, 10> dst{};
span<int, 5> src_span(src); const span<int, 5> src_span(src);
span<int> dst_span(dst); const span<int> dst_span(dst);
copy(src_span, dst_span); copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size())); copy(src_span, dst_span.subspan(src_span.size()));
@ -70,8 +78,8 @@ TEST_CASE("same_type")
std::array<int, 5> src{1, 2, 3, 4, 5}; std::array<int, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{}; std::array<int, 10> dst{};
span<int> src_span(src); const span<int> src_span(src);
span<int, 10> dst_span(dst); const span<int, 10> dst_span(dst);
copy(src_span, dst_span); copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size())); copy(src_span, dst_span.subspan(src_span.size()));
@ -87,8 +95,8 @@ TEST_CASE("same_type")
std::array<int, 5> src{1, 2, 3, 4, 5}; std::array<int, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{}; std::array<int, 10> dst{};
span<int, 5> src_span(src); const span<int, 5> src_span(src);
span<int, 10> dst_span(dst); const span<int, 10> dst_span(dst);
copy(src_span, dst_span); copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size())); copy(src_span, dst_span.subspan(src_span.size()));
@ -100,6 +108,9 @@ TEST_CASE("same_type")
} }
} }
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("compatible_type") TEST_CASE("compatible_type")
{ {
// dynamic source and destination span // dynamic source and destination span
@ -107,8 +118,8 @@ TEST_CASE("compatible_type")
std::array<short, 5> src{1, 2, 3, 4, 5}; std::array<short, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{}; std::array<int, 10> dst{};
span<short> src_span(src); const span<short> src_span(src);
span<int> dst_span(dst); const span<int> dst_span(dst);
copy(src_span, dst_span); copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size())); copy(src_span, dst_span.subspan(src_span.size()));
@ -124,8 +135,8 @@ TEST_CASE("compatible_type")
std::array<short, 5> src{1, 2, 3, 4, 5}; std::array<short, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{}; std::array<int, 10> dst{};
span<short, 5> src_span(src); const span<short, 5> src_span(src);
span<int> dst_span(dst); const span<int> dst_span(dst);
copy(src_span, dst_span); copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size())); copy(src_span, dst_span.subspan(src_span.size()));
@ -141,8 +152,8 @@ TEST_CASE("compatible_type")
std::array<short, 5> src{1, 2, 3, 4, 5}; std::array<short, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{}; std::array<int, 10> dst{};
span<short> src_span(src); const span<short> src_span(src);
span<int, 10> dst_span(dst); const span<int, 10> dst_span(dst);
copy(src_span, dst_span); copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size())); copy(src_span, dst_span.subspan(src_span.size()));
@ -158,8 +169,8 @@ TEST_CASE("compatible_type")
std::array<short, 5> src{1, 2, 3, 4, 5}; std::array<short, 5> src{1, 2, 3, 4, 5};
std::array<int, 10> dst{}; std::array<int, 10> dst{};
span<short, 5> src_span(src); const span<short, 5> src_span(src);
span<int, 10> dst_span(dst); const span<int, 10> dst_span(dst);
copy(src_span, dst_span); copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size())); copy(src_span, dst_span.subspan(src_span.size()));
@ -195,10 +206,10 @@ TEST_CASE("small_destination_span")
std::array<int, 12> src{1, 2, 3, 4}; std::array<int, 12> src{1, 2, 3, 4};
std::array<int, 4> dst{}; std::array<int, 4> dst{};
span<int> src_span_dyn(src); const span<int> src_span_dyn(src);
span<int, 12> src_span_static(src); const span<int, 12> src_span_static(src);
span<int> dst_span_dyn(dst); const span<int> dst_span_dyn(dst);
span<int, 4> dst_span_static(dst); const span<int, 4> dst_span_static(dst);
CHECK_THROWS_AS(copy(src_span_dyn, dst_span_dyn), fail_fast); CHECK_THROWS_AS(copy(src_span_dyn, dst_span_dyn), fail_fast);
CHECK_THROWS_AS(copy(src_span_dyn, dst_span_static), fail_fast); CHECK_THROWS_AS(copy(src_span_dyn, dst_span_static), fail_fast);

View File

@ -14,6 +14,12 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK... #include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK...
#include <gsl/gsl_assert> // for fail_fast (ptr only), Ensures, Expects #include <gsl/gsl_assert> // for fail_fast (ptr only), Ensures, Expects

View File

@ -14,6 +14,12 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK_THROW... #include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK_THROW...
#include <gsl/gsl_util> // for at #include <gsl/gsl_util> // for at
@ -23,12 +29,15 @@
#include <initializer_list> // for initializer_list #include <initializer_list> // for initializer_list
#include <vector> // for vector #include <vector> // for vector
namespace gsl { namespace gsl {
struct fail_fast; struct fail_fast;
} // namespace gsl } // namespace gsl
using gsl::fail_fast; using gsl::fail_fast;
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("static_array") TEST_CASE("static_array")
{ {
int a[4] = {1, 2, 3, 4}; int a[4] = {1, 2, 3, 4};
@ -45,6 +54,8 @@ TEST_CASE("static_array")
CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast); CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast);
} }
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("std_array") TEST_CASE("std_array")
{ {
std::array<int, 4> a = {1, 2, 3, 4}; std::array<int, 4> a = {1, 2, 3, 4};
@ -61,6 +72,8 @@ TEST_CASE("std_array")
CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast); CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast);
} }
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("StdVector") TEST_CASE("StdVector")
{ {
std::vector<int> a = {1, 2, 3, 4}; std::vector<int> a = {1, 2, 3, 4};
@ -77,9 +90,11 @@ TEST_CASE("StdVector")
CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast); CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast);
} }
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("InitializerList") TEST_CASE("InitializerList")
{ {
std::initializer_list<int> a = {1, 2, 3, 4}; const std::initializer_list<int> a = {1, 2, 3, 4};
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
CHECK(gsl::at(a, i) == i + 1); CHECK(gsl::at(a, i) == i + 1);
@ -93,6 +108,9 @@ TEST_CASE("InitializerList")
} }
#if !defined(_MSC_VER) || defined(__clang__) || _MSC_VER >= 1910 #if !defined(_MSC_VER) || defined(__clang__) || _MSC_VER >= 1910
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
static constexpr bool test_constexpr() static constexpr bool test_constexpr()
{ {
int a1[4] = {1, 2, 3, 4}; int a1[4] = {1, 2, 3, 4};
@ -114,3 +132,4 @@ static constexpr bool test_constexpr()
static_assert(test_constexpr(), "FAIL"); static_assert(test_constexpr(), "FAIL");
#endif #endif

View File

@ -14,6 +14,12 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, TEST_CASE #include <catch/catch.hpp> // for AssertionHandler, StringRef, TEST_CASE
#include <gsl/multi_span> // for static_bounds, static_bounds_dynamic_range_t #include <gsl/multi_span> // for static_bounds, static_bounds_dynamic_range_t
@ -32,6 +38,7 @@ namespace
void use(std::ptrdiff_t&) {} void use(std::ptrdiff_t&) {}
} }
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
TEST_CASE("basic_bounds") TEST_CASE("basic_bounds")
{ {
for (auto point : static_bounds<dynamic_range, 3, 4>{2}) { for (auto point : static_bounds<dynamic_range, 3, 4>{2}) {
@ -44,6 +51,8 @@ TEST_CASE("basic_bounds")
} }
} }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("bounds_basic") TEST_CASE("bounds_basic")
{ {
static_bounds<3, 4, 5> b; static_bounds<3, 4, 5> b;
@ -53,6 +62,8 @@ TEST_CASE("bounds_basic")
x.slice().slice(); x.slice().slice();
} }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("arrayview_iterator") TEST_CASE("arrayview_iterator")
{ {
static_bounds<4, dynamic_range, 2> bounds{3}; static_bounds<4, dynamic_range, 2> bounds{3};
@ -71,6 +82,7 @@ TEST_CASE("arrayview_iterator")
#endif #endif
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("bounds_convertible") TEST_CASE("bounds_convertible")
{ {
static_bounds<7, 4, 2> b1; static_bounds<7, 4, 2> b1;
@ -97,3 +109,7 @@ TEST_CASE("bounds_convertible")
CHECK(b5 == b6); CHECK(b5 == b6);
CHECK(b5.size() == b6.size()); CHECK(b5.size() == b6.size());
} }
#ifdef CONFIRM_COMPILATION_ERRORS
copy(src_span_static, dst_span_static);
#endif

View File

@ -14,6 +14,12 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_... #include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
#include <gsl/gsl_byte> // for to_byte, to_integer, byte, operator&, ope... #include <gsl/gsl_byte> // for to_byte, to_integer, byte, operator&, ope...
@ -23,7 +29,6 @@ using namespace gsl;
namespace namespace
{ {
TEST_CASE("construction") TEST_CASE("construction")
{ {
{ {
@ -31,6 +36,7 @@ TEST_CASE("construction")
CHECK(static_cast<unsigned char>(b) == 4); CHECK(static_cast<unsigned char>(b) == 4);
} }
GSL_SUPPRESS(es.49)
{ {
const byte b = byte(12); const byte b = byte(12);
CHECK(static_cast<unsigned char>(b) == 12); CHECK(static_cast<unsigned char>(b) == 12);
@ -46,11 +52,12 @@ TEST_CASE("construction")
CHECK(static_cast<unsigned char>(b) == 12); CHECK(static_cast<unsigned char>(b) == 12);
} }
// waiting for C++17 enum class direct initializer support #if defined(__cplusplus) && (__cplusplus >= 201703L)
//{ {
// byte b { 14 }; const byte b { 14 };
// CHECK(static_cast<unsigned char>(b) == 14); CHECK(static_cast<unsigned char>(b) == 14);
//} }
#endif
} }
TEST_CASE("bitwise_operations") TEST_CASE("bitwise_operations")
@ -114,6 +121,7 @@ int modify_both(gsl::byte & b, int& i)
return i; return i;
} }
GSL_SUPPRESS(type.1)
TEST_CASE("aliasing") TEST_CASE("aliasing")
{ {
int i{0}; int i{0};
@ -122,3 +130,7 @@ TEST_CASE("aliasing")
} }
} }
#ifdef CONFIRM_COMPILATION_ERRORS
copy(src_span_static, dst_span_static);
#endif

View File

@ -14,6 +14,13 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK... #include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK...
#include <gsl/gsl_byte> // for byte #include <gsl/gsl_byte> // for byte
@ -29,7 +36,8 @@
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
namespace gsl { namespace gsl
{
struct fail_fast; struct fail_fast;
} // namespace gsl } // namespace gsl
@ -44,8 +52,9 @@ struct BaseClass
struct DerivedClass : BaseClass struct DerivedClass : BaseClass
{ {
}; };
} } // namespace
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("default_constructor") TEST_CASE("default_constructor")
{ {
{ {
@ -80,6 +89,7 @@ TEST_CASE("default_constructor")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_nullptr_constructor") TEST_CASE("from_nullptr_constructor")
{ {
{ {
@ -122,8 +132,8 @@ TEST_CASE("from_nullptr_constructor")
} }
} }
TEST_CASE("from_nullptr_length_constructor") GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
{ TEST_CASE("from_nullptr_length_constructor") {
{ {
multi_span<int> s{nullptr, 0}; multi_span<int> s{nullptr, 0};
CHECK((s.length() == 0 && s.data() == nullptr)); CHECK((s.length() == 0 && s.data() == nullptr));
@ -141,25 +151,18 @@ TEST_CASE("from_nullptr_length_constructor")
} }
{ {
#ifdef CONFIRM_COMPILATION_ERRORS auto workaround_macro = []() { const multi_span<int> s{nullptr, 1}; };
multi_span<int, 1> s{nullptr, 0};
CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile
#endif
}
{
auto workaround_macro = []() { multi_span<int> s{nullptr, 1}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
auto const_workaround_macro = []() { multi_span<const int> cs{nullptr, 1}; }; auto const_workaround_macro = []() { const multi_span<const int> cs{nullptr, 1}; };
CHECK_THROWS_AS(const_workaround_macro(), fail_fast); CHECK_THROWS_AS(const_workaround_macro(), fail_fast);
} }
{ {
auto workaround_macro = []() { multi_span<int, 0> s{nullptr, 1}; }; auto workaround_macro = []() { const multi_span<int, 0> s{nullptr, 1}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
auto const_workaround_macro = []() { multi_span<const int, 0> s{nullptr, 1}; }; auto const_workaround_macro = []() { const multi_span<const int, 0> s{nullptr, 1}; };
CHECK_THROWS_AS(const_workaround_macro(), fail_fast); CHECK_THROWS_AS(const_workaround_macro(), fail_fast);
} }
@ -170,8 +173,16 @@ TEST_CASE("from_nullptr_length_constructor")
multi_span<const int*> cs{nullptr, 0}; multi_span<const int*> cs{nullptr, 0};
CHECK((cs.length() == 0 && cs.data() == nullptr)); CHECK((cs.length() == 0 && cs.data() == nullptr));
} }
{
#ifdef CONFIRM_COMPILATION_ERRORS
multi_span<int, 1> s{nullptr, 0};
CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile
#endif
}
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_element_constructor") TEST_CASE("from_element_constructor")
{ {
int i = 5; int i = 5;
@ -222,6 +233,7 @@ TEST_CASE("from_element_constructor")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_pointer_length_constructor") TEST_CASE("from_pointer_length_constructor")
{ {
int arr[4] = {1, 2, 3, 4}; int arr[4] = {1, 2, 3, 4};
@ -246,11 +258,12 @@ TEST_CASE("from_pointer_length_constructor")
{ {
int* p = nullptr; int* p = nullptr;
auto workaround_macro = [=]() { multi_span<int> s{p, 2}; }; auto workaround_macro = [=]() { const multi_span<int> s{p, 2}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_pointer_pointer_constructor") TEST_CASE("from_pointer_pointer_constructor")
{ {
int arr[4] = {1, 2, 3, 4}; int arr[4] = {1, 2, 3, 4};
@ -278,29 +291,31 @@ TEST_CASE("from_pointer_pointer_constructor")
} }
{ {
auto workaround_macro = [&]() { multi_span<int> s{&arr[1], &arr[0]}; }; auto workaround_macro = [&]() { const multi_span<int> s{&arr[1], &arr[0]}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
{ {
int* p = nullptr; int* p = nullptr;
auto workaround_macro = [&]() { multi_span<int> s{&arr[0], p}; }; auto workaround_macro = [&]() { const multi_span<int> s{&arr[0], p}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
{ {
int* p = nullptr; int* p = nullptr;
auto workaround_macro = [&]() { multi_span<int> s{p, p}; }; auto workaround_macro = [&]() { const multi_span<int> s{p, p}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
{ {
int* p = nullptr; int* p = nullptr;
auto workaround_macro = [&]() { multi_span<int> s{&arr[0], p}; }; auto workaround_macro = [&]() { const multi_span<int> s{&arr[0], p}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
TEST_CASE("from_array_constructor") TEST_CASE("from_array_constructor")
{ {
int arr[5] = {1, 2, 3, 4, 5}; int arr[5] = {1, 2, 3, 4, 5};
@ -425,6 +440,11 @@ TEST_CASE("from_array_constructor")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
TEST_CASE("from_dynamic_array_constructor") TEST_CASE("from_dynamic_array_constructor")
{ {
double(*arr)[3][4] = new double[100][3][4]; double(*arr)[3][4] = new double[100][3][4];
@ -453,6 +473,7 @@ TEST_CASE("from_dynamic_array_constructor")
delete[] arr; delete[] arr;
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: Attribute
TEST_CASE("from_std_array_constructor") TEST_CASE("from_std_array_constructor")
{ {
std::array<int, 4> arr = {1, 2, 3, 4}; std::array<int, 4> arr = {1, 2, 3, 4};
@ -512,6 +533,7 @@ TEST_CASE("from_std_array_constructor")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_const_std_array_constructor") TEST_CASE("from_const_std_array_constructor")
{ {
const std::array<int, 4> arr = {1, 2, 3, 4}; const std::array<int, 4> arr = {1, 2, 3, 4};
@ -559,6 +581,7 @@ TEST_CASE("from_const_std_array_constructor")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_container_constructor") TEST_CASE("from_container_constructor")
{ {
std::vector<int> v = {1, 2, 3}; std::vector<int> v = {1, 2, 3};
@ -589,8 +612,7 @@ TEST_CASE("from_container_constructor")
multi_span<char> s{cstr}; multi_span<char> s{cstr};
#endif #endif
multi_span<const char> cs{cstr}; multi_span<const char> cs{cstr};
CHECK((cs.size() == narrow_cast<std::ptrdiff_t>(cstr.size()) && CHECK((cs.size() == narrow_cast<std::ptrdiff_t>(cstr.size()) && cs.data() == cstr.data()));
cs.data() == cstr.data()));
} }
{ {
@ -633,6 +655,8 @@ TEST_CASE("from_container_constructor")
} }
} }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_convertible_span_constructor") TEST_CASE("from_convertible_span_constructor")
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
@ -660,6 +684,7 @@ TEST_CASE("from_convertible_span_constructor")
(void) avcd; (void) avcd;
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("copy_move_and_assignment") TEST_CASE("copy_move_and_assignment")
{ {
multi_span<int> s1; multi_span<int> s1;
@ -688,6 +713,8 @@ void fn(const Bounds&)
{ {
static_assert(Bounds::static_size == 60, "static bounds is wrong size"); static_assert(Bounds::static_size == 60, "static bounds is wrong size");
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("as_multi_span_reshape") TEST_CASE("as_multi_span_reshape")
{ {
int a[3][4][5]; int a[3][4][5];
@ -706,11 +733,10 @@ TEST_CASE("as_multi_span_reshape")
auto av8 = as_multi_span<int>(av7); auto av8 = as_multi_span<int>(av7);
CHECK(av8.size() == av6.size()); CHECK(av8.size() == av6.size());
for (auto i = 0; i < av8.size(); i++) { for (auto i = 0; i < av8.size(); i++) { CHECK(av8[i] == 1); }
CHECK(av8[i] == 1);
}
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("first") TEST_CASE("first")
{ {
int arr[5] = {1, 2, 3, 4, 5}; int arr[5] = {1, 2, 3, 4, 5};
@ -754,6 +780,7 @@ TEST_CASE("first")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("last") TEST_CASE("last")
{ {
int arr[5] = {1, 2, 3, 4, 5}; int arr[5] = {1, 2, 3, 4, 5};
@ -796,6 +823,7 @@ TEST_CASE("last")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("subspan") TEST_CASE("subspan")
{ {
int arr[5] = {1, 2, 3, 4, 5}; int arr[5] = {1, 2, 3, 4, 5};
@ -869,6 +897,7 @@ TEST_CASE("subspan")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("rank") TEST_CASE("rank")
{ {
int arr[2] = {1, 2}; int arr[2] = {1, 2};
@ -890,6 +919,7 @@ TEST_CASE("rank")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("extent") TEST_CASE("extent")
{ {
{ {
@ -962,6 +992,7 @@ TEST_CASE("operator_function_call")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("comparison_operators") TEST_CASE("comparison_operators")
{ {
{ {
@ -1074,17 +1105,20 @@ TEST_CASE("comparison_operators")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
TEST_CASE("basics") TEST_CASE("basics")
{ {
auto ptr = as_multi_span(new int[10], 10); auto ptr = as_multi_span(new int[10], 10);
fill(ptr.begin(), ptr.end(), 99); fill(ptr.begin(), ptr.end(), 99);
for (int num : ptr) { for (int num : ptr) { CHECK(num == 99); }
CHECK(num == 99);
}
delete[] ptr.data(); delete[] ptr.data();
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
TEST_CASE("bounds_checks") TEST_CASE("bounds_checks")
{ {
int arr[10][2]; int arr[10][2];
@ -1111,25 +1145,24 @@ TEST_CASE("bounds_checks")
void overloaded_func(multi_span<const int, dynamic_range, 3, 5> exp, int expected_value) void overloaded_func(multi_span<const int, dynamic_range, 3, 5> exp, int expected_value)
{ {
for (auto val : exp) { for (auto val : exp) { CHECK(val == expected_value); }
CHECK(val == expected_value);
}
} }
void overloaded_func(multi_span<const char, dynamic_range, 3, 5> exp, char expected_value) void overloaded_func(multi_span<const char, dynamic_range, 3, 5> exp, char expected_value)
{ {
for (auto val : exp) { for (auto val : exp) { CHECK(val == expected_value); }
CHECK(val == expected_value);
}
} }
void fixed_func(multi_span<int, 3, 3, 5> exp, int expected_value) void fixed_func(multi_span<int, 3, 3, 5> exp, int expected_value)
{ {
for (auto val : exp) { for (auto val : exp) { CHECK(val == expected_value); }
CHECK(val == expected_value);
}
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
TEST_CASE("span_parameter_test") TEST_CASE("span_parameter_test")
{ {
auto data = new int[4][3][5]; auto data = new int[4][3][5];
@ -1151,12 +1184,16 @@ TEST_CASE("span_parameter_test")
delete[] data; delete[] data;
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // false positive, checker does not recognize multi_span yet
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
TEST_CASE("md_access") TEST_CASE("md_access")
{ {
auto width = 5, height = 20; auto width = 5, height = 20;
auto imgSize = width * height; auto imgSize = width * height;
auto image_ptr = new int[static_cast<std::size_t>(imgSize)][3]; auto image_ptr = new int[narrow_cast<std::size_t>(imgSize)][3];
// size check will be done // size check will be done
auto image_view = auto image_view =
@ -1165,8 +1202,10 @@ TEST_CASE("md_access")
iota(image_view.begin(), image_view.end(), 1); iota(image_view.begin(), image_view.end(), 1);
int expected = 0; int expected = 0;
for (auto i = 0; i < height; i++) { for (auto i = 0; i < height; i++)
for (auto j = 0; j < width; j++) { {
for (auto j = 0; j < width; j++)
{
CHECK(expected + 1 == image_view[i][j][0]); CHECK(expected + 1 == image_view[i][j][0]);
CHECK(expected + 2 == image_view[i][j][1]); CHECK(expected + 2 == image_view[i][j][1]);
CHECK(expected + 3 == image_view[i][j][2]); CHECK(expected + 3 == image_view[i][j][2]);
@ -1183,6 +1222,11 @@ TEST_CASE("md_access")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
TEST_CASE("as_multi_span") TEST_CASE("as_multi_span")
{ {
{ {
@ -1201,6 +1245,7 @@ TEST_CASE("as_multi_span")
string str = "ttttttttttttttt"; // size = 15 string str = "ttttttttttttttt"; // size = 15
auto t = str.data(); auto t = str.data();
GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive
(void) t; (void) t;
auto av3 = as_multi_span(str); auto av3 = as_multi_span(str);
overloaded_func(as_multi_span(av3, dim(1), dim<3>(), dim<5>()), 't'); overloaded_func(as_multi_span(av3, dim(1), dim<3>(), dim<5>()), 't');
@ -1232,12 +1277,13 @@ TEST_CASE("as_multi_span")
auto dv = as_multi_span(vec); auto dv = as_multi_span(vec);
(void) dv; (void) dv;
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
auto dv2 = as_multi_span(std::move(vec)); auto dv2 = as_multi_span(std::move(vec));
#endif #endif
} }
} }
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
TEST_CASE("empty_spans") TEST_CASE("empty_spans")
{ {
{ {
@ -1247,7 +1293,8 @@ TEST_CASE("empty_spans")
CHECK_THROWS_AS(empty_av[0], fail_fast); CHECK_THROWS_AS(empty_av[0], fail_fast);
CHECK_THROWS_AS(empty_av.begin()[0], fail_fast); CHECK_THROWS_AS(empty_av.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast); CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast);
for (auto& v : empty_av) { for (auto& v : empty_av)
{
(void) v; (void) v;
CHECK(false); CHECK(false);
} }
@ -1259,17 +1306,25 @@ TEST_CASE("empty_spans")
CHECK_THROWS_AS(empty_av[0], fail_fast); CHECK_THROWS_AS(empty_av[0], fail_fast);
CHECK_THROWS_AS(empty_av.begin()[0], fail_fast); CHECK_THROWS_AS(empty_av.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast); CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast);
for (auto& v : empty_av) { for (auto& v : empty_av)
{
(void) v; (void) v;
CHECK(false); CHECK(false);
} }
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
TEST_CASE("index_constructor") TEST_CASE("index_constructor")
{ {
auto arr = new int[8]; auto arr = new int[8];
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i)
{
arr[2 * i] = 4 + i; arr[2 * i] = 4 + i;
arr[2 * i + 1] = i; arr[2 * i + 1] = i;
} }
@ -1291,6 +1346,7 @@ TEST_CASE("index_constructor")
delete[] arr; delete[] arr;
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("index_constructors") TEST_CASE("index_constructors")
{ {
{ {
@ -1352,7 +1408,7 @@ TEST_CASE("index_constructors")
CHECK(i9[0] == 0); CHECK(i9[0] == 0);
} }
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {
multi_span_index<3> i1(0, 1); multi_span_index<3> i1(0, 1);
multi_span_index<3> i2(0, 1, 2, 3); multi_span_index<3> i2(0, 1, 2, 3);
@ -1360,9 +1416,10 @@ TEST_CASE("index_constructors")
multi_span_index<3> i4 = {0, 1, 2, 3}; multi_span_index<3> i4 = {0, 1, 2, 3};
multi_span_index<1> i5 = {0, 1}; multi_span_index<1> i5 = {0, 1};
} }
#endif #endif
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("index_operations") TEST_CASE("index_operations")
{ {
ptrdiff_t a[3] = {0, 1, 2}; ptrdiff_t a[3] = {0, 1, 2};
@ -1418,6 +1475,8 @@ TEST_CASE("index_operations")
} }
} }
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av) void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
{ {
auto length = av.size() / 2; auto length = av.size() / 2;
@ -1426,33 +1485,33 @@ void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
auto section = av.section({0, 1}, {length, 1}); auto section = av.section({0, 1}, {length, 1});
CHECK(section.size() == length); CHECK(section.size() == length);
for (auto i = 0; i < section.size(); ++i) { for (auto i = 0; i < section.size(); ++i) { CHECK(section[i][0] == av[i][1]); }
CHECK(section[i][0] == av[i][1]);
}
for (auto i = 0; i < section.size(); ++i) { for (auto i = 0; i < section.size(); ++i)
{
auto idx = multi_span_index<2>{i, 0}; // avoid braces inside the CHECK macro auto idx = multi_span_index<2>{i, 0}; // avoid braces inside the CHECK macro
CHECK(section[idx] == av[i][1]); CHECK(section[idx] == av[i][1]);
} }
CHECK(section.bounds().index_bounds()[0] == length); CHECK(section.bounds().index_bounds()[0] == length);
CHECK(section.bounds().index_bounds()[1] == 1); CHECK(section.bounds().index_bounds()[1] == 1);
for (auto i = 0; i < section.bounds().index_bounds()[0]; ++i) { for (auto i = 0; i < section.bounds().index_bounds()[0]; ++i)
for (auto j = 0; j < section.bounds().index_bounds()[1]; ++j) { {
for (auto j = 0; j < section.bounds().index_bounds()[1]; ++j)
{
auto idx = multi_span_index<2>{i, j}; // avoid braces inside the CHECK macro auto idx = multi_span_index<2>{i, j}; // avoid braces inside the CHECK macro
CHECK(section[idx] == av[i][1]); CHECK(section[idx] == av[i][1]);
} }
} }
auto check_sum = 0; auto check_sum = 0;
for (auto i = 0; i < length; ++i) { for (auto i = 0; i < length; ++i) { check_sum += av[i][1]; }
check_sum += av[i][1];
}
{ {
auto idx = 0; auto idx = 0;
auto sum = 0; auto sum = 0;
for (auto num : section) { for (auto num : section)
{
CHECK(num == av[idx][1]); CHECK(num == av[idx][1]);
sum += num; sum += num;
idx++; idx++;
@ -1463,7 +1522,8 @@ void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
{ {
auto idx = length - 1; auto idx = length - 1;
auto sum = 0; auto sum = 0;
for (auto iter = section.rbegin(); iter != section.rend(); ++iter) { for (auto iter = section.rbegin(); iter != section.rend(); ++iter)
{
CHECK(*iter == av[idx][1]); CHECK(*iter == av[idx][1]);
sum += *iter; sum += *iter;
idx--; idx--;
@ -1473,6 +1533,7 @@ void iterate_second_column(multi_span<int, dynamic_range, dynamic_range> av)
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("span_section_iteration") TEST_CASE("span_section_iteration")
{ {
int arr[4][2] = {{4, 0}, {5, 1}, {6, 2}, {7, 3}}; int arr[4][2] = {{4, 0}, {5, 1}, {6, 2}, {7, 3}};
@ -1499,15 +1560,18 @@ TEST_CASE("span_section_iteration")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
TEST_CASE("dynamic_span_section_iteration") TEST_CASE("dynamic_span_section_iteration")
{ {
auto height = 4, width = 2; auto height = 4, width = 2;
auto size = height * width; auto size = height * width;
auto arr = new int[static_cast<std::size_t>(size)]; auto arr = new int[narrow_cast<std::size_t>(size)];
for (auto i = 0; i < size; ++i) { for (auto i = 0; i < size; ++i) { arr[i] = i; }
arr[i] = i;
}
auto av = as_multi_span(arr, size); auto av = as_multi_span(arr, size);
@ -1531,6 +1595,10 @@ TEST_CASE("dynamic_span_section_iteration")
delete[] arr; delete[] arr;
} }
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
TEST_CASE("span_structure_size") TEST_CASE("span_structure_size")
{ {
double(*arr)[3][4] = new double[100][3][4]; double(*arr)[3][4] = new double[100][3][4];
@ -1550,6 +1618,7 @@ TEST_CASE("span_structure_size")
(void) av2; (void) av2;
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("fixed_size_conversions") TEST_CASE("fixed_size_conversions")
{ {
int arr[] = {1, 2, 3, 4}; int arr[] = {1, 2, 3, 4};
@ -1631,7 +1700,7 @@ TEST_CASE("fixed_size_conversions")
#endif #endif
{ {
auto f = [&]() { auto f = [&]() {
multi_span<int, 4> av9 = {arr2, 2}; const multi_span<int, 4> av9 = {arr2, 2};
(void) av9; (void) av9;
}; };
CHECK_THROWS_AS(f(), fail_fast); CHECK_THROWS_AS(f(), fail_fast);
@ -1640,12 +1709,13 @@ TEST_CASE("fixed_size_conversions")
// this should fail - we are trying to assign a small dynamic a_v to a fixed_size larger one // this should fail - we are trying to assign a small dynamic a_v to a fixed_size larger one
multi_span<int, dynamic_range> av = arr2; multi_span<int, dynamic_range> av = arr2;
auto f = [&]() { auto f = [&]() {
multi_span<int, 4> av2 = av; const multi_span<int, 4> av2 = av;
(void) av2; (void) av2;
}; };
CHECK_THROWS_AS(f(), fail_fast); CHECK_THROWS_AS(f(), fail_fast);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("as_writeable_bytes") TEST_CASE("as_writeable_bytes")
{ {
int a[] = {1, 2, 3, 4}; int a[] = {1, 2, 3, 4};
@ -1674,6 +1744,10 @@ TEST_CASE("as_writeable_bytes")
} }
} }
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("iterator") TEST_CASE("iterator")
{ {
int a[] = {1, 2, 3, 4}; int a[] = {1, 2, 3, 4};
@ -1682,8 +1756,14 @@ TEST_CASE("iterator")
multi_span<int, dynamic_range> av = a; multi_span<int, dynamic_range> av = a;
auto wav = as_writeable_bytes(av); auto wav = as_writeable_bytes(av);
for (auto& b : wav) { for (auto& b : wav) {
#if defined(__cplusplus) && (__cplusplus >= 201703L)
b = byte{0};
#else
GSL_SUPPRESS(es.49)
b = byte(0); b = byte(0);
#endif
} }
for (std::size_t i = 0; i < 4; ++i) { for (std::size_t i = 0; i < 4; ++i) {
CHECK(a[i] == 0); CHECK(a[i] == 0);
} }
@ -1699,3 +1779,7 @@ TEST_CASE("iterator")
} }
} }
} }
#ifdef CONFIRM_COMPILATION_ERRORS
copy(src_span_static, dst_span_static);
#endif

View File

@ -17,10 +17,10 @@
#include <cstdlib> // for std::exit #include <cstdlib> // for std::exit
#include <gsl/span> // for span #include <gsl/span> // for span
int operator_subscript_no_throw() int operator_subscript_no_throw() noexcept
{ {
int arr[10]; int arr[10];
gsl::span<int> sp { arr }; const gsl::span<int> sp { arr };
return sp[11]; return sp[11];
} }
@ -30,7 +30,7 @@ void test_terminate()
std::exit(0); std::exit(0);
} }
void setup_termination_handler() void setup_termination_handler() noexcept
{ {
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -45,7 +45,7 @@ void setup_termination_handler()
} }
int main() int main() noexcept
{ {
setup_termination_handler(); setup_termination_handler();
operator_subscript_no_throw(); operator_subscript_no_throw();

View File

@ -16,10 +16,11 @@
#include <cstdlib> // for std::exit #include <cstdlib> // for std::exit
#include <gsl/gsl_util> // for narrow #include <gsl/gsl_util> // for narrow
#include <gsl/gsl_assert> // for get_terminate
int narrow_no_throw() int narrow_no_throw()
{ {
long long bigNumber = 0x0fffffffffffffff; const long long bigNumber = 0x0fffffffffffffff;
return gsl::narrow<int>(bigNumber); return gsl::narrow<int>(bigNumber);
} }
@ -28,7 +29,7 @@ void test_terminate()
std::exit(0); std::exit(0);
} }
void setup_termination_handler() void setup_termination_handler() noexcept
{ {
#if defined(_MSC_VER) #if defined(_MSC_VER)

View File

@ -14,6 +14,15 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
// Fix VS2015 build breaks in Release
#pragma warning(disable : 4702) // unreachable code
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_... #include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
#include <gsl/pointers> // for not_null, operator<, operator<=, operator> #include <gsl/pointers> // for not_null, operator<, operator<=, operator>
@ -25,7 +34,8 @@
#include <string> // for basic_string, operator==, string, operator<< #include <string> // for basic_string, operator==, string, operator<<
#include <typeinfo> // for type_info #include <typeinfo> // for type_info
namespace gsl { namespace gsl
{
struct fail_fast; struct fail_fast;
} // namespace gsl } // namespace gsl
@ -63,6 +73,7 @@ struct CustomPtr
template <typename T, typename U> template <typename T, typename U>
std::string operator==(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs) std::string operator==(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{ {
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return reinterpret_cast<const void*>(lhs.p_) == reinterpret_cast<const void*>(rhs.p_) ? "true" return reinterpret_cast<const void*>(lhs.p_) == reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false"; : "false";
} }
@ -70,6 +81,7 @@ std::string operator==(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U> template <typename T, typename U>
std::string operator!=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs) std::string operator!=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{ {
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return reinterpret_cast<const void*>(lhs.p_) != reinterpret_cast<const void*>(rhs.p_) ? "true" return reinterpret_cast<const void*>(lhs.p_) != reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false"; : "false";
} }
@ -77,6 +89,7 @@ std::string operator!=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U> template <typename T, typename U>
std::string operator<(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs) std::string operator<(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{ {
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return reinterpret_cast<const void*>(lhs.p_) < reinterpret_cast<const void*>(rhs.p_) ? "true" return reinterpret_cast<const void*>(lhs.p_) < reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false"; : "false";
} }
@ -84,6 +97,7 @@ std::string operator<(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U> template <typename T, typename U>
std::string operator>(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs) std::string operator>(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{ {
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return reinterpret_cast<const void*>(lhs.p_) > reinterpret_cast<const void*>(rhs.p_) ? "true" return reinterpret_cast<const void*>(lhs.p_) > reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false"; : "false";
} }
@ -91,6 +105,7 @@ std::string operator>(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U> template <typename T, typename U>
std::string operator<=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs) std::string operator<=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{ {
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return reinterpret_cast<const void*>(lhs.p_) <= reinterpret_cast<const void*>(rhs.p_) ? "true" return reinterpret_cast<const void*>(lhs.p_) <= reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false"; : "false";
} }
@ -98,6 +113,7 @@ std::string operator<=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U> template <typename T, typename U>
std::string operator>=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs) std::string operator>=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{ {
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
return reinterpret_cast<const void*>(lhs.p_) >= reinterpret_cast<const void*>(rhs.p_) ? "true" return reinterpret_cast<const void*>(lhs.p_) >= reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false"; : "false";
} }
@ -111,9 +127,19 @@ struct NonCopyableNonMovable
NonCopyableNonMovable& operator=(NonCopyableNonMovable&&) = delete; NonCopyableNonMovable& operator=(NonCopyableNonMovable&&) = delete;
}; };
bool helper(not_null<int*> p) { return *p == 12; } GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool helper_const(not_null<const int*> p) { return *p == 12; } bool helper(not_null<int*> p)
{
return *p == 12;
}
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool helper_const(not_null<const int*> p)
{
return *p == 12;
}
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullConstructors") TEST_CASE("TestNotNullConstructors")
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
@ -143,6 +169,7 @@ TEST_CASE("TestNotNullConstructors")
} }
template<typename T> template<typename T>
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
void ostream_helper(T v) void ostream_helper(T v)
{ {
not_null<T*> p(&v); not_null<T*> p(&v);
@ -173,7 +200,8 @@ TEST_CASE("TestNotNullostream")
ostream_helper<std::string>("string"); ostream_helper<std::string>("string");
} }
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullCasting") TEST_CASE("TestNotNullCasting")
{ {
MyBase base; MyBase base;
@ -233,9 +261,9 @@ TEST_CASE("TestNotNullRawPointerComparison")
CHECK((NotNull1(p1) <= NotNull1(p1)) == true); CHECK((NotNull1(p1) <= NotNull1(p1)) == true);
CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2)); CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2));
CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1)); CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1));
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullDereferenceOperator") TEST_CASE("TestNotNullDereferenceOperator")
{ {
{ {
@ -247,7 +275,7 @@ TEST_CASE("TestNotNullDereferenceOperator")
} }
{ {
int ints[1] = { 42 }; int ints[1] = {42};
CustomPtr<int> p1(&ints[0]); CustomPtr<int> p1(&ints[0]);
using NotNull1 = not_null<decltype(p1)>; using NotNull1 = not_null<decltype(p1)>;
@ -297,6 +325,7 @@ TEST_CASE("TestNotNullSharedPtrComparison")
CHECK((NotNullSp2(sp2) >= NotNullSp1(sp1)) == (sp2 >= sp1)); CHECK((NotNullSp2(sp2) >= NotNullSp1(sp1)) == (sp2 >= sp1));
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullCustomPtrComparison") TEST_CASE("TestNotNullCustomPtrComparison")
{ {
int ints[2] = {42, 43}; int ints[2] = {42, 43};
@ -329,8 +358,9 @@ TEST_CASE("TestNotNullCustomPtrComparison")
CHECK((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1)); CHECK((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1));
} }
#if defined(__cplusplus) && (__cplusplus >= 201703L) #if defined(__cplusplus) && (__cplusplus >= 201703L)
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullConstructorTypeDeduction") TEST_CASE("TestNotNullConstructorTypeDeduction")
{ {
{ {
@ -357,7 +387,7 @@ TEST_CASE("TestNotNullConstructorTypeDeduction")
{ {
auto workaround_macro = []() { auto workaround_macro = []() {
int* p1 = nullptr; int* p1 = nullptr;
not_null x{p1}; const not_null x{p1};
}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
@ -365,7 +395,7 @@ TEST_CASE("TestNotNullConstructorTypeDeduction")
{ {
auto workaround_macro = []() { auto workaround_macro = []() {
const int* p1 = nullptr; const int* p1 = nullptr;
not_null x{p1}; const not_null x{p1};
}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
@ -387,4 +417,62 @@ TEST_CASE("TestNotNullConstructorTypeDeduction")
} }
#endif // #if defined(__cplusplus) && (__cplusplus >= 201703L) #endif // #if defined(__cplusplus) && (__cplusplus >= 201703L)
TEST_CASE("TestMakeNotNull")
{
{
int i = 42;
const auto x = make_not_null(&i);
helper(make_not_null(&i));
helper_const(make_not_null(&i));
CHECK(*x == 42);
}
{
int i = 42;
int* p = &i;
const auto x = make_not_null(p);
helper(make_not_null(p));
helper_const(make_not_null(p));
CHECK(*x == 42);
}
{
const auto workaround_macro = []() {
int* p1 = nullptr;
const auto x = make_not_null(p1);
CHECK(*x == 42);
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
{
const auto workaround_macro = []() {
const int* p1 = nullptr;
const auto x = make_not_null(p1);
CHECK(*x == 42);
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
{
int* p = nullptr;
CHECK_THROWS_AS(helper(make_not_null(p)), fail_fast);
CHECK_THROWS_AS(helper_const(make_not_null(p)), fail_fast);
}
#ifdef CONFIRM_COMPILATION_ERRORS
{
CHECK_THROWS_AS(make_not_null(nullptr), fail_fast);
CHECK_THROWS_AS(helper(make_not_null(nullptr)), fail_fast);
CHECK_THROWS_AS(helper_const(make_not_null(nullptr)), fail_fast);
}
#endif
}
static_assert(std::is_nothrow_move_constructible<not_null<void *>>::value, "not_null must be no-throw move constructible"); static_assert(std::is_nothrow_move_constructible<not_null<void *>>::value, "not_null must be no-throw move constructible");

View File

@ -14,14 +14,25 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_... #include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
#include <gsl/pointers> // for owner #include <gsl/pointers> // for owner
using namespace gsl; using namespace gsl;
GSL_SUPPRESS(f.23) // NO-FORMAT: attribute
void f(int* i) { *i += 1; } void f(int* i) { *i += 1; }
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute // TODO: false positive
GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
TEST_CASE("basic_test") TEST_CASE("basic_test")
{ {
owner<int*> p = new int(120); owner<int*> p = new int(120);

View File

@ -0,0 +1,124 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
// Fix VS2015 build breaks in Release
#pragma warning(disable : 4702) // unreachable code
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
#include <gsl/pointers> // for not_null, operator<, operator<=, operator>
#include <samples/gsl_transition> // for sloppy_not_null
namespace gsl
{
struct fail_fast;
} // namespace gsl
using namespace gsl;
using namespace gsl_helpers;
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool helper(not_null<int*> p) { return *p == 12; }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool helper_const(not_null<const int*> p) { return *p == 12; }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool sloppy_helper(sloppy_not_null<int*> p) { return *p == 12; }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool sloppy_helper_const(sloppy_not_null<const int*> p) { return *p == 12; }
TEST_CASE("TestSloppyNotNull")
{
{
// raw ptr <-> sloppy_not_null
int x = 42;
const sloppy_not_null<int*> snn = &x;
sloppy_helper(&x);
sloppy_helper_const(&x);
CHECK(*snn == 42);
}
{
// sloppy_not_null -> sloppy_not_null
int x = 42;
sloppy_not_null<int*> snn1{&x};
const sloppy_not_null<int*> snn2{&x};
sloppy_helper(snn1);
sloppy_helper_const(snn1);
CHECK(snn1 == snn2);
}
{
// sloppy_not_null -> not_null
int x = 42;
sloppy_not_null<int*> snn{&x};
const not_null<int*> nn1 = snn;
const not_null<int*> nn2{snn};
helper(snn);
helper_const(snn);
CHECK(snn == nn1);
CHECK(snn == nn2);
}
{
// not_null -> sloppy_not_null
int x = 42;
not_null<int*> nn{&x};
const sloppy_not_null<int*> snn1{nn};
const sloppy_not_null<int*> snn2 = nn;
sloppy_helper(nn);
sloppy_helper_const(nn);
CHECK(snn1 == nn);
CHECK(snn2 == nn);
std::hash<sloppy_not_null<int*>> hash_snn;
std::hash<not_null<int*>> hash_nn;
CHECK(hash_nn(snn1) == hash_nn(nn));
CHECK(hash_snn(snn1) == hash_nn(nn));
CHECK(hash_nn(snn1) == hash_nn(snn2));
CHECK(hash_snn(snn1) == hash_snn(nn));
}
#ifdef CONFIRM_COMPILATION_ERRORS
{
sloppy_not_null<int*> p{nullptr};
}
#endif
}
static_assert(std::is_nothrow_move_constructible<sloppy_not_null<void*>>::value,
"sloppy_not_null must be no-throw move constructible");

View File

@ -14,6 +14,13 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426 26497) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_... #include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
#include <gsl/gsl_byte> // for byte #include <gsl/gsl_byte> // for byte
@ -45,8 +52,13 @@ struct BaseClass
struct DerivedClass : BaseClass struct DerivedClass : BaseClass
{ {
}; };
struct AddressOverloaded
{
AddressOverloaded operator&() const { return {}; }
};
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("default_constructor") TEST_CASE("default_constructor")
{ {
{ {
@ -81,6 +93,7 @@ TEST_CASE("default_constructor")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("size_optimization") TEST_CASE("size_optimization")
{ {
{ {
@ -94,56 +107,60 @@ TEST_CASE("size_optimization")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_nullptr_size_constructor") TEST_CASE("from_nullptr_size_constructor")
{ {
{ {
span<int> s{nullptr, static_cast<span<int>::index_type>(0)}; span<int> s{nullptr, narrow_cast<span<int>::index_type>(0)};
CHECK((s.size() == 0 && s.data() == nullptr)); CHECK((s.size() == 0 && s.data() == nullptr));
span<const int> cs{nullptr, static_cast<span<int>::index_type>(0)}; span<const int> cs{nullptr, narrow_cast<span<int>::index_type>(0)};
CHECK((cs.size() == 0 && cs.data() == nullptr)); CHECK((cs.size() == 0 && cs.data() == nullptr));
} }
{ {
span<int, 0> s{nullptr, static_cast<span<int>::index_type>(0)}; span<int, 0> s{nullptr, narrow_cast<span<int>::index_type>(0)};
CHECK((s.size() == 0 && s.data() == nullptr)); CHECK((s.size() == 0 && s.data() == nullptr));
span<const int, 0> cs{nullptr, static_cast<span<int>::index_type>(0)}; span<const int, 0> cs{nullptr, narrow_cast<span<int>::index_type>(0)};
CHECK((cs.size() == 0 && cs.data() == nullptr)); CHECK((cs.size() == 0 && cs.data() == nullptr));
} }
{ {
auto workaround_macro = []() { auto workaround_macro = []() {
span<int, 1> s{nullptr, static_cast<span<int>::index_type>(0)}; const span<int, 1> s{nullptr, narrow_cast<span<int>::index_type>(0)};
}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
{ {
auto workaround_macro = []() { span<int> s{nullptr, 1}; }; auto workaround_macro = []() { const span<int> s{nullptr, 1}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
auto const_workaround_macro = []() { span<const int> cs{nullptr, 1}; }; auto const_workaround_macro = []() { const span<const int> cs{nullptr, 1}; };
CHECK_THROWS_AS(const_workaround_macro(), fail_fast); CHECK_THROWS_AS(const_workaround_macro(), fail_fast);
} }
{ {
auto workaround_macro = []() { span<int, 0> s{nullptr, 1}; }; auto workaround_macro = []() { const span<int, 0> s{nullptr, 1}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
auto const_workaround_macro = []() { span<const int, 0> s{nullptr, 1}; }; auto const_workaround_macro = []() { const span<const int, 0> s{nullptr, 1}; };
CHECK_THROWS_AS(const_workaround_macro(), fail_fast); CHECK_THROWS_AS(const_workaround_macro(), fail_fast);
} }
{ {
span<int*> s{nullptr, static_cast<span<int>::index_type>(0)}; span<int*> s{nullptr, narrow_cast<span<int>::index_type>(0)};
CHECK((s.size() == 0 && s.data() == nullptr)); CHECK((s.size() == 0 && s.data() == nullptr));
span<const int*> cs{nullptr, static_cast<span<int>::index_type>(0)}; span<const int*> cs{nullptr, narrow_cast<span<int>::index_type>(0)};
CHECK((cs.size() == 0 && cs.data() == nullptr)); CHECK((cs.size() == 0 && cs.data() == nullptr));
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("from_pointer_length_constructor") TEST_CASE("from_pointer_length_constructor")
{ {
int arr[4] = {1, 2, 3, 4}; int arr[4] = {1, 2, 3, 4};
@ -164,7 +181,7 @@ TEST_CASE("from_pointer_length_constructor")
} }
} }
{ {
span<int> s = { &arr[i], 4-i }; span<int> s = { &arr[i], 4-narrow_cast<ptrdiff_t>(i) };
CHECK(s.size() == 4-i); CHECK(s.size() == 4-i);
CHECK(s.data() == &arr[i]); CHECK(s.data() == &arr[i]);
CHECK(s.empty() == (4-i == 0)); CHECK(s.empty() == (4-i == 0));
@ -186,13 +203,13 @@ TEST_CASE("from_pointer_length_constructor")
{ {
int* p = nullptr; int* p = nullptr;
span<int> s{p, static_cast<span<int>::index_type>(0)}; span<int> s{p, narrow_cast<span<int>::index_type>(0)};
CHECK((s.size() == 0 && s.data() == nullptr)); CHECK((s.size() == 0 && s.data() == nullptr));
} }
{ {
int* p = nullptr; int* p = nullptr;
auto workaround_macro = [=]() { span<int> s{p, 2}; }; auto workaround_macro = [=]() { const span<int> s{p, 2}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
@ -204,7 +221,7 @@ TEST_CASE("from_pointer_length_constructor")
{ {
int* p = nullptr; int* p = nullptr;
auto s = make_span(p, static_cast<span<int>::index_type>(0)); auto s = make_span(p, narrow_cast<span<int>::index_type>(0));
CHECK((s.size() == 0 && s.data() == nullptr)); CHECK((s.size() == 0 && s.data() == nullptr));
} }
@ -215,6 +232,8 @@ TEST_CASE("from_pointer_length_constructor")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_pointer_pointer_constructor") TEST_CASE("from_pointer_pointer_constructor")
{ {
int arr[4] = {1, 2, 3, 4}; int arr[4] = {1, 2, 3, 4};
@ -296,12 +315,12 @@ TEST_CASE("from_array_constructor")
int arr[5] = {1, 2, 3, 4, 5}; int arr[5] = {1, 2, 3, 4, 5};
{ {
span<int> s{arr}; const span<int> s{arr};
CHECK((s.size() == 5 && s.data() == &arr[0])); CHECK((s.size() == 5 && s.data() == &arr[0]));
} }
{ {
span<int, 5> s{arr}; const span<int, 5> s{arr};
CHECK((s.size() == 5 && s.data() == &arr[0])); CHECK((s.size() == 5 && s.data() == &arr[0]));
} }
@ -333,8 +352,8 @@ TEST_CASE("from_array_constructor")
} }
#endif #endif
{ {
span<int[3]> s{&(arr2d[0]), 1}; const span<int[3]> s{std::addressof(arr2d[0]), 1};
CHECK((s.size() == 1 && s.data() == &arr2d[0])); CHECK((s.size() == 1 && s.data() == std::addressof(arr2d[0])));
} }
int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
@ -362,26 +381,38 @@ TEST_CASE("from_array_constructor")
} }
#endif #endif
{ {
span<int[3][2]> s{&arr3d[0], 1}; const span<int[3][2]> s{std::addressof(arr3d[0]), 1};
CHECK((s.size() == 1 && s.data() == &arr3d[0])); CHECK((s.size() == 1 && s.data() == std::addressof(arr3d[0])));
} }
{ {
auto s = make_span(arr); const auto s = make_span(arr);
CHECK((s.size() == 5 && s.data() == &arr[0])); CHECK((s.size() == 5 && s.data() == std::addressof(arr[0])));
} }
{ {
auto s = make_span(&(arr2d[0]), 1); const auto s = make_span(std::addressof(arr2d[0]), 1);
CHECK((s.size() == 1 && s.data() == &arr2d[0])); CHECK((s.size() == 1 && s.data() == std::addressof(arr2d[0])));
} }
{ {
auto s = make_span(&arr3d[0], 1); const auto s = make_span(std::addressof(arr3d[0]), 1);
CHECK((s.size() == 1 && s.data() == &arr3d[0])); CHECK((s.size() == 1 && s.data() == std::addressof(arr3d[0])));
} }
AddressOverloaded ao_arr[5] = {};
{
const span<AddressOverloaded, 5> s{ao_arr};
CHECK((s.size() == 5 && s.data() == std::addressof(ao_arr[0])));
}
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
GSL_SUPPRESS(i.11) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("from_dynamic_array_constructor") TEST_CASE("from_dynamic_array_constructor")
{ {
double(*arr)[3][4] = new double[100][3][4]; double(*arr)[3][4] = new double[100][3][4];
@ -399,6 +430,8 @@ TEST_CASE("from_dynamic_array_constructor")
delete[] arr; delete[] arr;
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_std_array_constructor") TEST_CASE("from_std_array_constructor")
{ {
std::array<int, 4> arr = {1, 2, 3, 4}; std::array<int, 4> arr = {1, 2, 3, 4};
@ -419,6 +452,13 @@ TEST_CASE("from_std_array_constructor")
CHECK((cs.size() == narrow_cast<ptrdiff_t>(arr.size()) && cs.data() == arr.data())); CHECK((cs.size() == narrow_cast<ptrdiff_t>(arr.size()) && cs.data() == arr.data()));
} }
std::array<AddressOverloaded, 4> ao_arr{};
{
span<AddressOverloaded, 4> fs{ao_arr};
CHECK((fs.size() == narrow_cast<ptrdiff_t>(ao_arr.size()) && ao_arr.data() == fs.data()));
}
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {
span<int, 2> s{arr}; span<int, 2> s{arr};
@ -478,6 +518,7 @@ TEST_CASE("from_std_array_constructor")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_const_std_array_constructor") TEST_CASE("from_const_std_array_constructor")
{ {
const std::array<int, 4> arr = {1, 2, 3, 4}; const std::array<int, 4> arr = {1, 2, 3, 4};
@ -492,6 +533,13 @@ TEST_CASE("from_const_std_array_constructor")
CHECK((s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data())); CHECK((s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()));
} }
const std::array<AddressOverloaded, 4> ao_arr{};
{
span<const AddressOverloaded, 4> s{ao_arr};
CHECK((s.size() == narrow_cast<ptrdiff_t>(ao_arr.size()) && s.data() == ao_arr.data()));
}
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {
span<const int, 2> s{arr}; span<const int, 2> s{arr};
@ -521,6 +569,7 @@ TEST_CASE("from_const_std_array_constructor")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_std_array_const_constructor") TEST_CASE("from_std_array_const_constructor")
{ {
std::array<const int, 4> arr = {1, 2, 3, 4}; std::array<const int, 4> arr = {1, 2, 3, 4};
@ -561,6 +610,7 @@ TEST_CASE("from_std_array_const_constructor")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_container_constructor") TEST_CASE("from_container_constructor")
{ {
std::vector<int> v = {1, 2, 3}; std::vector<int> v = {1, 2, 3};
@ -653,6 +703,7 @@ TEST_CASE("from_container_constructor")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("from_convertible_span_constructor") TEST_CASE("from_convertible_span_constructor")
{ {
{ {
@ -690,6 +741,7 @@ TEST_CASE("from_convertible_span_constructor")
#endif #endif
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("copy_move_and_assignment") TEST_CASE("copy_move_and_assignment")
{ {
span<int> s1; span<int> s1;
@ -711,6 +763,7 @@ TEST_CASE("copy_move_and_assignment")
CHECK((s1.size() == 2 && s1.data() == &arr[1])); CHECK((s1.size() == 2 && s1.data() == &arr[1]));
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("first") TEST_CASE("first")
{ {
int arr[5] = {1, 2, 3, 4, 5}; int arr[5] = {1, 2, 3, 4, 5};
@ -749,6 +802,7 @@ TEST_CASE("first")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("last") TEST_CASE("last")
{ {
int arr[5] = {1, 2, 3, 4, 5}; int arr[5] = {1, 2, 3, 4, 5};
@ -786,6 +840,7 @@ TEST_CASE("last")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("subspan") TEST_CASE("subspan")
{ {
int arr[5] = {1, 2, 3, 4, 5}; int arr[5] = {1, 2, 3, 4, 5};
@ -867,6 +922,7 @@ TEST_CASE("subspan")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("at_call") TEST_CASE("at_call")
{ {
int arr[4] = {1, 2, 3, 4}; int arr[4] = {1, 2, 3, 4};
@ -886,6 +942,7 @@ TEST_CASE("at_call")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("operator_function_call") TEST_CASE("operator_function_call")
{ {
int arr[4] = {1, 2, 3, 4}; int arr[4] = {1, 2, 3, 4};
@ -905,6 +962,7 @@ TEST_CASE("operator_function_call")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("iterator_default_init") TEST_CASE("iterator_default_init")
{ {
span<int>::iterator it1; span<int>::iterator it1;
@ -912,6 +970,7 @@ TEST_CASE("iterator_default_init")
CHECK(it1 == it2); CHECK(it1 == it2);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("const_iterator_default_init") TEST_CASE("const_iterator_default_init")
{ {
span<int>::const_iterator it1; span<int>::const_iterator it1;
@ -919,6 +978,7 @@ TEST_CASE("const_iterator_default_init")
CHECK(it1 == it2); CHECK(it1 == it2);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("iterator_conversions") TEST_CASE("iterator_conversions")
{ {
span<int>::iterator badIt; span<int>::iterator badIt;
@ -941,6 +1001,7 @@ TEST_CASE("iterator_conversions")
CHECK(cit3 == s.cend()); CHECK(cit3 == s.cend());
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("iterator_comparisons") TEST_CASE("iterator_comparisons")
{ {
int a[] = {1, 2, 3, 4}; int a[] = {1, 2, 3, 4};
@ -988,6 +1049,7 @@ TEST_CASE("iterator_comparisons")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("begin_end") TEST_CASE("begin_end")
{ {
{ {
@ -1043,6 +1105,7 @@ TEST_CASE("begin_end")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("cbegin_cend") TEST_CASE("cbegin_cend")
{ {
{ {
@ -1095,6 +1158,7 @@ TEST_CASE("cbegin_cend")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("rbegin_rend") TEST_CASE("rbegin_rend")
{ {
{ {
@ -1137,6 +1201,7 @@ TEST_CASE("rbegin_rend")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("crbegin_crend") TEST_CASE("crbegin_crend")
{ {
{ {
@ -1176,6 +1241,7 @@ TEST_CASE("crbegin_crend")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("comparison_operators") TEST_CASE("comparison_operators")
{ {
{ {
@ -1296,6 +1362,7 @@ TEST_CASE("comparison_operators")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("as_bytes") TEST_CASE("as_bytes")
{ {
int a[] = {1, 2, 3, 4}; int a[] = {1, 2, 3, 4};
@ -1326,6 +1393,7 @@ TEST_CASE("as_bytes")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("as_writeable_bytes") TEST_CASE("as_writeable_bytes")
{ {
int a[] = {1, 2, 3, 4}; int a[] = {1, 2, 3, 4};
@ -1359,6 +1427,7 @@ TEST_CASE("as_writeable_bytes")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("fixed_size_conversions") TEST_CASE("fixed_size_conversions")
{ {
int arr[] = {1, 2, 3, 4}; int arr[] = {1, 2, 3, 4};
@ -1389,7 +1458,7 @@ TEST_CASE("fixed_size_conversions")
{ {
span<int> s = arr; span<int> s = arr;
auto f = [&]() { auto f = [&]() {
span<int, 2> s2 = s; const span<int, 2> s2 = s;
static_cast<void>(s2); static_cast<void>(s2);
}; };
CHECK_THROWS_AS(f(), fail_fast); CHECK_THROWS_AS(f(), fail_fast);
@ -1399,7 +1468,7 @@ TEST_CASE("fixed_size_conversions")
// you can convert statically // you can convert statically
{ {
const span<int, 2> s2 = {arr, 2}; const span<int, 2> s2 = {&arr[0], 2};
static_cast<void>(s2); static_cast<void>(s2);
} }
{ {
@ -1428,7 +1497,7 @@ TEST_CASE("fixed_size_conversions")
#endif #endif
{ {
auto f = [&]() { auto f = [&]() {
span<int, 4> _s4 = {arr2, 2}; const span<int, 4> _s4 = {arr2, 2};
static_cast<void>(_s4); static_cast<void>(_s4);
}; };
CHECK_THROWS_AS(f(), fail_fast); CHECK_THROWS_AS(f(), fail_fast);
@ -1437,12 +1506,13 @@ TEST_CASE("fixed_size_conversions")
// this should fail - we are trying to assign a small dynamic span to a fixed_size larger one // this should fail - we are trying to assign a small dynamic span to a fixed_size larger one
span<int> av = arr2; span<int> av = arr2;
auto f = [&]() { auto f = [&]() {
span<int, 4> _s4 = av; const span<int, 4> _s4 = av;
static_cast<void>(_s4); static_cast<void>(_s4);
}; };
CHECK_THROWS_AS(f(), fail_fast); CHECK_THROWS_AS(f(), fail_fast);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("interop_with_std_regex") TEST_CASE("interop_with_std_regex")
{ {
char lat[] = {'1', '2', '3', '4', '5', '6', 'E', 'F', 'G'}; char lat[] = {'1', '2', '3', '4', '5', '6', 'E', 'F', 'G'};
@ -1466,6 +1536,7 @@ TEST_CASE("interop_with_std_regex")
CHECK(match[0].second == (f_it + 1)); CHECK(match[0].second == (f_it + 1));
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("interop_with_gsl_at") TEST_CASE("interop_with_gsl_at")
{ {
int arr[5] = {1, 2, 3, 4, 5}; int arr[5] = {1, 2, 3, 4, 5};
@ -1479,3 +1550,4 @@ TEST_CASE("default_constructible")
CHECK((std::is_default_constructible<span<int, 0>>::value)); CHECK((std::is_default_constructible<span<int, 0>>::value));
CHECK((!std::is_default_constructible<span<int, 42>>::value)); CHECK((!std::is_default_constructible<span<int, 42>>::value));
} }

View File

@ -14,6 +14,13 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK... #include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK...
#include <gsl/gsl_byte> // for byte #include <gsl/gsl_byte> // for byte
@ -60,17 +67,20 @@ TEST_CASE("span_section")
const multi_span<int, 5, 10> av = as_multi_span(multi_span<int>{data}, dim<5>(), dim<10>()); const multi_span<int, 5, 10> av = as_multi_span(multi_span<int>{data}, dim<5>(), dim<10>());
const strided_span<int, 2> av_section_1 = av.section({1, 2}, {3, 4}); const strided_span<int, 2> av_section_1 = av.section({1, 2}, {3, 4});
CHECK(!av_section_1.empty());
CHECK((av_section_1[{0, 0}] == 12)); CHECK((av_section_1[{0, 0}] == 12));
CHECK((av_section_1[{0, 1}] == 13)); CHECK((av_section_1[{0, 1}] == 13));
CHECK((av_section_1[{1, 0}] == 22)); CHECK((av_section_1[{1, 0}] == 22));
CHECK((av_section_1[{2, 3}] == 35)); CHECK((av_section_1[{2, 3}] == 35));
const strided_span<int, 2> av_section_2 = av_section_1.section({1, 2}, {2, 2}); const strided_span<int, 2> av_section_2 = av_section_1.section({1, 2}, {2, 2});
CHECK(!av_section_2.empty());
CHECK((av_section_2[{0, 0}] == 24)); CHECK((av_section_2[{0, 0}] == 24));
CHECK((av_section_2[{0, 1}] == 25)); CHECK((av_section_2[{0, 1}] == 25));
CHECK((av_section_2[{1, 0}] == 34)); CHECK((av_section_2[{1, 0}] == 34));
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_constructors") TEST_CASE("strided_span_constructors")
{ {
// Check stride constructor // Check stride constructor
@ -271,6 +281,7 @@ TEST_CASE("strided_span_constructors")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_slice") TEST_CASE("strided_span_slice")
{ {
std::vector<int> data(5 * 10); std::vector<int> data(5 * 10);
@ -297,6 +308,7 @@ TEST_CASE("strided_span_slice")
CHECK(sav[4][9] == 49); CHECK(sav[4][9] == 49);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_column_major") TEST_CASE("strided_span_column_major")
{ {
// strided_span may be used to accommodate more peculiar // strided_span may be used to accommodate more peculiar
@ -329,6 +341,7 @@ TEST_CASE("strided_span_column_major")
CHECK((cm_sec[{2, 1}] == 15)); CHECK((cm_sec[{2, 1}] == 15));
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_bounds") TEST_CASE("strided_span_bounds")
{ {
int arr[] = {0, 1, 2, 3}; int arr[] = {0, 1, 2, 3};
@ -445,6 +458,7 @@ TEST_CASE("strided_span_bounds")
#endif #endif
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_type_conversion") TEST_CASE("strided_span_type_conversion")
{ {
int arr[] = {0, 1, 2, 3}; int arr[] = {0, 1, 2, 3};
@ -542,6 +556,8 @@ TEST_CASE("strided_span_type_conversion")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
TEST_CASE("empty_strided_spans") TEST_CASE("empty_strided_spans")
{ {
{ {
@ -549,6 +565,7 @@ TEST_CASE("empty_strided_spans")
strided_span<int, 1> empty_sav{empty_av, {0, 1}}; strided_span<int, 1> empty_sav{empty_av, {0, 1}};
CHECK(empty_sav.bounds().index_bounds() == multi_span_index<1>{0}); CHECK(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
CHECK(empty_sav.empty());
CHECK_THROWS_AS(empty_sav[0], fail_fast); CHECK_THROWS_AS(empty_sav[0], fail_fast);
CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast); CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast); CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast);
@ -574,6 +591,8 @@ TEST_CASE("empty_strided_spans")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
void iterate_every_other_element(multi_span<int, dynamic_range> av) void iterate_every_other_element(multi_span<int, dynamic_range> av)
{ {
// pick every other element // pick every other element
@ -599,6 +618,7 @@ void iterate_every_other_element(multi_span<int, dynamic_range> av)
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_section_iteration") TEST_CASE("strided_span_section_iteration")
{ {
int arr[8] = {4, 0, 5, 1, 6, 2, 7, 3}; int arr[8] = {4, 0, 5, 1, 6, 2, 7, 3};
@ -616,6 +636,11 @@ TEST_CASE("strided_span_section_iteration")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("dynamic_strided_span_section_iteration") TEST_CASE("dynamic_strided_span_section_iteration")
{ {
auto arr = new int[8]; auto arr = new int[8];
@ -630,6 +655,9 @@ TEST_CASE("dynamic_strided_span_section_iteration")
delete[] arr; delete[] arr;
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute // TODO: does not work
void iterate_second_slice(multi_span<int, dynamic_range, dynamic_range, dynamic_range> av) void iterate_second_slice(multi_span<int, dynamic_range, dynamic_range, dynamic_range> av)
{ {
const int expected[6] = {2, 3, 10, 11, 18, 19}; const int expected[6] = {2, 3, 10, 11, 18, 19};
@ -656,6 +684,9 @@ void iterate_second_slice(multi_span<int, dynamic_range, dynamic_range, dynamic_
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("strided_span_section_iteration_3d") TEST_CASE("strided_span_section_iteration_3d")
{ {
int arr[3][4][2]{}; int arr[3][4][2]{};
@ -670,6 +701,11 @@ TEST_CASE("strided_span_section_iteration_3d")
} }
} }
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
TEST_CASE("dynamic_strided_span_section_iteration_3d") TEST_CASE("dynamic_strided_span_section_iteration_3d")
{ {
const auto height = 12, width = 2; const auto height = 12, width = 2;
@ -702,6 +738,9 @@ TEST_CASE("dynamic_strided_span_section_iteration_3d")
delete[] arr; delete[] arr;
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("strided_span_conversion") TEST_CASE("strided_span_conversion")
{ {
// get an multi_span of 'c' values from the list of X's // get an multi_span of 'c' values from the list of X's
@ -720,7 +759,7 @@ TEST_CASE("strided_span_conversion")
auto d1 = narrow_cast<int>(sizeof(int)) * 12 / d2; auto d1 = narrow_cast<int>(sizeof(int)) * 12 / d2;
// convert to 4x12 array of bytes // convert to 4x12 array of bytes
auto av = as_multi_span(as_bytes(as_multi_span(arr, 4)), dim(d1), dim(d2)); auto av = as_multi_span(as_bytes(as_multi_span(&arr[0], 4)), dim(d1), dim(d2));
CHECK(av.bounds().index_bounds()[0] == 4); CHECK(av.bounds().index_bounds()[0] == 4);
CHECK(av.bounds().index_bounds()[1] == 12); CHECK(av.bounds().index_bounds()[1] == 12);

View File

@ -14,6 +14,13 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_... #include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
#include <gsl/gsl_assert> // for Expects, fail_fast (ptr only) #include <gsl/gsl_assert> // for Expects, fail_fast (ptr only)
@ -37,6 +44,8 @@ namespace generic
{ {
template <typename CharT> template <typename CharT>
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(f.23) // NO-FORMAT: attribute
auto strlen(const CharT* s) auto strlen(const CharT* s)
{ {
auto p = s; auto p = s;
@ -45,13 +54,15 @@ auto strlen(const CharT* s)
} }
template <typename CharT> template <typename CharT>
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
auto strnlen(const CharT* s, std::size_t n) auto strnlen(const CharT* s, std::size_t n)
{ {
return std::find(s, s + n, CharT(0)) - s; return std::find(s, s + n, CharT{0}) - s;
} }
} // namespace generic } // namespace generic
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestLiteralConstruction") TEST_CASE("TestLiteralConstruction")
{ {
cwstring_span<> v = ensure_z(L"Hello"); cwstring_span<> v = ensure_z(L"Hello");
@ -61,6 +72,7 @@ TEST_CASE("TestLiteralConstruction")
wstring_span<> v2 = ensure0(L"Hello"); wstring_span<> v2 = ensure0(L"Hello");
#endif #endif
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestConstructFromStdString") TEST_CASE("TestConstructFromStdString")
{ {
@ -69,6 +81,7 @@ TEST_CASE("TestConstructFromStdString")
CHECK(v.length() == static_cast<cstring_span<>::index_type>(s.length())); CHECK(v.length() == static_cast<cstring_span<>::index_type>(s.length()));
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestConstructFromStdVector") TEST_CASE("TestConstructFromStdVector")
{ {
std::vector<char> vec(5, 'h'); std::vector<char> vec(5, 'h');
@ -76,6 +89,7 @@ TEST_CASE("TestConstructFromStdVector")
CHECK(v.length() == static_cast<string_span<>::index_type>(vec.size())); CHECK(v.length() == static_cast<string_span<>::index_type>(vec.size()));
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestStackArrayConstruction") TEST_CASE("TestStackArrayConstruction")
{ {
wchar_t stack_string[] = L"Hello"; wchar_t stack_string[] = L"Hello";
@ -101,6 +115,7 @@ TEST_CASE("TestStackArrayConstruction")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestConstructFromConstCharPointer") TEST_CASE("TestConstructFromConstCharPointer")
{ {
const char* s = "Hello"; const char* s = "Hello";
@ -108,6 +123,7 @@ TEST_CASE("TestConstructFromConstCharPointer")
CHECK(v.length() == 5); CHECK(v.length() == 5);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestConversionToConst") TEST_CASE("TestConversionToConst")
{ {
char stack_string[] = "Hello"; char stack_string[] = "Hello";
@ -116,6 +132,7 @@ TEST_CASE("TestConversionToConst")
CHECK(v.length() == v2.length()); CHECK(v.length() == v2.length());
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestConversionFromConst") TEST_CASE("TestConversionFromConst")
{ {
char stack_string[] = "Hello"; char stack_string[] = "Hello";
@ -127,6 +144,7 @@ TEST_CASE("TestConversionFromConst")
#endif #endif
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestToString") TEST_CASE("TestToString")
{ {
auto s = gsl::to_string(cstring_span<>{}); auto s = gsl::to_string(cstring_span<>{});
@ -139,6 +157,7 @@ TEST_CASE("TestToString")
CHECK(s2.length() == 5); CHECK(s2.length() == 5);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestToBasicString") TEST_CASE("TestToBasicString")
{ {
auto s = gsl::to_basic_string<char, std::char_traits<char>, ::std::allocator<char>>( auto s = gsl::to_basic_string<char, std::char_traits<char>, ::std::allocator<char>>(
@ -152,6 +171,8 @@ TEST_CASE("TestToBasicString")
CHECK(s2.length() == 5); CHECK(s2.length() == 5);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
TEST_CASE("EqualityAndImplicitConstructors") TEST_CASE("EqualityAndImplicitConstructors")
{ {
{ {
@ -378,6 +399,8 @@ TEST_CASE("EqualityAndImplicitConstructors")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
TEST_CASE("ComparisonAndImplicitConstructors") TEST_CASE("ComparisonAndImplicitConstructors")
{ {
{ {
@ -448,6 +471,12 @@ TEST_CASE("ComparisonAndImplicitConstructors")
CHECK(span >= string_span<>(vec)); CHECK(span >= string_span<>(vec));
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("ConstrutorsEnsureZ") TEST_CASE("ConstrutorsEnsureZ")
{ {
// remove z from literals // remove z from literals
@ -478,6 +507,8 @@ TEST_CASE("ConstrutorsEnsureZ")
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
TEST_CASE("Constructors") TEST_CASE("Constructors")
{ {
// creating cstring_span // creating cstring_span
@ -884,6 +915,8 @@ czstring_span<> CreateTempName(string_span<> span)
return {ret}; return {ret};
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("zstring") TEST_CASE("zstring")
{ {
@ -904,7 +937,7 @@ TEST_CASE("zstring")
char buf[1]; char buf[1];
buf[0] = 'a'; buf[0] = 'a';
auto workaround_macro = [&]() { zstring_span<> zspan({buf, 1}); }; auto workaround_macro = [&]() { const zstring_span<> zspan({buf, 1}); };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
@ -938,6 +971,8 @@ cwzstring_span<> CreateTempNameW(wstring_span<> span)
return {ret}; return {ret};
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("wzstring") TEST_CASE("wzstring")
{ {
@ -958,7 +993,7 @@ TEST_CASE("wzstring")
wchar_t buf[1]; wchar_t buf[1];
buf[0] = L'a'; buf[0] = L'a';
const auto workaround_macro = [&]() { wzstring_span<> zspan({buf, 1}); }; const auto workaround_macro = [&]() { const wzstring_span<> zspan({buf, 1}); };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
@ -992,6 +1027,8 @@ cu16zstring_span<> CreateTempNameU16(u16string_span<> span)
return {ret}; return {ret};
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("u16zstring") TEST_CASE("u16zstring")
{ {
@ -1012,7 +1049,7 @@ TEST_CASE("u16zstring")
char16_t buf[1]; char16_t buf[1];
buf[0] = u'a'; buf[0] = u'a';
const auto workaround_macro = [&]() { u16zstring_span<> zspan({buf, 1}); }; const auto workaround_macro = [&]() { const u16zstring_span<> zspan({buf, 1}); };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
@ -1046,6 +1083,8 @@ cu32zstring_span<> CreateTempNameU32(u32string_span<> span)
return {ret}; return {ret};
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("u32zstring") TEST_CASE("u32zstring")
{ {
@ -1066,7 +1105,7 @@ TEST_CASE("u32zstring")
char32_t buf[1]; char32_t buf[1];
buf[0] = u'a'; buf[0] = u'a';
const auto workaround_macro = [&]() { u32zstring_span<> zspan({buf, 1}); }; const auto workaround_macro = [&]() { const u32zstring_span<> zspan({buf, 1}); };
CHECK_THROWS_AS(workaround_macro(), fail_fast); CHECK_THROWS_AS(workaround_macro(), fail_fast);
} }
@ -1090,6 +1129,8 @@ TEST_CASE("Issue305")
CHECK(foo["bar"] == 1); CHECK(foo["bar"] == 1);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
TEST_CASE("char16_t type") TEST_CASE("char16_t type")
{ {
gsl::cu16string_span<> ss1 = gsl::ensure_z(u"abc"); gsl::cu16string_span<> ss1 = gsl::ensure_z(u"abc");
@ -1131,6 +1172,8 @@ TEST_CASE("char16_t type")
CHECK(ss8 != ss9); CHECK(ss8 != ss9);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
TEST_CASE("char32_t type") TEST_CASE("char32_t type")
{ {
gsl::cu32string_span<> ss1 = gsl::ensure_z(U"abc"); gsl::cu32string_span<> ss1 = gsl::ensure_z(U"abc");
@ -1168,6 +1211,7 @@ TEST_CASE("char32_t type")
CHECK(ss8 != ss9); CHECK(ss8 != ss9);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("as_bytes") TEST_CASE("as_bytes")
{ {
cwzstring_span<> v(L"qwerty"); cwzstring_span<> v(L"qwerty");
@ -1177,6 +1221,7 @@ TEST_CASE("as_bytes")
CHECK(bs.size() == s.size_bytes()); CHECK(bs.size() == s.size_bytes());
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("as_writeable_bytes") TEST_CASE("as_writeable_bytes")
{ {
wchar_t buf[]{L"qwerty"}; wchar_t buf[]{L"qwerty"};

View File

@ -15,4 +15,12 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define CATCH_CONFIG_MAIN #define CATCH_CONFIG_MAIN
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26401 26409 26415 26418 26426 26429 26432 26433 26434 26435 26436 26439 26440 26443 26444 26446 26447 26451 26460 26461 26466 26472 26481 26482 26485 26492 26493 26494 26495 26496 26497) // from catch
#endif // _MSC_VER
#include <catch/catch.hpp> #include <catch/catch.hpp>

View File

@ -14,6 +14,13 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_... #include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
#include <gsl/gsl_util> // for narrow, finally, narrow_cast, narrowing_e... #include <gsl/gsl_util> // for narrow, finally, narrow_cast, narrowing_e...
@ -85,6 +92,7 @@ TEST_CASE("finally_function_ptr")
CHECK(j == 1); CHECK(j == 1);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("narrow_cast") TEST_CASE("narrow_cast")
{ {
int n = 120; int n = 120;
@ -96,6 +104,7 @@ TEST_CASE("narrow_cast")
CHECK(uc == 44); CHECK(uc == 44);
} }
GSL_SUPPRESS(con.5) // NO-FORMAT: attribute
TEST_CASE("narrow") TEST_CASE("narrow")
{ {
int n = 120; int n = 120;