From 831be5de39fd297aa8b434554321b54a438107d3 Mon Sep 17 00:00:00 2001 From: Neil MacIntosh Date: Wed, 14 Sep 2016 22:01:02 -0700 Subject: [PATCH 1/6] Removed redundant static_cast<> and is_same<> test. --- gsl/span | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/gsl/span b/gsl/span index d2e16dc..a9a3322 100644 --- a/gsl/span +++ b/gsl/span @@ -132,8 +132,7 @@ namespace details template struct is_allowed_element_type_conversion - : public std::integral_constant>::value || - std::is_convertible::value> + : public std::integral_constant::value> { }; @@ -420,8 +419,7 @@ public: details::is_allowed_extent_conversion::value && details::is_allowed_element_type_conversion::value>> constexpr span(const span& other) - : storage_(static_cast(other.data()), - details::extent_type(other.size())) + : storage_(other.data(), details::extent_type(other.size())) { } @@ -431,8 +429,7 @@ public: details::is_allowed_extent_conversion::value && details::is_allowed_element_type_conversion::value>> constexpr span(span&& other) - : storage_(static_cast(other.data()), - details::extent_type(other.size())) + : storage_(other.data(), details::extent_type(other.size())) { } @@ -626,7 +623,7 @@ as_writeable_bytes(span s) noexcept // Specialization of gsl::at for span template -constexpr ElementType& at(const span& s, size_t index) +constexpr ElementType& at(const span& s, size_t index) { // No bounds checking here because it is done in span::operator[] called below return s[index]; From 67717ea6ae69f391807fec7ebbeb85c135e9facf Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 27 Sep 2016 21:12:51 -0700 Subject: [PATCH 2/6] [multi_span] Fix UB hack in static_bounds::operator= * Make BoundsRanges::m_bound non-const and private * Remove various defaulted copy constructor/assignment declarations from BoundsRanges specializations whose only effect is to needlessly suppress the generation of moves * Remove the hackish static_bounds::operator=(const static_bounds&). The implicitly generated default is now sufficient --- gsl/multi_span | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/gsl/multi_span b/gsl/multi_span index 40752aa..2186c7b 100644 --- a/gsl/multi_span +++ b/gsl/multi_span @@ -308,8 +308,6 @@ namespace details { } - BoundsRanges(const BoundsRanges&) = default; - BoundsRanges& operator=(const BoundsRanges&) = default; BoundsRanges(const std::ptrdiff_t* const) {} BoundsRanges() = default; @@ -346,9 +344,9 @@ namespace details static const size_t DynamicNum = Base::DynamicNum + 1; static const size_type CurrentRange = dynamic_range; static const size_type TotalSize = dynamic_range; - const size_type m_bound; - - BoundsRanges(const BoundsRanges&) = default; + private: + size_type m_bound; + public: BoundsRanges(const std::ptrdiff_t* const arr) : Base(arr + 1), m_bound(*arr * this->Base::totalSize()) @@ -420,8 +418,6 @@ namespace details static const size_type TotalSize = Base::TotalSize == dynamic_range ? dynamic_range : CurrentRange * Base::TotalSize; - BoundsRanges(const BoundsRanges&) = default; - BoundsRanges(const std::ptrdiff_t* const arr) : Base(arr) {} BoundsRanges() = default; @@ -633,12 +629,6 @@ public: constexpr static_bounds() = default; - constexpr static_bounds& operator=(const static_bounds& otherBounds) - { - new (&m_ranges) MyRanges(otherBounds.m_ranges); - return *this; - } - constexpr sliced_type slice() const noexcept { return sliced_type{static_cast&>(m_ranges)}; From 4b29878d702e4cd243d5bf6f0eb5dcb228301be4 Mon Sep 17 00:00:00 2001 From: Rian Quinn Date: Wed, 28 Sep 2016 09:43:13 -0600 Subject: [PATCH 3/6] Add branch prediction to Ensures / Expects We should be using branch prediction on asserts as these conditions are known to be unlikely, therefore we should be optimizing the likely case. These macros are similar to what the Linux kernel uses. Not really sure what Visual Studio does so at the moment these are disabled for VS. --- gsl/gsl_assert | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/gsl/gsl_assert b/gsl/gsl_assert index 10de31a..34b3ecb 100644 --- a/gsl/gsl_assert +++ b/gsl/gsl_assert @@ -38,6 +38,14 @@ #define GSL_STRINGIFY_DETAIL(x) #x #define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) +#if defined(__clang__) || defined(__GNUC__) +#define GSL_LIKELY(x) __builtin_expect (!!(x), 1) +#define GSL_UNLIKELY(x) __builtin_expect (!!(x), 0) +#else +#define GSL_LIKELY(x) +#define GSL_UNLIKELY(x) +#endif + // // GSL.assert: assertions // @@ -53,19 +61,19 @@ struct fail_fast : public std::runtime_error #if defined(GSL_THROW_ON_CONTRACT_VIOLATION) #define Expects(cond) \ - if (!(cond)) \ + if (GSL_UNLIKELY(!(cond))) \ throw gsl::fail_fast("GSL: Precondition failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__)); #define Ensures(cond) \ - if (!(cond)) \ + if (GSL_UNLIKELY(!(cond))) \ throw gsl::fail_fast("GSL: Postcondition failure at " __FILE__ \ ": " GSL_STRINGIFY(__LINE__)); #elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) #define Expects(cond) \ - if (!(cond)) std::terminate(); + if (GSL_UNLIKELY(!(cond))) std::terminate(); #define Ensures(cond) \ - if (!(cond)) std::terminate(); + if (GSL_UNLIKELY(!(cond))) std::terminate(); #elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION) From 3161d6133fb0c05785e657acd4b178d0253e8319 Mon Sep 17 00:00:00 2001 From: Rian Quinn Date: Wed, 28 Sep 2016 09:53:33 -0600 Subject: [PATCH 4/6] Fix issue with VS builds The Visual Studio part of this patch was wrong, and left an empty if statement. --- gsl/gsl_assert | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gsl/gsl_assert b/gsl/gsl_assert index 34b3ecb..6d8760d 100644 --- a/gsl/gsl_assert +++ b/gsl/gsl_assert @@ -39,11 +39,11 @@ #define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) #if defined(__clang__) || defined(__GNUC__) -#define GSL_LIKELY(x) __builtin_expect (!!(x), 1) -#define GSL_UNLIKELY(x) __builtin_expect (!!(x), 0) +#define GSL_LIKELY(x) __builtin_expect (!!(x), 1) +#define GSL_UNLIKELY(x) __builtin_expect (!!(x), 0) #else -#define GSL_LIKELY(x) -#define GSL_UNLIKELY(x) +#define GSL_LIKELY(x) (x) +#define GSL_UNLIKELY(x) (x) #endif // From 9e055be6593e11849d4fa7966847054372d025b1 Mon Sep 17 00:00:00 2001 From: Rian Quinn Date: Wed, 28 Sep 2016 10:00:47 -0600 Subject: [PATCH 5/6] Fix compilation issues with Cygwin Cygwin recently did an update that broken string_span again. The original update had to provide a custom strnlen function because Cygwin doesn't implement this (it's a non-std extension). We never added wchar_t support, and the Cygwin update now breaks on exactly this. This patch provides the missing wchar_t. --- gsl/string_span | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/gsl/string_span b/gsl/string_span index cd49998..768bfd5 100644 --- a/gsl/string_span +++ b/gsl/string_span @@ -118,6 +118,24 @@ namespace details return len; #endif } + + inline std::size_t wstring_length(const wchar_t *str, std::size_t n) + { +#ifdef GSL_PLATFORM_HAS_STRNLEN + return wcsnlen(str, n); +#else + if (str == nullptr || n == 0) + return 0; + + std::size_t len = 0; + span str_span{str, n}; + + while (len < n && str_span[len]) + len++; + + return len; +#endif + } } // @@ -166,14 +184,14 @@ inline span ensure_z(const char* const& sz, std::ptr inline span ensure_z(wchar_t* const& sz, std::ptrdiff_t max) { - auto len = wcsnlen(sz, narrow_cast(max)); + auto len = details::wstring_length(sz, narrow_cast(max)); Ensures(sz[len] == 0); return {sz, static_cast(len)}; } inline span ensure_z(const wchar_t* const& sz, std::ptrdiff_t max) { - auto len = wcsnlen(sz, narrow_cast(max)); + auto len = details::wstring_length(sz, narrow_cast(max)); Ensures(sz[len] == 0); return {sz, static_cast(len)}; } @@ -230,7 +248,7 @@ namespace details { std::ptrdiff_t operator()(wchar_t* const ptr, std::ptrdiff_t length) noexcept { - return narrow_cast(wcsnlen(ptr, narrow_cast(length))); + return narrow_cast(details::wstring_length(ptr, narrow_cast(length))); } }; @@ -248,7 +266,7 @@ namespace details { std::ptrdiff_t operator()(const wchar_t* const ptr, std::ptrdiff_t length) noexcept { - return narrow_cast(wcsnlen(ptr, narrow_cast(length))); + return narrow_cast(details::wstring_length(ptr, narrow_cast(length))); } }; } From f953b792f084a7f20e0420e11395888548d5f834 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 27 Sep 2016 22:02:49 -0700 Subject: [PATCH 6/6] [Travis] enlarge the support matrix * Build on OSX with Xcode 8 * Build on Linux with Clang 3.6/7/8 and libc++ * Build on Linux with GCC 5/6 --- .travis.yml | 135 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 105 insertions(+), 30 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3fed41b..5c69187 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,65 +3,140 @@ language: cpp sudo: false +cache: + directories: + - ${TRAVIS_BUILD_DIR}/deps/cmake + - ${TRAVIS_BUILD_DIR}/deps/llvm-3.5.2/install + - ${TRAVIS_BUILD_DIR}/deps/llvm-3.6.2/install + - ${TRAVIS_BUILD_DIR}/deps/llvm-3.7.1/install + - ${TRAVIS_BUILD_DIR}/deps/llvm-3.8.1/install + - ${TRAVIS_BUILD_DIR}/deps/llvm-3.9.0/install + matrix: include: - - env: COMPILER=clang++-3.6 BUILD_TYPE=Debug CLANG=1 + - env: BUILD_TYPE=Debug + os: osx + osx_image: xcode8 compiler: clang + - env: BUILD_TYPE=Release + os: osx + osx_image: xcode8 + compiler: clang + - env: CLANG_VERSION=3.6 BUILD_TYPE=Debug + os: linux addons: &clang36 apt: packages: - clang-3.6 - - cmake - g++-5 sources: &sources - ubuntu-toolchain-r-test - llvm-toolchain-precise-3.6 - - kalakris-cmake - - env: COMPILER=clang++-3.6 BUILD_TYPE=Release CLANG=1 - compiler: clang + - env: CLANG_VERSION=3.6 BUILD_TYPE=Release + os: linux addons: *clang36 - - env: COMPILER=g++-5 BUILD_TYPE=Debug - compiler: gcc + - env: CLANG_VERSION=3.7 BUILD_TYPE=Debug + os: linux + addons: &clang37 + apt: + packages: + - clang-3.7 + - g++-5 + sources: &sources + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.7 + - env: CLANG_VERSION=3.7 BUILD_TYPE=Release + os: linux + addons: *clang37 + - env: CLANG_VERSION=3.8 BUILD_TYPE=Debug + os: linux + addons: &clang38 + apt: + packages: + - clang-3.8 + - g++-5 + sources: &sources + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.8 + - env: CLANG_VERSION=3.8 BUILD_TYPE=Release + os: linux + addons: *clang38 + - env: GCC_VERSION=5 BUILD_TYPE=Debug + os: linux addons: &gcc5 apt: packages: g++-5 sources: *sources - - env: COMPILER=g++-5 BUILD_TYPE=Release - compiler: gcc + - env: GCC_VERSION=5 BUILD_TYPE=Release + os: linux addons: *gcc5 + - env: GCC_VERSION=6 BUILD_TYPE=Debug + os: linux + addons: &gcc6 + apt: + packages: g++-6 + sources: *sources + - env: GCC_VERSION=6 BUILD_TYPE=Release + os: linux + addons: *gcc6 install: - - which $COMPILER + - if [[ -n "$CLANG_VERSION" ]]; then export CXX=clang++-$CLANG_VERSION CC=clang-$CLANG_VERSION; fi + - if [[ -n "$GCC_VERSION" ]]; then export CXX=g++-$GCC_VERSION CC=gcc-$GCC_VERSION; fi + - JOBS=2 - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" - - mkdir ${DEPS_DIR} && cd ${DEPS_DIR} + - mkdir -p "${DEPS_DIR}" && cd "${DEPS_DIR}" + + ############################################################################ + # Install a recent CMake (unless already installed on OS X) + ############################################################################ - | - if [[ "$CLANG" == 1 && "${TRAVIS_OS_NAME}" == "linux" && "${STDLIB}" != "libstdc++" ]]; then - if [[ "${COMPILER}" == "clang++-3.5" ]]; then LLVM_VERSION="3.5.2"; fi - if [[ "${COMPILER}" == "clang++-3.6" ]]; then LLVM_VERSION="3.6.2"; fi - if [[ "${COMPILER}" == "clang++-3.7" ]]; then LLVM_VERSION="3.7.0"; fi + if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then + if [[ -z "$(ls -A ${DEPS_DIR}/cmake/bin)" ]]; then + CMAKE_URL="https://cmake.org/files/v3.6/cmake-3.6.2-Linux-x86_64.tar.gz" + mkdir -p cmake && travis_retry wget --no-check-certificate --quiet -O - "${CMAKE_URL}" | tar --strip-components=1 -xz -C cmake + fi + export PATH="${DEPS_DIR}/cmake/bin:${PATH}" + else + if ! brew ls --version cmake &>/dev/null; then brew install cmake; fi + fi + + ############################################################################ + # [linux]: Install the right version of libc++ + ############################################################################ + - | + if [[ -n "$CLANG_VERSION" && "${TRAVIS_OS_NAME}" == "linux" && "${STDLIB}" != "libstdc++" ]]; then + if [[ "$CLANG_VERSION" == "3.5" ]]; then LLVM_VERSION="3.5.2"; fi + if [[ "$CLANG_VERSION" == "3.6" ]]; then LLVM_VERSION="3.6.2"; fi + if [[ "$CLANG_VERSION" == "3.7" ]]; then LLVM_VERSION="3.7.1"; fi + if [[ "$CLANG_VERSION" == "3.8" ]]; then LLVM_VERSION="3.8.1"; fi + if [[ "$CLANG_VERSION" == "3.9" ]]; then LLVM_VERSION="3.9.0"; fi + LLVM_ROOT="${DEPS_DIR}/llvm-${LLVM_VERSION}" LLVM_URL="http://llvm.org/releases/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz" LIBCXX_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxx-${LLVM_VERSION}.src.tar.xz" LIBCXXABI_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxxabi-${LLVM_VERSION}.src.tar.xz" - mkdir -p llvm llvm/build llvm/projects/libcxx llvm/projects/libcxxabi - travis_retry wget --quiet -O - ${LLVM_URL} | tar --strip-components=1 -xJ -C llvm - travis_retry wget --quiet -O - ${LIBCXX_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxx - travis_retry wget --quiet -O - ${LIBCXXABI_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxxabi - (cd llvm/build && cmake .. -DCMAKE_INSTALL_PREFIX=${DEPS_DIR}/llvm/install -DCMAKE_CXX_COMPILER=clang++) - (cd llvm/build/projects/libcxx && make install -j2) - (cd llvm/build/projects/libcxxabi && make install -j2) - export CXXFLAGS="-I ${DEPS_DIR}/llvm/install/include/c++/v1" - export LDFLAGS="-L ${DEPS_DIR}/llvm/install/lib -l c++ -l c++abi" - export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${DEPS_DIR}/llvm/install/lib" + if [[ -z "$(ls -A ${LLVM_ROOT}/install/include)" ]]; then + mkdir -p "${LLVM_ROOT}" "${LLVM_ROOT}/build" "${LLVM_ROOT}/projects/libcxx" "${LLVM_ROOT}/projects/libcxxabi" + travis_retry wget --quiet -O - "${LLVM_URL}" | tar --strip-components=1 -xJ -C "${LLVM_ROOT}" + travis_retry wget --quiet -O - "${LIBCXX_URL}" | tar --strip-components=1 -xJ -C "${LLVM_ROOT}/projects/libcxx" + travis_retry wget --quiet -O - "${LIBCXXABI_URL}" | tar --strip-components=1 -xJ -C "${LLVM_ROOT}/projects/libcxxabi" + (cd "${LLVM_ROOT}/build" && cmake .. -DCMAKE_CXX_COMPILER="$CXX" -DCMAKE_C_COMPILER="$CC" -DCMAKE_INSTALL_PREFIX="${LLVM_ROOT}/install" -DCMAKE_BUILD_TYPE=$BUILD_TYPE) + (cd "${LLVM_ROOT}/build/projects/libcxx" && make install -j$JOBS) + (cd "${LLVM_ROOT}/build/projects/libcxxabi" && make install -j$JOBS) + fi + export CXXFLAGS="-I ${LLVM_ROOT}/install/include/c++/v1" + export LDFLAGS="-L ${LLVM_ROOT}/install/lib -lc++ -lc++abi" + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${LLVM_ROOT}/install/lib" fi before_script: - - cd ${TRAVIS_BUILD_DIR} - - cmake -H. -Bb -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_INSTALL_PREFIX=$PWD/o -DCMAKE_BUILD_TYPE=$BUILD_TYPE - - cmake --build b + - cd "${TRAVIS_BUILD_DIR}" + - cmake . -Bbuild -DCMAKE_CXX_COMPILER="$CXX" -DCMAKE_C_COMPILER="$CC" -DCMAKE_BUILD_TYPE=$BUILD_TYPE + - cmake --build build -- -j$JOBS script: - - cd b - - ctest + - cd build + - ctest --output-on-failure -j$JOBS notifications: email: false