Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Daniel Donenfeld 2019-02-06 18:15:51 -08:00
commit c8438976db
23 changed files with 639 additions and 400 deletions

View File

@ -163,6 +163,28 @@ matrix:
- env: COMPILER=clang++-6.0 BUILD_TYPE=Release GSL_CXX_STANDARD=17 - env: COMPILER=clang++-6.0 BUILD_TYPE=Release GSL_CXX_STANDARD=17
addons: *clang60 addons: *clang60
# Clang 7.0
- env: COMPILER=clang++-7 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang70
apt:
packages:
- clang-7
- g++-7
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-7
- env: COMPILER=clang++-7 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang70
# Clang 7.0 c++17
- env: COMPILER=clang++-7 BUILD_TYPE=Debug GSL_CXX_STANDARD=17
addons: *clang70
- env: COMPILER=clang++-7 BUILD_TYPE=Release GSL_CXX_STANDARD=17
addons: *clang70
########################################################################## ##########################################################################
# GCC on Linux # GCC on Linux
########################################################################## ##########################################################################

View File

@ -67,7 +67,7 @@ else()
endif() endif()
if ((CMAKE_VERSION GREATER 3.7.9) OR (CMAKE_VERSION EQUAL 3.7.9)) if (CMAKE_VERSION VERSION_GREATER 3.7.8)
if (MSVC_IDE) if (MSVC_IDE)
option(VS_ADD_NATIVE_VISUALIZERS "Configure project to use Visual Studio native visualizers" TRUE) option(VS_ADD_NATIVE_VISUALIZERS "Configure project to use Visual Studio native visualizers" TRUE)
else() else()

View File

@ -27,9 +27,14 @@ The test suite that exercises GSL has been built and passes successfully on the
* Windows using Visual Studio 2015 * Windows using Visual Studio 2015
* Windows using Visual Studio 2017 * Windows using Visual Studio 2017
* Windows using Clang/LLVM 3.6 * Windows using Clang/LLVM 3.6
* Windows using Clang/LLVM 7.0.0
* Windows using GCC 5.1 * Windows using GCC 5.1
* Windows using Intel C++ Compiler 18.0 * Windows using Intel C++ Compiler 18.0
* GNU/Linux using Clang/LLVM 3.6 * GNU/Linux using Clang/LLVM 3.6-3.9
* GNU/Linux using Clang/LLVM 4.0
* GNU/Linux using Clang/LLVM 5.0
* GNU/Linux using Clang/LLVM 6.0
* GNU/Linux using Clang/LLVM 7.0
* GNU/Linux using GCC 5.1 * GNU/Linux using GCC 5.1
* OS X Yosemite using Xcode with Apple Clang 7.0.0.7000072 * OS X Yosemite using Xcode with Apple Clang 7.0.0.7000072
* OS X Yosemite using GCC-5.2.0 * OS X Yosemite using GCC-5.2.0

View File

@ -20,44 +20,108 @@ image:
environment: environment:
access_token: access_token:
secure: JoKQ6wDekwtEk9su/zJWT12TtHMsHAacSLnPe47/SV22BAfVSMMR8VCyDF/W9bE2 secure: JoKQ6wDekwtEk9su/zJWT12TtHMsHAacSLnPe47/SV22BAfVSMMR8VCyDF/W9bE2
NINJA_TAG: v1.8.2
NINJA_SHA512: 9B9CE248240665FCD6404B989F3B3C27ED9682838225E6DC9B67B551774F251E4FF8A207504F941E7C811E7A8BE1945E7BCB94472A335EF15E23A0200A32E6D5
NINJA_PATH: C:\Tools\ninja\ninja-%NINJA_TAG%
VCVAR2015: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat'
VCVAR2017: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat'
matrix: matrix:
- GSL_CXX_STANDARD: 14 - GSL_CXX_STANDARD: 14
USE_TOOLSET: MSVC
USE_GENERATOR: MSBuild
- GSL_CXX_STANDARD: 17 - GSL_CXX_STANDARD: 17
USE_TOOLSET: MSVC
USE_GENERATOR: MSBuild
- GSL_CXX_STANDARD: 14
USE_TOOLSET: LLVM
USE_GENERATOR: Ninja
- GSL_CXX_STANDARD: 17
USE_TOOLSET: LLVM
USE_GENERATOR: Ninja
matrix: matrix:
exclude: exclude:
- image: Visual Studio 2015 - image: Visual Studio 2015
GSL_CXX_STANDARD: 17 GSL_CXX_STANDARD: 17
- image: Visual Studio 2015
USE_TOOLSET: LLVM
USE_GENERATOR: MSBuild
cache: cache:
- C:\cmake-3.8.0-win32-x86 - C:\cmake-3.8.0-win32-x86
- C:\Tools\ninja
install: install:
- ps: | - ps: |
if (![IO.File]::Exists("C:\cmake-3.8.0-win32-x86\bin\cmake.exe")) { if (![IO.File]::Exists("$env:NINJA_PATH\ninja.exe")) {
Start-FileDownload 'https://cmake.org/files/v3.8/cmake-3.8.0-win32-x86.zip' Start-FileDownload `
7z x -y cmake-3.8.0-win32-x86.zip -oC:\ "https://github.com/ninja-build/ninja/releases/download/$env:NINJA_TAG/ninja-win.zip"
$hash = (Get-FileHash ninja-win.zip -Algorithm SHA512).Hash
if ($env:NINJA_SHA512 -eq $hash) {
7z e -y -bso0 ninja-win.zip -o"$env:NINJA_PATH"
} else { Write-Warning "Ninja download hash changed!"; Write-Output "$hash" }
}
if ([IO.File]::Exists("$env:NINJA_PATH\ninja.exe")) {
$env:PATH = "$env:NINJA_PATH;$env:PATH"
} else { Write-Warning "Failed to find ninja.exe in expected location." }
if ($env:USE_TOOLSET -ne "LLVM") {
if (![IO.File]::Exists("C:\cmake-3.8.0-win32-x86\bin\cmake.exe")) {
Start-FileDownload 'https://cmake.org/files/v3.8/cmake-3.8.0-win32-x86.zip'
7z x -y -bso0 cmake-3.8.0-win32-x86.zip -oC:\
}
$env:PATH="C:\cmake-3.8.0-win32-x86\bin;$env:PATH"
} }
$env:PATH="C:\cmake-3.8.0-win32-x86\bin;$env:PATH"
before_build: before_build:
- ps: | - ps: |
mkdir build if ("$env:USE_GENERATOR" -eq "Ninja") {
cd build $GeneratorFlags = '-k 10'
$Architecture = $env:PLATFORM
if ("$env:APPVEYOR_JOB_NAME" -match "Image: Visual Studio 2015") { if ("$env:APPVEYOR_BUILD_WORKER_IMAGE" -eq "Visual Studio 2015") {
$env:generator="Visual Studio 14 2015" $env:VCVARSALL = "`"$env:VCVAR2015`" $Architecture"
} else {
$env:VCVARSALL = "`"$env:VCVAR2017`" $Architecture"
}
$env:CMakeGenFlags = "-G Ninja -DGSL_CXX_STANDARD=$env:GSL_CXX_STANDARD -DGSL_ASM_FOLDER=`"$($env:APPVEYOR_BUILD_WORKER_IMAGE)_$($env:GSL_CXX_STANDARD)_$($env:USE_TOOLSET)_$($env:PLATFORM)_$($env:CONFIGURATION)`""
} else { } else {
$env:generator="Visual Studio 15 2017" $GeneratorFlags = '/m /v:minimal'
if ("$env:APPVEYOR_BUILD_WORKER_IMAGE" -eq "Visual Studio 2015") {
$Generator = 'Visual Studio 14 2015'
} else {
$Generator = 'Visual Studio 15 2017'
}
if ("$env:PLATFORM" -eq "x86") {
$Architecture = "Win32"
} else {
$Architecture = "x64"
}
if ("$env:USE_TOOLSET" -eq "LLVM") {
$env:CMakeGenFlags = "-G `"$Generator`" -A $Architecture -T llvm -DGSL_CXX_STANDARD=$env:GSL_CXX_STANDARD -DGSL_ASM_FOLDER=`"$($env:APPVEYOR_BUILD_WORKER_IMAGE)_$($env:GSL_CXX_STANDARD)_$($env:USE_TOOLSET)_$($env:PLATFORM)_$($env:CONFIGURATION)`""
} else {
$env:CMakeGenFlags = "-G `"$Generator`" -A $Architecture -DGSL_CXX_STANDARD=$env:GSL_CXX_STANDARD -DGSL_ASM_FOLDER=`"$($env:APPVEYOR_BUILD_WORKER_IMAGE)_$($env:GSL_CXX_STANDARD)_$($env:USE_TOOLSET)_$($env:PLATFORM)_$($env:CONFIGURATION)`""
}
} }
if ($env:PLATFORM -eq "x64") { if ("$env:USE_TOOLSET" -eq "LLVM") {
$env:generator="$env:generator Win64" $env:CC = "clang-cl"
$env:CXX = "clang-cl"
if ("$env:PLATFORM" -eq "x86") {
$env:CFLAGS = "-m32";
$env:CXXFLAGS = "-m32";
} else {
$env:CFLAGS = "-m64";
$env:CXXFLAGS = "-m64";
}
} }
echo generator="$env:generator" $env:CMakeBuildFlags = "--config $env:CONFIGURATION -- $GeneratorFlags"
cmake .. -G "$env:generator" -DGSL_CXX_STANDARD="$env:GSL_CXX_STANDARD" -DGSL_ASM_FOLDER="$($env:APPVEYOR_BUILD_WORKER_IMAGE)_$($env:GSL_CXX_STANDARD)_$($env:PLATFORM)_$($env:CONFIGURATION)" - mkdir build
- cd build
- if %USE_GENERATOR%==Ninja (call %VCVARSALL%)
- echo %CMakeGenFlags%
- cmake .. %CMakeGenFlags%
build_script: build_script:
- cmake --build . --config %CONFIGURATION% -- /m /v:minimal - echo %CMakeBuildFlags%
- cmake --build . %CMakeBuildFlags%
test_script: test_script:
- ctest -j2 - ctest -j2

View File

@ -22,17 +22,17 @@
// //
// make suppress attributes parse for some compilers // make suppress attributes parse for some compilers
// Hopefully temporary until suppresion standardization occurs // Hopefully temporary until suppression standardization occurs
// //
#if defined (_MSC_VER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#if defined(__clang__) #if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] #define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else #else
#if defined(_MSC_VER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x) #define GSL_SUPPRESS(x)
#endif // __clang__
#endif // _MSC_VER #endif // _MSC_VER
#endif // __clang__
// //
// Temporary until MSVC STL supports no-exceptions mode. // Temporary until MSVC STL supports no-exceptions mode.
@ -42,6 +42,12 @@
#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND #define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
#include <intrin.h> #include <intrin.h>
#define RANGE_CHECKS_FAILURE 0 #define RANGE_CHECKS_FAILURE 0
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winvalid-noreturn"
#endif
#endif #endif
// //
@ -98,7 +104,7 @@ namespace details
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) #if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
typedef void (__cdecl *terminate_handler)(); typedef void (__cdecl *terminate_handler)();
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute GSL_SUPPRESS(f.6) // NO-FORMAT: attribute
[[noreturn]] inline void __cdecl default_terminate_handler() [[noreturn]] inline void __cdecl default_terminate_handler()
{ {
@ -138,7 +144,7 @@ namespace details
throw std::forward<Exception>(exception); throw std::forward<Exception>(exception);
} }
#endif #endif // GSL_TERMINATE_ON_CONTRACT_VIOLATION
} // namespace details } // namespace details
} // namespace gsl } // namespace gsl
@ -159,9 +165,13 @@ namespace details
#define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond) #define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond)
#endif #endif // GSL_THROW_ON_CONTRACT_VIOLATION
#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond) #define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond)
#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond) #define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif // GSL_CONTRACTS_H #endif // GSL_CONTRACTS_H

View File

@ -19,17 +19,17 @@
// //
// make suppress attributes work for some compilers // make suppress attributes work for some compilers
// Hopefully temporary until suppresion standardization occurs // Hopefully temporary until suppression standardization occurs
// //
#if defined(_MSC_VER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#if defined(__clang__) #if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] #define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else #else
#if defined(_MSC_VER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x) #define GSL_SUPPRESS(x)
#endif // __clang__
#endif // _MSC_VER #endif // _MSC_VER
#endif // __clang__
#include <type_traits> #include <type_traits>
@ -79,7 +79,7 @@
#endif // _MSC_VER #endif // _MSC_VER
// Use __may_alias__ attribute on gcc and clang // Use __may_alias__ attribute on gcc and clang
#if defined __clang__ || (__GNUC__ > 5) #if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5)
#define byte_may_alias __attribute__((__may_alias__)) #define byte_may_alias __attribute__((__may_alias__))
#else // defined __clang__ || defined __GNUC__ #else // defined __clang__ || defined __GNUC__
#define byte_may_alias #define byte_may_alias

View File

@ -26,7 +26,7 @@
#include <type_traits> // for is_signed, integral_constant #include <type_traits> // for is_signed, integral_constant
#include <utility> // for forward #include <utility> // for forward
#if defined(_MSC_VER) #if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4127) // conditional expression is constant
@ -37,6 +37,12 @@
#endif // _MSC_VER < 1910 #endif // _MSC_VER < 1910
#endif // _MSC_VER #endif // _MSC_VER
#if (defined(_MSC_VER) && _MSC_VER < 1910) || (!defined(__clang__) && defined(__GNUC__) && __GUNC__ < 6)
#define GSL_CONSTEXPR_NARROW 0
#else
#define GSL_CONSTEXPR_NARROW 1
#endif
namespace gsl namespace gsl
{ {
// //
@ -111,6 +117,9 @@ namespace details
template <class T, class U> template <class T, class U>
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false) GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
#if GSL_CONSTEXPR_NARROW
constexpr
#endif
T narrow(U u) noexcept(false) T narrow(U u) noexcept(false)
{ {
T t = narrow_cast<T>(u); T t = narrow_cast<T>(u);
@ -152,7 +161,7 @@ constexpr T at(const std::initializer_list<T> cont, const index i)
} // namespace gsl } // namespace gsl
#if defined(_MSC_VER) #if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#undef constexpr #undef constexpr
#pragma pop_macro("constexpr") #pragma pop_macro("constexpr")

View File

@ -37,7 +37,7 @@
#include <type_traits> // for enable_if_t, remove_cv_t, is_same, is_co... #include <type_traits> // for enable_if_t, remove_cv_t, is_same, is_co...
#include <utility> #include <utility>
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
// turn off some warnings that are noisy about our Expects statements // turn off some warnings that are noisy about our Expects statements
#pragma warning(push) #pragma warning(push)
@ -62,7 +62,7 @@
// compiletime, so the compiler wouldn't have to warn indiscriminently, but // compiletime, so the compiler wouldn't have to warn indiscriminently, but
// could check if the source value actually doesn't fit into the target type // could check if the source value actually doesn't fit into the target type
// and only warn in those cases. // and only warn in those cases.
#if __GNUC__ > 6 #if defined(__GNUC__) && __GNUC__ > 6
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wsign-conversion"
#endif #endif
@ -412,6 +412,7 @@ namespace details
return totalSize() / this->Base::totalSize(); return totalSize() / this->Base::totalSize();
} }
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
constexpr size_type elementNum(std::size_t dim) const noexcept constexpr size_type elementNum(std::size_t dim) const noexcept
{ {
if (dim > 0) if (dim > 0)
@ -595,7 +596,6 @@ public:
using sliced_type = static_bounds<RestRanges...>; using sliced_type = static_bounds<RestRanges...>;
using mapping_type = contiguous_mapping_tag; using mapping_type = contiguous_mapping_tag;
constexpr static_bounds(const static_bounds&) noexcept = default;
constexpr static_bounds() /*noexcept*/ = default; constexpr static_bounds() /*noexcept*/ = default;
template <typename SourceType, typename TargetType, std::size_t Rank> template <typename SourceType, typename TargetType, std::size_t Rank>
@ -1886,6 +1886,8 @@ public:
auto d = narrow_cast<size_type>(sizeof(OtherValueType) / sizeof(value_type)); auto d = narrow_cast<size_type>(sizeof(OtherValueType) / sizeof(value_type));
const size_type size = this->bounds().total_size() / d; const size_type size = this->bounds().total_size() / d;
GSL_SUPPRESS(type.3) // NO-FORMAT: attribute
return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())), return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())),
size, size,
bounds_type{resize_extent(this->bounds().index_bounds(), d), bounds_type{resize_extent(this->bounds().index_bounds(), d),
@ -2273,7 +2275,7 @@ general_span_iterator<Span> operator+(typename general_span_iterator<Span>::diff
} // namespace gsl } // namespace gsl
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#undef constexpr #undef constexpr
@ -2284,7 +2286,7 @@ general_span_iterator<Span> operator+(typename general_span_iterator<Span>::diff
#endif // _MSC_VER #endif // _MSC_VER
#if __GNUC__ > 6 #if defined(__GNUC__) && __GNUC__ > 6
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif // __GNUC__ > 6 #endif // __GNUC__ > 6

View File

@ -25,7 +25,7 @@
#include <system_error> // for hash #include <system_error> // for hash
#include <type_traits> // for enable_if_t, is_convertible, is_assignable #include <type_traits> // for enable_if_t, is_convertible, is_assignable
#if defined(_MSC_VER) && _MSC_VER < 1910 #if defined(_MSC_VER) && _MSC_VER < 1910 && !defined(__clang__)
#pragma push_macro("constexpr") #pragma push_macro("constexpr")
#define constexpr /*constexpr*/ #define constexpr /*constexpr*/
@ -72,13 +72,13 @@ public:
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr."); static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>> template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr explicit not_null(U&& u) : ptr_(std::forward<U>(u)) constexpr not_null(U&& u) : ptr_(std::forward<U>(u))
{ {
Expects(ptr_ != nullptr); Expects(ptr_ != nullptr);
} }
template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>> template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
constexpr explicit not_null(T u) : ptr_(u) constexpr not_null(T u) : ptr_(u)
{ {
Expects(ptr_ != nullptr); Expects(ptr_ != nullptr);
} }
@ -121,7 +121,7 @@ private:
template <class T> template <class T>
auto make_not_null(T&& t) { auto make_not_null(T&& t) {
return gsl::not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)}; return not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
} }
template <class T> template <class T>
@ -189,10 +189,106 @@ struct hash<gsl::not_null<T>>
} // namespace std } // namespace std
#if defined(_MSC_VER) && _MSC_VER < 1910 namespace gsl
{
//
// strict_not_null
//
// Restricts a pointer or smart pointer to only hold non-null values,
//
// - provides a strict (i.e. explicit contructor from T) wrapper of not_null
// - to be used for new code that wishes the design to be cleaner and make not_null
// checks intentional, or in old code that would like to make the transition.
//
// To make the transition from not_null, incrementally replace not_null
// by strict_not_null and fix compilation errors
//
// Expect to
// - remove all unneded conversions from raw pointer to not_null and back
// - make API clear by specifyning not_null in parameters where needed
// - remove unnesessary asserts
//
template <class T>
class strict_not_null: public not_null<T>
{
public:
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr explicit strict_not_null(U&& u) :
not_null<T>(std::forward<U>(u))
{}
template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
constexpr explicit strict_not_null(T u) :
not_null<T>(u)
{}
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr strict_not_null(const not_null<U>& other) :
not_null<T>(other)
{}
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr strict_not_null(const strict_not_null<U>& other) :
not_null<T>(other)
{}
strict_not_null(strict_not_null&& other) = default;
strict_not_null(const strict_not_null& other) = default;
strict_not_null& operator=(const strict_not_null& other) = default;
strict_not_null& operator=(const not_null<T>& other)
{
not_null<T>::operator=(other);
return *this;
}
// prevents compilation when someone attempts to assign a null pointer constant
strict_not_null(std::nullptr_t) = delete;
strict_not_null& operator=(std::nullptr_t) = delete;
// unwanted operators...pointers only point to single objects!
strict_not_null& operator++() = delete;
strict_not_null& operator--() = delete;
strict_not_null operator++(int) = delete;
strict_not_null operator--(int) = delete;
strict_not_null& operator+=(std::ptrdiff_t) = delete;
strict_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 strict_not_null<T>&, const strict_not_null<U>&) = delete;
template <class T>
strict_not_null<T> operator-(const strict_not_null<T>&, std::ptrdiff_t) = delete;
template <class T>
strict_not_null<T> operator+(const strict_not_null<T>&, std::ptrdiff_t) = delete;
template <class T>
strict_not_null<T> operator+(std::ptrdiff_t, const strict_not_null<T>&) = delete;
template <class T>
auto make_strict_not_null(T&& t) {
return strict_not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
}
} // namespace gsl
namespace std
{
template <class T>
struct hash<gsl::strict_not_null<T>>
{
std::size_t operator()(const gsl::strict_not_null<T>& value) const { return hash<T>{}(value); }
};
} // namespace std
#if defined(_MSC_VER) && _MSC_VER < 1910 && !defined(__clang__)
#undef constexpr #undef constexpr
#pragma pop_macro("constexpr") #pragma pop_macro("constexpr")
#endif // defined(_MSC_VER) && _MSC_VER < 1910 #endif // defined(_MSC_VER) && _MSC_VER < 1910 && !defined(__clang__)
#endif // GSL_POINTERS_H #endif // GSL_POINTERS_H

View File

@ -31,7 +31,7 @@
#include <utility> #include <utility>
#include <memory> // for std::addressof #include <memory> // for std::addressof
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push) #pragma warning(push)
// turn off some warnings that are noisy about our Expects statements // turn off some warnings that are noisy about our Expects statements
@ -61,7 +61,7 @@
// compiletime, so the compiler wouldn't have to warn indiscriminently, but // compiletime, so the compiler wouldn't have to warn indiscriminently, but
// could check if the source value actually doesn't fit into the target type // could check if the source value actually doesn't fit into the target type
// and only warn in those cases. // and only warn in those cases.
#if __GNUC__ > 6 #if defined(__GNUC__) && __GNUC__ > 6
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wsign-conversion"
#endif #endif
@ -544,7 +544,7 @@ public:
#endif // _MSC_VER #endif // _MSC_VER
private: private:
static bool CheckRange(index_type idx, index_type size) noexcept static constexpr bool CheckRange(index_type idx, index_type size) noexcept
{ {
// Optimization: // Optimization:
// //
@ -776,7 +776,7 @@ constexpr ElementType& at(span<ElementType, Extent> s, index i)
} // namespace gsl } // namespace gsl
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER < 1910 #if _MSC_VER < 1910
#undef constexpr #undef constexpr
#pragma pop_macro("constexpr") #pragma pop_macro("constexpr")
@ -786,7 +786,7 @@ constexpr ElementType& at(span<ElementType, Extent> s, index i)
#pragma warning(pop) #pragma warning(pop)
#endif // _MSC_VER #endif // _MSC_VER
#if __GNUC__ > 6 #if defined(__GNUC__) && __GNUC__ > 6
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif // __GNUC__ > 6 #endif // __GNUC__ > 6

View File

@ -30,7 +30,7 @@
#include <string> // for basic_string, allocator, char_traits #include <string> // for basic_string, allocator, char_traits
#include <type_traits> // for declval, is_convertible, enable_if_t, add_... #include <type_traits> // for declval, is_convertible, enable_if_t, add_...
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push) #pragma warning(push)
// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. // Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
@ -706,7 +706,7 @@ bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other)
#endif #endif
} // namespace gsl } // namespace gsl
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop) #pragma warning(pop)
#if _MSC_VER < 1910 #if _MSC_VER < 1910

View File

@ -1,130 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.7) cmake_minimum_required(VERSION 3.0.2)
project(GSLTests CXX) project(GSLTests CXX)
@ -33,14 +33,24 @@ endif()
# this interface adds compile options to how the tests are run # this interface adds compile options to how the tests are run
# please try to keep entries ordered =) # please try to keep entries ordered =)
add_library(gsl_tests_config INTERFACE) add_library(gsl_tests_config INTERFACE)
target_compile_options(gsl_tests_config INTERFACE if(MSVC) # MSVC or simulating MSVC
$<$<CXX_COMPILER_ID:MSVC>: target_compile_options(gsl_tests_config INTERFACE
${GSL_CPLUSPLUS_OPT}
/EHsc /EHsc
/W4 /W4
/WX /WX
> $<$<CXX_COMPILER_ID:Clang>:
${GSL_CPLUSPLUS_OPT} -Weverything
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>: -Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-missing-braces
-Wno-missing-prototypes
-Wno-unknown-attributes
$<$<EQUAL:${GSL_CXX_STANDARD},14>:-Wno-unused-member-function>
>
)
else()
target_compile_options(gsl_tests_config INTERFACE
-fno-strict-aliasing -fno-strict-aliasing
-Wall -Wall
-Wcast-align -Wcast-align
@ -48,16 +58,25 @@ target_compile_options(gsl_tests_config INTERFACE
-Wctor-dtor-privacy -Wctor-dtor-privacy
-Werror -Werror
-Wextra -Wextra
-Wno-missing-braces
-Wno-unknown-attributes
-Wnon-virtual-dtor
-Wold-style-cast
-Woverloaded-virtual
-Wpedantic -Wpedantic
-Wshadow -Wshadow
-Wsign-conversion -Wsign-conversion
> $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
) -Weverything
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-missing-braces
-Wno-missing-prototypes
-Wno-padded
-Wno-unknown-attributes
$<$<EQUAL:${GSL_CXX_STANDARD},14>:-Wno-unused-member-function>
-Wno-weak-vtables
>
$<$<CXX_COMPILER_ID:Clang>:
$<$<CXX_COMPILER_VERSION:5.0.2>:-Wno-undefined-func-template>
>
)
endif(MSVC)
# for tests to find the catch header # for tests to find the catch header
target_include_directories(gsl_tests_config INTERFACE target_include_directories(gsl_tests_config INTERFACE
@ -136,7 +155,7 @@ add_gsl_test(utils_tests FALSE)
add_gsl_test(owner_tests FALSE) add_gsl_test(owner_tests FALSE)
add_gsl_test(byte_tests FALSE) add_gsl_test(byte_tests FALSE)
add_gsl_test(algorithm_tests FALSE) add_gsl_test(algorithm_tests FALSE)
add_gsl_test(sloppy_notnull_tests FALSE) add_gsl_test(strict_notnull_tests FALSE)
# No exception tests # No exception tests
@ -150,34 +169,49 @@ endforeach(flag_var)
# this interface adds compile options to how the tests are run # this interface adds compile options to how the tests are run
# please try to keep entries ordered =) # please try to keep entries ordered =)
add_library(gsl_tests_config_noexcept INTERFACE) add_library(gsl_tests_config_noexcept INTERFACE)
target_compile_options(gsl_tests_config_noexcept INTERFACE if(MSVC) # MSVC or simulating MSVC
$<$<CXX_COMPILER_ID:MSVC>: target_compile_definitions(gsl_tests_config_noexcept INTERFACE
/D_HAS_EXCEPTIONS=0 _HAS_EXCEPTIONS=0
/wd4702 )
/wd4577 target_compile_options(gsl_tests_config_noexcept INTERFACE
${GSL_CPLUSPLUS_OPT}
/W4 /W4
/WX /WX
> $<$<CXX_COMPILER_ID:MSVC>:
${GSL_CPLUSPLUS_OPT} /wd4577
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>: /wd4702
-fno-strict-aliasing >
$<$<CXX_COMPILER_ID:Clang>:
-Weverything
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-missing-prototypes
-Wno-unknown-attributes
>
)
else()
target_compile_options(gsl_tests_config_noexcept INTERFACE
-fno-exceptions -fno-exceptions
-fno-strict-aliasing
-Wall -Wall
-Wcast-align -Wcast-align
-Wconversion -Wconversion
-Wctor-dtor-privacy -Wctor-dtor-privacy
-Werror -Werror
-Wextra -Wextra
-Wno-missing-braces
-Wno-unknown-attributes
-Wnon-virtual-dtor
-Wold-style-cast
-Woverloaded-virtual
-Wpedantic -Wpedantic
-Wshadow -Wshadow
-Wsign-conversion -Wsign-conversion
> $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
) -Weverything
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-missing-prototypes
-Wno-unknown-attributes
-Wno-weak-vtables
>
)
endif(MSVC)
# set definitions for tests # set definitions for tests
target_compile_definitions(gsl_tests_config_noexcept INTERFACE target_compile_definitions(gsl_tests_config_noexcept INTERFACE

View File

@ -1782,4 +1782,4 @@ TEST_CASE("iterator")
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
copy(src_span_static, dst_span_static); copy(src_span_static, dst_span_static);
#endif #endif

View File

@ -14,21 +14,17 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#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() noexcept int operator_subscript_no_throw() noexcept
{ {
int arr[10]; int arr[10];
const gsl::span<int> sp { arr }; const gsl::span<int> sp{arr};
return sp[11]; return sp[11];
} }
[[noreturn]] void test_terminate() { std::exit(0); }
void test_terminate()
{
std::exit(0);
}
void setup_termination_handler() noexcept void setup_termination_handler() noexcept
{ {
@ -44,7 +40,6 @@ void setup_termination_handler() noexcept
#endif #endif
} }
int main() noexcept int main() noexcept
{ {
setup_termination_handler(); setup_termination_handler();

View File

@ -14,20 +14,17 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <cstdlib> // for std::exit #include <cstdlib> // for std::exit
#include <gsl/gsl_util> // for narrow
#include <gsl/gsl_assert> // for get_terminate #include <gsl/gsl_assert> // for get_terminate
#include <gsl/gsl_util> // for narrow
int narrow_no_throw() int narrow_no_throw()
{ {
const long long bigNumber = 0x0fffffffffffffff; const long long bigNumber = 0x0fffffffffffffff;
return gsl::narrow<int>(bigNumber); return gsl::narrow<int>(bigNumber);
} }
void test_terminate() [[noreturn]] void test_terminate() { std::exit(0); }
{
std::exit(0);
}
void setup_termination_handler() noexcept void setup_termination_handler() noexcept
{ {
@ -43,7 +40,6 @@ void setup_termination_handler() noexcept
#endif #endif
} }
int main() int main()
{ {
setup_termination_handler(); setup_termination_handler();

View File

@ -25,7 +25,7 @@
#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>
#include <algorithm> // for addressof #include <algorithm> // for addressof
#include <memory> // for shared_ptr, make_shared, operator<, opera... #include <memory> // for shared_ptr, make_shared, operator<, opera...
@ -128,47 +128,105 @@ struct NonCopyableNonMovable
}; };
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool helper(not_null<int*> p) bool helper(not_null<int*> p) { return *p == 12; }
{
return *p == 12;
}
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool helper_const(not_null<const int*> p) bool helper_const(not_null<const int*> p) { return *p == 12; }
{
return *p == 12; int* return_pointer() { return nullptr; }
} const int* return_pointer_const() { return nullptr; }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullConstructors") TEST_CASE("TestNotNullConstructors")
{ {
{
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
not_null<int*> p = nullptr; // yay...does not compile! not_null<int*> p = nullptr; // yay...does not compile!
not_null<std::vector<char>*> p = 0; // yay...does not compile! not_null<std::vector<char>*> p1 = 0; // yay...does not compile!
not_null<int*> p; // yay...does not compile! not_null<int*> p2; // yay...does not compile!
std::unique_ptr<int> up = std::make_unique<int>(120); std::unique_ptr<int> up = std::make_unique<int>(120);
not_null<int*> p = up; not_null<int*> p3 = up;
// Forbid non-nullptr assignable types // Forbid non-nullptr assignable types
not_null<std::vector<int>> f(std::vector<int>{1}); not_null<std::vector<int>> f(std::vector<int>{1});
not_null<int> z(10); not_null<int> z(10);
not_null<std::vector<int>> y({1, 2}); not_null<std::vector<int>> y({1, 2});
#endif #endif
int i = 12; }
auto rp = RefCounted<int>(&i);
not_null<int*> p(rp);
CHECK(p.get() == &i);
not_null<std::shared_ptr<int>> x( {
std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable // from shared pointer
int i = 12;
auto rp = RefCounted<int>(&i);
not_null<int*> p(rp);
CHECK(p.get() == &i);
#ifdef GSL_THROW_ON_CONTRACT_VIOLATION not_null<std::shared_ptr<int>> x(
int* pi = nullptr; std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
CHECK_THROWS_AS(not_null<decltype(pi)>(pi), fail_fast);
#endif int* pi = nullptr;
CHECK_THROWS_AS(not_null<decltype(pi)>(pi), fail_fast);
}
{
// from pointer to local
int t = 42;
not_null<int*> x = &t;
helper(&t);
helper_const(&t);
CHECK(*x == 42);
}
{
// from raw pointer
// from not_null pointer
int t = 42;
int* p = &t;
not_null<int*> x = p;
helper(p);
helper_const(p);
helper(x);
helper_const(x);
CHECK(*x == 42);
}
{
// from raw const pointer
// from not_null const pointer
int t = 42;
const int* cp = &t;
not_null<const int*> x = cp;
helper_const(cp);
helper_const(x);
CHECK(*x == 42);
}
{
// from not_null const pointer, using auto
int t = 42;
const int* cp = &t;
auto x = not_null<const int*>{cp};
CHECK(*x == 42);
}
{
// from returned pointer
CHECK_THROWS_AS(helper(return_pointer()), fail_fast);
CHECK_THROWS_AS(helper_const(return_pointer()), fail_fast);
}
} }
template<typename T> template <typename T>
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
void ostream_helper(T v) void ostream_helper(T v)
{ {
@ -193,7 +251,7 @@ TEST_CASE("TestNotNullostream")
{ {
ostream_helper<int>(17); ostream_helper<int>(17);
ostream_helper<float>(21.5f); ostream_helper<float>(21.5f);
ostream_helper<double>(3.4566e-7f); ostream_helper<double>(3.4566e-7);
ostream_helper<char>('c'); ostream_helper<char>('c');
ostream_helper<uint16_t>(0x0123u); ostream_helper<uint16_t>(0x0123u);
ostream_helper<const char*>("cstring"); ostream_helper<const char*>("cstring");
@ -474,5 +532,5 @@ TEST_CASE("TestMakeNotNull")
#endif #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

@ -1,124 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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

@ -37,9 +37,10 @@
#include <type_traits> // for integral_constant<>::value, is_default_co... #include <type_traits> // for integral_constant<>::value, is_default_co...
#include <vector> // for vector #include <vector> // for vector
namespace gsl { namespace gsl
{
struct fail_fast; struct fail_fast;
} // namespace gsl } // namespace gsl
using namespace std; using namespace std;
using namespace gsl; using namespace gsl;
@ -54,9 +55,12 @@ struct DerivedClass : BaseClass
}; };
struct AddressOverloaded struct AddressOverloaded
{ {
#if (__cplusplus > 201402L)
[[maybe_unused]]
#endif
AddressOverloaded operator&() const { return {}; } AddressOverloaded operator&() const { return {}; }
}; };
} } // namespace
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("default_constructor") TEST_CASE("default_constructor")
@ -513,8 +517,8 @@ TEST_CASE("from_std_array_constructor")
static span<int> s2; static span<int> s2;
s2 = s1; s2 = s1;
#if __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && __GNUC_PATCHLEVEL__ == 0 && \ #if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && \
defined(__OPTIMIZE__) __GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__)
// Known to be broken in gcc 6.4 and 6.5 with optimizations // Known to be broken in gcc 6.4 and 6.5 with optimizations
// Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116 // Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116
CHECK(s1.size() == 4); CHECK(s1.size() == 4);

View File

@ -0,0 +1,193 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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>
namespace gsl
{
struct fail_fast;
} // namespace gsl
using namespace gsl;
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 strict_helper(strict_not_null<int*> p) { return *p == 12; }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool strict_helper_const(strict_not_null<const int*> p) { return *p == 12; }
int* return_pointer() { return nullptr; }
const int* return_pointer_const() { return nullptr; }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestStrictNotNull")
{
{
// raw ptr <-> strict_not_null
int x = 42;
#ifdef CONFIRM_COMPILATION_ERRORS
strict_not_null<int*> snn = &x;
strict_helper(&x);
strict_helper_const(&x);
strict_helper(return_pointer());
strict_helper_const(return_pointer_const());
#endif
const strict_not_null<int*> snn1{&x};
helper(snn1);
helper_const(snn1);
CHECK(*snn1 == 42);
}
{
// strict_not_null -> strict_not_null
int x = 42;
strict_not_null<int*> snn1{&x};
const strict_not_null<int*> snn2{&x};
strict_helper(snn1);
strict_helper_const(snn1);
strict_helper_const(snn2);
CHECK(snn1 == snn2);
}
{
// strict_not_null -> not_null
int x = 42;
strict_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 -> strict_not_null
int x = 42;
not_null<int*> nn{&x};
const strict_not_null<int*> snn1{nn};
const strict_not_null<int*> snn2{nn};
strict_helper(nn);
strict_helper_const(nn);
CHECK(snn1 == nn);
CHECK(snn2 == nn);
std::hash<strict_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
{
strict_not_null<int*> p{nullptr};
}
#endif
}
#if defined(__cplusplus) && (__cplusplus >= 201703L)
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestStrictNotNullConstructorTypeDeduction")
{
{
int i = 42;
strict_not_null x{&i};
helper(strict_not_null{&i});
helper_const(strict_not_null{&i});
CHECK(*x == 42);
}
{
int i = 42;
int* p = &i;
strict_not_null x{p};
helper(strict_not_null{p});
helper_const(strict_not_null{p});
CHECK(*x == 42);
}
{
auto workaround_macro = []() {
int* p1 = nullptr;
const strict_not_null x{p1};
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
{
auto workaround_macro = []() {
const int* p1 = nullptr;
const strict_not_null x{p1};
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}
{
int* p = nullptr;
CHECK_THROWS_AS(helper(strict_not_null{p}), fail_fast);
CHECK_THROWS_AS(helper_const(strict_not_null{p}), fail_fast);
}
#ifdef CONFIRM_COMPILATION_ERRORS
{
strict_not_null x{nullptr};
helper(strict_not_null{nullptr});
helper_const(strict_not_null{nullptr});
}
#endif
}
#endif // #if defined(__cplusplus) && (__cplusplus >= 201703L)
static_assert(std::is_nothrow_move_constructible<strict_not_null<void*>>::value,
"strict_not_null must be no-throw move constructible");

View File

@ -117,7 +117,7 @@ TEST_CASE("strided_span_constructors")
CHECK(sav.bounds().strides() == multi_span_index<1>{1}); CHECK(sav.bounds().strides() == multi_span_index<1>{1});
CHECK(sav[1] == 2); CHECK(sav[1] == 2);
#if _MSC_VER > 1800 #if defined(_MSC_VER) && _MSC_VER > 1800
// strided_span<const int, 1> sav_c{ {src}, {2, 1} }; // strided_span<const int, 1> sav_c{ {src}, {2, 1} };
strided_span<const int, 1> sav_c{multi_span<const int>{src}, strided_span<const int, 1> sav_c{multi_span<const int>{src},
strided_bounds<1>{2, 1}}; strided_bounds<1>{2, 1}};
@ -129,7 +129,7 @@ TEST_CASE("strided_span_constructors")
CHECK(sav_c.bounds().strides() == multi_span_index<1>{1}); CHECK(sav_c.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_c[1] == 2); CHECK(sav_c[1] == 2);
#if _MSC_VER > 1800 #if defined(_MSC_VER) && _MSC_VER > 1800
strided_span<volatile int, 1> sav_v{src, {2, 1}}; strided_span<volatile int, 1> sav_v{src, {2, 1}};
#else #else
strided_span<volatile int, 1> sav_v{multi_span<volatile int>{src}, strided_span<volatile int, 1> sav_v{multi_span<volatile int>{src},
@ -139,7 +139,7 @@ TEST_CASE("strided_span_constructors")
CHECK(sav_v.bounds().strides() == multi_span_index<1>{1}); CHECK(sav_v.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_v[1] == 2); CHECK(sav_v[1] == 2);
#if _MSC_VER > 1800 #if defined(_MSC_VER) && _MSC_VER > 1800
strided_span<const volatile int, 1> sav_cv{src, {2, 1}}; strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
#else #else
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src}, strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
@ -159,7 +159,7 @@ TEST_CASE("strided_span_constructors")
CHECK(sav_c.bounds().strides() == multi_span_index<1>{1}); CHECK(sav_c.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_c[1] == 2); CHECK(sav_c[1] == 2);
#if _MSC_VER > 1800 #if defined(_MSC_VER) && _MSC_VER > 1800
strided_span<const volatile int, 1> sav_cv{src, {2, 1}}; strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
#else #else
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src}, strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
@ -180,7 +180,7 @@ TEST_CASE("strided_span_constructors")
CHECK(sav_v.bounds().strides() == multi_span_index<1>{1}); CHECK(sav_v.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_v[1] == 2); CHECK(sav_v[1] == 2);
#if _MSC_VER > 1800 #if defined(_MSC_VER) && _MSC_VER > 1800
strided_span<const volatile int, 1> sav_cv{src, {2, 1}}; strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
#else #else
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src}, strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
@ -598,7 +598,7 @@ void iterate_every_other_element(multi_span<int, dynamic_range> av)
// pick every other element // pick every other element
auto length = av.size() / 2; auto length = av.size() / 2;
#if _MSC_VER > 1800 #if defined(_MSC_VER) && _MSC_VER > 1800
auto bounds = strided_bounds<1>({length}, {2}); auto bounds = strided_bounds<1>({length}, {2});
#else #else
auto bounds = strided_bounds<1>(multi_span_index<1>{length}, multi_span_index<1>{2}); auto bounds = strided_bounds<1>(multi_span_index<1>{length}, multi_span_index<1>{2});

View File

@ -20,7 +20,8 @@
// blanket turn off warnings from CppCoreCheck from catch // blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool. // 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 #include <CodeAnalysis/Warnings.h>
#pragma warning(disable : ALL_CODE_ANALYSIS_WARNINGS) // from catch
#endif // _MSC_VER #endif // _MSC_VER
#include <catch/catch.hpp> #include <catch/catch.hpp>

View File

@ -80,7 +80,7 @@ TEST_CASE("finally_function_with_bind")
CHECK(i == 1); CHECK(i == 1);
} }
int j = 0; static int j = 0;
void g() { j += 1; } void g() { j += 1; }
TEST_CASE("finally_function_ptr") TEST_CASE("finally_function_ptr")
{ {
@ -126,4 +126,8 @@ TEST_CASE("narrow")
n = -42; n = -42;
CHECK_THROWS_AS(narrow<unsigned>(n), narrowing_error); CHECK_THROWS_AS(narrow<unsigned>(n), narrowing_error);
#if GSL_CONSTEXPR_NARROW
static_assert(narrow<char>(120) == 120, "Fix GSL_CONSTEXPR_NARROW");
#endif
} }