diff --git a/.clang-format b/.clang-format index c12d3bf..08ad16a 100644 --- a/.clang-format +++ b/.clang-format @@ -31,4 +31,4 @@ AlignConsecutiveAssignments: false AlignTrailingComments: true SpaceAfterCStyleCast: true -CommentPragmas: '^ NO-FORMAT:' +WhitespaceSensitiveMacros: [GSL_SUPPRESS] diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml new file mode 100644 index 0000000..ddb373d --- /dev/null +++ b/.github/workflows/clang-format.yml @@ -0,0 +1,39 @@ +name: Code Formatting + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +permissions: + contents: read + +env: + CLANG_VERSION: "20" + +jobs: + clang-format: + name: Run clang-format + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + # Install the exact clang-format binary + - name: Install clang-format + run: | + sudo apt install clang-format-${{ env.CLANG_VERSION }} + + # Prints the version of clang-format being used + - name: Log clang-format version + run: clang-format-${{ env.CLANG_VERSION }} --version + + # Runs clang-format over the repository codebase + - name: Check format + run: | + { + find include/gsl -type f + find tests -type f \( -name '*.cpp' -o -name '*.h' \) + } | xargs clang-format-${{ env.CLANG_VERSION }} --dry-run --Werror diff --git a/.github/workflows/shell-script-linter.yml b/.github/workflows/shell-script-linter.yml new file mode 100644 index 0000000..c31c511 --- /dev/null +++ b/.github/workflows/shell-script-linter.yml @@ -0,0 +1,32 @@ +name: Shell script linter + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +permissions: + contents: read + +jobs: + clang-format: + name: Run shfmt and shellcheck + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + # Install the needed binaries + - name: Install shfmt and shellcheck + run: | + sudo apt install shfmt shellcheck + + - name: Check format + run: | + find scripts -type f -name '*.sh' -exec shfmt -l {} \; + + - name: Run shellcheck + run: | + find scripts -type f -name '*.sh' -exec shellcheck {} \; diff --git a/include/gsl/algorithm b/include/gsl/algorithm index c67f35a..2098906 100644 --- a/include/gsl/algorithm +++ b/include/gsl/algorithm @@ -48,9 +48,7 @@ void copy(span src, span "Source range is longer than target range"); Expects(dest.size() >= src.size()); - // clang-format off - GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(stl.1) std::copy_n(src.data(), src.size(), dest.data()); } diff --git a/include/gsl/assert b/include/gsl/assert index a08424c..5181c13 100644 --- a/include/gsl/assert +++ b/include/gsl/assert @@ -93,9 +93,7 @@ namespace details typedef void(__cdecl* terminate_handler)(); - // clang-format off - GSL_SUPPRESS(f.6) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(f.6) [[noreturn]] inline void __cdecl default_terminate_handler() { __fastfail(RANGE_CHECKS_FAILURE); diff --git a/include/gsl/byte b/include/gsl/byte index fe9b286..b532b5f 100644 --- a/include/gsl/byte +++ b/include/gsl/byte @@ -82,11 +82,13 @@ namespace gsl { #if GSL_USE_STD_BYTE -namespace impl { -// impl::byte is used by gsl::as_bytes so our own code does not trigger a deprecation warning as would be the case when we used gsl::byte. -// Users of GSL should only use gsl::byte, not gsl::impl::byte. -using byte = std::byte; -} +namespace impl +{ + // impl::byte is used by gsl::as_bytes so our own code does not trigger a deprecation warning as + // would be the case when we used gsl::byte. Users of GSL should only use gsl::byte, not + // gsl::impl::byte. + using byte = std::byte; +} // namespace impl using byte GSL_DEPRECATED("Use std::byte instead.") = std::byte; @@ -100,11 +102,13 @@ enum class byte_may_alias byte : unsigned char { }; -namespace impl { -// impl::byte is used by gsl::as_bytes so our own code does not trigger a deprecation warning as would be the case when we used gsl::byte. -// Users of GSL should only use gsl::byte, not gsl::impl::byte. -using byte = gsl::byte; -} +namespace impl +{ + // impl::byte is used by gsl::as_bytes so our own code does not trigger a deprecation warning as + // would be the case when we used gsl::byte. Users of GSL should only use gsl::byte, not + // gsl::impl::byte. + using byte = gsl::byte; +} // namespace impl template ::value, bool> = true> constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept @@ -170,15 +174,13 @@ constexpr IntegerType to_integer(byte b) noexcept #endif // GSL_USE_STD_BYTE - 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 gsl::impl::byte to_byte(T t) noexcept { - static_assert(std::is_same::value, - "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. " - "If you are calling to_byte with an integer constant use: gsl::to_byte() version."); + static_assert( + std::is_same::value, + "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. " + "If you are calling to_byte with an integer constant use: gsl::to_byte() version."); return gsl::impl::byte(t); } diff --git a/include/gsl/gsl b/include/gsl/gsl index ffaa1eb..157ef6c 100644 --- a/include/gsl/gsl +++ b/include/gsl/gsl @@ -18,13 +18,13 @@ #define GSL_GSL_H // IWYU pragma: begin_exports -#include "./algorithm" // copy -#include "./assert" // Ensures/Expects -#include "./byte" // byte -#include "./pointers" // owner, not_null -#include "./span" // span -#include "./zstring" // zstring -#include "./util" // finally()/narrow_cast()... +#include "./algorithm" // copy +#include "./assert" // Ensures/Expects +#include "./byte" // byte +#include "./pointers" // owner, not_null +#include "./span" // span +#include "./util" // finally()/narrow_cast()... +#include "./zstring" // zstring #ifdef __cpp_exceptions #include "./narrow" // narrow() diff --git a/include/gsl/narrow b/include/gsl/narrow index bee29a1..5c65717 100644 --- a/include/gsl/narrow +++ b/include/gsl/narrow @@ -16,8 +16,8 @@ #ifndef GSL_NARROW_H #define GSL_NARROW_H -#include "./assert" // for GSL_SUPPRESS -#include "./util" // for narrow_cast +#include "./assert" // for GSL_SUPPRESS +#include "./util" // for narrow_cast #include // for std::exception namespace gsl { @@ -28,28 +28,28 @@ struct narrowing_error : public std::exception // narrow() : a checked version of narrow_cast() that throws if the cast changed the value template ::value>::type* = nullptr> -// clang-format off -GSL_SUPPRESS(type.1) // NO-FORMAT: attribute -GSL_SUPPRESS(es.46) // NO-FORMAT: attribute // The warning suggests that a floating->unsigned conversion can occur - // in the static_cast below, and that gsl::narrow should be used instead. - // Suppress this warning, since gsl::narrow is defined in terms of - // static_cast - // clang-format on +GSL_SUPPRESS(type.1) + GSL_SUPPRESS(es.46) // The warning suggests that a floating->unsigned conversion can occur + // in the static_cast below, and that gsl::narrow should be used instead. + // Suppress this warning, since gsl::narrow is defined in terms of + // static_cast constexpr T narrow(U u) { constexpr const bool is_different_signedness = (std::is_signed::value != std::is_signed::value); -GSL_SUPPRESS(es.103) // NO-FORMAT: attribute // don't overflow -GSL_SUPPRESS(es.104) // NO-FORMAT: attribute // don't underflow -GSL_SUPPRESS(p.2) // NO-FORMAT: attribute // don't rely on undefined behavior - const T t = narrow_cast(u); // While this is technically undefined behavior in some cases (i.e., if the source value is of floating-point type - // and cannot fit into the destination integral type), the resultant behavior is benign on the platforms - // that we target (i.e., no hardware trap representations are hit). + GSL_SUPPRESS(es.103) // don't overflow + GSL_SUPPRESS(es.104) // don't underflow + GSL_SUPPRESS(p.2) // don't rely on undefined behavior + const T t = narrow_cast( + u); // While this is technically undefined behavior in some cases (i.e., if the source value + // is of floating-point type and cannot fit into the destination integral type), the + // resultant behavior is benign on the platforms that we target (i.e., no hardware trap + // representations are hit). #if defined(__clang__) || defined(__GNUC__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wfloat-equal" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" #endif // Note: NaN will always throw, since NaN != NaN if (static_cast(t) != u || (is_different_signedness && ((t < T{}) != (u < U{})))) @@ -57,24 +57,18 @@ GSL_SUPPRESS(p.2) // NO-FORMAT: attribute // don't rely on undefined behavior throw narrowing_error{}; } #if defined(__clang__) || defined(__GNUC__) - #pragma GCC diagnostic pop +#pragma GCC diagnostic pop #endif return t; } template ::value>::type* = nullptr> -// clang-format off -GSL_SUPPRESS(type.1) // NO-FORMAT: attribute - // clang-format on - constexpr T narrow(U u) +GSL_SUPPRESS(type.1) constexpr T narrow(U u) { const T t = narrow_cast(u); - if (static_cast(t) != u) - { - throw narrowing_error{}; - } + if (static_cast(t) != u) { throw narrowing_error{}; } return t; } diff --git a/include/gsl/pointers b/include/gsl/pointers index 436f09a..09c40f7 100644 --- a/include/gsl/pointers +++ b/include/gsl/pointers @@ -18,13 +18,13 @@ #define GSL_POINTERS_H #include "./assert" // for Ensures, Expects -#include "./util" // for GSL_DEPRECATED +#include "./util" // for GSL_DEPRECATED -#include // for ptrdiff_t, nullptr_t, size_t -#include // for less, greater -#include // for shared_ptr, unique_ptr, hash -#include // for enable_if_t, is_convertible, is_assignable -#include // for declval, forward +#include // for ptrdiff_t, nullptr_t, size_t +#include // for less, greater +#include // for shared_ptr, unique_ptr, hash +#include // for enable_if_t, is_convertible, is_assignable +#include // for declval, forward #if !defined(GSL_NO_IOSTREAMS) #include // for ostream @@ -48,15 +48,16 @@ namespace details { }; - // Resolves to the more efficient of `const T` or `const T&`, in the context of returning a const-qualified value - // of type T. + // Resolves to the more efficient of `const T` or `const T&`, in the context of returning a + // const-qualified value of type T. // - // Copied from cppfront's implementation of the CppCoreGuidelines F.16 (https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rf-in) - template - using value_or_reference_return_t = std::conditional_t< - sizeof(T) <= 2*sizeof(void*) && std::is_trivially_copy_constructible::value, - const T, - const T&>; + // Copied from cppfront's implementation of the CppCoreGuidelines F.16 + // (https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rf-in) + template + using value_or_reference_return_t = + std::conditional_t::value, + const T, const T&>; } // namespace details @@ -72,9 +73,10 @@ using unique_ptr GSL_DEPRECATED("Use std::unique_ptr instead") = std::unique_ptr // // owner // -// `gsl::owner` is designed as a safety mechanism for code that must deal directly with raw pointers that own memory. -// Ideally such code should be restricted to the implementation of low-level abstractions. `gsl::owner` can also be used -// as a stepping point in converting legacy code to use more modern RAII constructs, such as smart pointers. +// `gsl::owner` is designed as a safety mechanism for code that must deal directly with raw +// pointers that own memory. Ideally such code should be restricted to the implementation of +// low-level abstractions. `gsl::owner` can also be used as a stepping point in converting legacy +// code to use more modern RAII constructs, such as smart pointers. // // T must be a pointer type // - disallow construction from any type other than pointer type @@ -105,19 +107,23 @@ public: using element_type = T; template ::value>> - constexpr not_null(U&& u) noexcept(std::is_nothrow_move_constructible::value) : ptr_(std::forward(u)) + constexpr not_null(U&& u) noexcept(std::is_nothrow_move_constructible::value) + : ptr_(std::forward(u)) { Expects(ptr_ != nullptr); } template ::value>> - constexpr not_null(T u) noexcept(std::is_nothrow_move_constructible::value) : ptr_(std::move(u)) + constexpr not_null(T u) noexcept(std::is_nothrow_move_constructible::value) + : ptr_(std::move(u)) { Expects(ptr_ != nullptr); } template ::value>> - constexpr not_null(const not_null& other) noexcept(std::is_nothrow_move_constructible::value) : not_null(other.get()) + constexpr not_null(const not_null& other) noexcept( + std::is_nothrow_move_constructible::value) + : not_null(other.get()) {} not_null(const not_null& other) = default; @@ -151,7 +157,9 @@ private: T ptr_; }; -template ::value && std::is_move_constructible::value, bool> = true> +template ::value && + std::is_move_constructible::value, + bool> = true> void swap(not_null& a, not_null& b) noexcept { a.swap(b); @@ -174,7 +182,7 @@ std::ostream& operator<<(std::ostream& os, const not_null& val) template constexpr auto operator==(const not_null& lhs, - const not_null& rhs) noexcept(noexcept(lhs.get() == rhs.get())) + const not_null& rhs) noexcept(noexcept(lhs.get() == rhs.get())) -> decltype(lhs.get() == rhs.get()) { return lhs.get() == rhs.get(); @@ -182,39 +190,41 @@ constexpr auto operator==(const not_null& lhs, template constexpr auto operator!=(const not_null& lhs, - const not_null& rhs) noexcept(noexcept(lhs.get() != rhs.get())) + const not_null& rhs) noexcept(noexcept(lhs.get() != rhs.get())) -> decltype(lhs.get() != rhs.get()) { return lhs.get() != rhs.get(); } template -constexpr auto operator<(const not_null& lhs, - const not_null& rhs) noexcept(noexcept(std::less<>{}(lhs.get(), rhs.get()))) - -> decltype(std::less<>{}(lhs.get(), rhs.get())) +constexpr auto operator<(const not_null& lhs, const not_null& rhs) noexcept( + noexcept(std::less<>{}(lhs.get(), rhs.get()))) -> decltype(std::less<>{}(lhs.get(), rhs.get())) { return std::less<>{}(lhs.get(), rhs.get()); } template -constexpr auto operator<=(const not_null& lhs, - const not_null& rhs) noexcept(noexcept(std::less_equal<>{}(lhs.get(), rhs.get()))) +constexpr auto +operator<=(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(std::less_equal<>{}(lhs.get(), rhs.get()))) -> decltype(std::less_equal<>{}(lhs.get(), rhs.get())) { return std::less_equal<>{}(lhs.get(), rhs.get()); } template -constexpr auto operator>(const not_null& lhs, - const not_null& rhs) noexcept(noexcept(std::greater<>{}(lhs.get(), rhs.get()))) +constexpr auto +operator>(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(std::greater<>{}(lhs.get(), rhs.get()))) -> decltype(std::greater<>{}(lhs.get(), rhs.get())) { return std::greater<>{}(lhs.get(), rhs.get()); } template -constexpr auto operator>=(const not_null& lhs, - const not_null& rhs) noexcept(noexcept(std::greater_equal<>{}(lhs.get(), rhs.get()))) +constexpr auto +operator>=(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(std::greater_equal<>{}(lhs.get(), rhs.get()))) -> decltype(std::greater_equal<>{}(lhs.get(), rhs.get())) { return std::greater_equal<>{}(lhs.get(), rhs.get()); @@ -230,9 +240,10 @@ not_null operator+(const not_null&, std::ptrdiff_t) = delete; template not_null operator+(std::ptrdiff_t, const not_null&) = delete; - -// T is conceptually a pointer so we don't have to worry about it being a reference and violating std::hash requirements -template >::value> +// T is conceptually a pointer so we don't have to worry about it being a reference and violating +// std::hash requirements +template >::value> struct not_null_hash { std::size_t operator()(const T& value) const noexcept { return std::hash{}(value.get()); } @@ -282,24 +293,32 @@ class strict_not_null : public not_null { public: template ::value>> - constexpr explicit strict_not_null(U&& u) noexcept(std::is_nothrow_move_constructible::value) : not_null(std::forward(u)) + constexpr explicit strict_not_null(U&& u) noexcept(std::is_nothrow_move_constructible::value) + : not_null(std::forward(u)) {} template ::value>> - constexpr explicit strict_not_null(T u) noexcept(std::is_nothrow_move_constructible::value) : not_null(std::move(u)) + constexpr explicit strict_not_null(T u) noexcept(std::is_nothrow_move_constructible::value) + : not_null(std::move(u)) {} template ::value>> - constexpr strict_not_null(const not_null& other) noexcept(std::is_nothrow_move_constructible::value) : not_null(other) + constexpr strict_not_null(const not_null& other) noexcept( + std::is_nothrow_move_constructible::value) + : not_null(other) {} template ::value>> - constexpr strict_not_null(const strict_not_null& other) noexcept(std::is_nothrow_move_constructible::value) : not_null(other) + constexpr strict_not_null(const strict_not_null& other) noexcept( + std::is_nothrow_move_constructible::value) + : not_null(other) {} // To avoid invalidating the "not null" invariant, the contained pointer is actually copied - // instead of moved. If it is a custom pointer, its constructor could in theory throw exceptions. - strict_not_null(strict_not_null&& other) noexcept(std::is_nothrow_copy_constructible::value) = default; + // instead of moved. If it is a custom pointer, its constructor could in theory throw + // exceptions. + strict_not_null(strict_not_null&& other) noexcept( + std::is_nothrow_copy_constructible::value) = 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& other) diff --git a/include/gsl/span b/include/gsl/span index af351ca..abbb6b5 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -163,9 +163,7 @@ namespace details constexpr span_iterator& operator++() noexcept { Expects(current_ != end_); - // clang-format off - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(bounds.1) ++current_; return *this; } @@ -196,9 +194,7 @@ namespace details if (n != 0) Expects(begin_ && current_ && end_); if (n > 0) Expects(end_ - current_ >= n); if (n < 0) Expects(current_ - begin_ >= -n); - // clang-format off - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(bounds.1) current_ += n; return *this; } @@ -315,9 +311,7 @@ namespace details if (n < 0) Expects(current_ - begin_ >= -n); } - // clang-format off - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(bounds.1) constexpr pointer _Unwrapped() const noexcept { // after seeking *this to a high water mark, or using one of the // _Verify_xxx functions above, unwrap this span_iterator to a raw @@ -332,9 +326,7 @@ namespace details #else static constexpr bool _Unwrap_when_unverified = false; #endif - // clang-format off - GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive - // clang-format on + GSL_SUPPRESS(con.3) // TODO: false positive constexpr void _Seek_to(const pointer p) noexcept { // adjust the position of *this to previously verified location p // after _Unwrapped @@ -349,7 +341,8 @@ namespace details template friend struct std::pointer_traits; }; -}} // namespace gsl::details +} // namespace details +} // namespace gsl namespace std { @@ -364,7 +357,10 @@ struct pointer_traits<::gsl::details::span_iterator> }; } // namespace std -namespace gsl { namespace details { +namespace gsl +{ +namespace details +{ template class extent_type { @@ -589,10 +585,7 @@ public: } template - // clang-format off - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on - constexpr span last() const noexcept + GSL_SUPPRESS(bounds.1) constexpr span last() const noexcept { static_assert(Extent == dynamic_extent || Count <= Extent, "last() cannot extract more elements from a span than it contains."); @@ -601,10 +594,7 @@ public: } template - // clang-format off - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on - constexpr auto subspan() const noexcept -> + GSL_SUPPRESS(bounds.1) constexpr auto subspan() const noexcept -> typename details::calculate_subspan_type::type { static_assert(Extent == dynamic_extent || (Extent >= Offset && (Count == dynamic_extent || @@ -642,9 +632,7 @@ public: constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access - // clang-format off - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(bounds.1) constexpr reference operator[](size_type idx) const noexcept { Expects(idx < size()); @@ -669,18 +657,14 @@ public: constexpr iterator begin() const noexcept { const auto data = storage_.data(); - // clang-format off - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(bounds.1) return {data, data + size(), data}; } constexpr iterator end() const noexcept { const auto data = storage_.data(); - // clang-format off - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(bounds.1) const auto endData = data + storage_.size(); return {data, endData, endData}; } @@ -693,9 +677,7 @@ public: constexpr pointer _Unchecked_begin() const noexcept { return data(); } constexpr pointer _Unchecked_end() const noexcept { - // clang-format off - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(bounds.1) return data() + size(); } #endif // _MSC_VER @@ -752,9 +734,7 @@ private: return tmp.subspan(offset, count); } - // clang-format off - GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(bounds.1) constexpr span make_subspan(size_type offset, size_type count, subspan_selector) const noexcept { @@ -792,7 +772,9 @@ span(const Container&) -> span; #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) #if defined(__clang__) && defined(_MSC_VER) && defined(__cplusplus) && (__cplusplus < 201703L) #pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated" // Bug in clang-cl.exe which raises a C++17 -Wdeprecated warning about this static constexpr workaround in C++14 mode. +#pragma clang diagnostic ignored \ + "-Wdeprecated" // Bug in clang-cl.exe which raises a C++17 -Wdeprecated warning about this + // static constexpr workaround in C++14 mode. #endif // defined(__clang__) && defined(_MSC_VER) && defined(__cplusplus) && (__cplusplus < 201703L) template constexpr const typename span::size_type span::extent; @@ -827,11 +809,10 @@ template span::value> as_bytes(span s) noexcept { - using type = span::value>; + using type = + span::value>; - // clang-format off - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(type.1) return type{reinterpret_cast(s.data()), s.size_bytes()}; } @@ -842,9 +823,7 @@ as_writable_bytes(span s) noexcept { using type = span::value>; - // clang-format off - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(type.1) return type{reinterpret_cast(s.data()), s.size_bytes()}; } diff --git a/include/gsl/util b/include/gsl/util index 7a3caed..e6dbb86 100644 --- a/include/gsl/util +++ b/include/gsl/util @@ -21,8 +21,8 @@ #include #include // for ptrdiff_t, size_t -#include // for numeric_limits #include // for initializer_list +#include // for numeric_limits #include // for is_signed, integral_constant #include // for exchange, forward @@ -100,18 +100,21 @@ template class final_action { public: - explicit final_action(const F& ff) noexcept : f{ff} { } - explicit final_action(F&& ff) noexcept : f{std::move(ff)} { } + explicit final_action(const F& ff) noexcept : f{ff} {} + explicit final_action(F&& ff) noexcept : f{std::move(ff)} {} - ~final_action() noexcept { if (invoke) f(); } + ~final_action() noexcept + { + if (invoke) f(); + } final_action(final_action&& other) noexcept : f(std::move(other.f)), invoke(std::exchange(other.invoke, false)) - { } + {} - final_action(const final_action&) = delete; + final_action(const final_action&) = delete; void operator=(const final_action&) = delete; - void operator=(final_action&&) = delete; + void operator=(final_action&&) = delete; private: F f; @@ -127,10 +130,7 @@ GSL_NODISCARD auto finally(F&& f) noexcept // narrow_cast(): a searchable way to do narrowing casts of values template -// clang-format off -GSL_SUPPRESS(type.1) // NO-FORMAT: attribute - // clang-format on - constexpr T narrow_cast(U&& u) noexcept +GSL_SUPPRESS(type.1) constexpr T narrow_cast(U&& u) noexcept { return static_cast(std::forward(u)); } @@ -139,23 +139,17 @@ GSL_SUPPRESS(type.1) // NO-FORMAT: attribute // at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector // template -// clang-format off -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute - // clang-format on - constexpr T& at(T (&arr)[N], const index i) +GSL_SUPPRESS(bounds.4) GSL_SUPPRESS(bounds.2) constexpr T& at(T (&arr)[N], const index i) { - static_assert(N <= static_cast((std::numeric_limits::max)()), "We only support arrays up to PTRDIFF_MAX bytes."); + static_assert(N <= static_cast((std::numeric_limits::max)()), + "We only support arrays up to PTRDIFF_MAX bytes."); Expects(i >= 0 && i < narrow_cast(N)); return arr[narrow_cast(i)]; } template -// clang-format off -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute - // clang-format on - constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()]) +GSL_SUPPRESS(bounds.4) GSL_SUPPRESS(bounds.2) constexpr auto at(Cont& cont, const index i) + -> decltype(cont[cont.size()]) { Expects(i >= 0 && i < narrow_cast(cont.size())); using size_type = decltype(cont.size()); @@ -163,17 +157,18 @@ GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute } template -// clang-format off -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on - constexpr T at(const std::initializer_list cont, const index i) +GSL_SUPPRESS(bounds.1) constexpr T at(const std::initializer_list cont, const index i) { Expects(i >= 0 && i < narrow_cast(cont.size())); return *(cont.begin() + i); } -template ::value && std::is_move_constructible::value>> -void swap(T& a, T& b) { std::swap(a, b); } +template ::value && + std::is_move_constructible::value>> +void swap(T& a, T& b) +{ + std::swap(a, b); +} #if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L template diff --git a/include/gsl/zstring b/include/gsl/zstring index f00aa05..a718251 100644 --- a/include/gsl/zstring +++ b/include/gsl/zstring @@ -19,7 +19,7 @@ #include "./span_ext" // for dynamic_extent -#include // for size_t, nullptr_t +#include // for size_t, nullptr_t namespace gsl { diff --git a/scripts/apply-formatting.bat b/scripts/apply-formatting.bat new file mode 100644 index 0000000..397dccf --- /dev/null +++ b/scripts/apply-formatting.bat @@ -0,0 +1,13 @@ +@echo off +setlocal enabledelayedexpansion + +"%VCINSTALLDIR%Tools\Llvm\bin\clang-format" -version +if %errorlevel% neq 0 ( + echo [ERROR] clang-format not found, script should be called from a visual studio developer command prompt. + exit /b %errorlevel% +) + +for %%f in (include\gsl\* tests\*.h tests\*.cpp) do ( + echo formatting %%f + "%VCINSTALLDIR%Tools\Llvm\bin\clang-format" -i --assume-filename x.cpp "%%f" +) diff --git a/scripts/apply-formatting.sh b/scripts/apply-formatting.sh new file mode 100644 index 0000000..560d9b5 --- /dev/null +++ b/scripts/apply-formatting.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -euo pipefail + +cf=clang-format-$(grep -i 'CLANG_VERSION:' .github/workflows/clang-format.yml | sed -E 's/.*"([^"]+)".*/\1/') +readonly cf + +if ! "${cf}" -version; then + echo "[ERROR] clang-format not found. Please install it using: sudo apt install ${cf}" + exit 1 +fi + +{ + find include/gsl -type f + find tests -type f \( -name '*.cpp' -o -name '*.h' \) +} | xargs "${cf}" -i --assume-filename=x.cpp --verbose + +find scripts -type f -name '*.sh' -print -exec shfmt -w {} \; diff --git a/tests/at_tests.cpp b/tests/at_tests.cpp index 42b2241..a280907 100644 --- a/tests/at_tests.cpp +++ b/tests/at_tests.cpp @@ -32,7 +32,7 @@ TEST(at_tests, static_array) { int a[4] = {1, 2, 3, 4}; - const int(&c_a)[4] = a; + const int (&c_a)[4] = a; for (int i = 0; i < 4; ++i) { @@ -152,7 +152,7 @@ TEST(at_tests, std_span) static constexpr bool test_constexpr() { int a1[4] = {1, 2, 3, 4}; - const int(&c_a1)[4] = a1; + const int (&c_a1)[4] = a1; std::array a2 = {1, 2, 3, 4}; const std::array& c_a2 = a2; diff --git a/tests/byte_tests.cpp b/tests/byte_tests.cpp index 77a947a..e361e8a 100644 --- a/tests/byte_tests.cpp +++ b/tests/byte_tests.cpp @@ -171,8 +171,8 @@ static_assert(!RShiftAssignCompilesFor, "!RShiftAssignCompilesFor" template static constexpr bool ToIntegerCompilesFor = false; template -static constexpr bool - ToIntegerCompilesFor(gsl::byte{}))>> = true; +static constexpr bool ToIntegerCompilesFor(gsl::byte{}))>> = + true; static_assert(!ToIntegerCompilesFor, "!ToIntegerCompilesFor"); } // namespace diff --git a/tests/constexpr_notnull_tests.cpp b/tests/constexpr_notnull_tests.cpp index 9192f85..f735b14 100644 --- a/tests/constexpr_notnull_tests.cpp +++ b/tests/constexpr_notnull_tests.cpp @@ -28,15 +28,15 @@ constexpr bool comparison_test(const int* ptr1, const int* ptr2) const not_null p1(ptr1); const not_null p1_same(ptr1); const not_null p2(ptr2); - + // Testing operator== const bool eq_result = (p1 == p1_same); // Should be true const bool neq_result = (p1 != p2); // Should be true - + // Testing operator<= and operator>= const bool le_result = (p1 <= p1_same); // Should be true const bool ge_result = (p1 >= p1_same); // Should be true - + // The exact comparison results will depend on pointer ordering, // but we can verify that the basic equality checks work as expected return eq_result && neq_result && le_result && ge_result; @@ -47,11 +47,11 @@ constexpr bool workaround_test(const int* ptr1, const int* ptr2) const not_null p1(ptr1); const not_null p1_same(ptr1); const not_null p2(ptr2); - + // Using .get() to compare const bool eq_result = (p1.get() == p1_same.get()); // Should be true const bool neq_result = (p1.get() != p2.get()); // Should be true - + return eq_result && neq_result; } } // namespace @@ -59,8 +59,10 @@ constexpr bool workaround_test(const int* ptr1, const int* ptr2) constexpr int test_value1 = 1; constexpr int test_value2 = 2; -static_assert(comparison_test(&test_value1, &test_value2), "not_null comparison operators should be constexpr"); -static_assert(workaround_test(&test_value1, &test_value2), "not_null .get() comparison workaround should work"); +static_assert(comparison_test(&test_value1, &test_value2), + "not_null comparison operators should be constexpr"); +static_assert(workaround_test(&test_value1, &test_value2), + "not_null .get() comparison workaround should work"); TEST(notnull_constexpr_tests, TestNotNullConstexprComparison) { @@ -71,4 +73,3 @@ TEST(notnull_constexpr_tests, TestNotNullConstexprComparison) EXPECT_TRUE(comparison_test(&value1, &value2)); EXPECT_TRUE(workaround_test(&value1, &value2)); } - diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index 8cb9f86..178433f 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -69,9 +69,7 @@ struct CustomPtr template std::string operator==(CustomPtr const& lhs, CustomPtr const& rhs) { - // clang-format off - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(type.1) return reinterpret_cast(lhs.p_) == reinterpret_cast(rhs.p_) ? "true" : "false"; } @@ -79,9 +77,7 @@ std::string operator==(CustomPtr const& lhs, CustomPtr const& rhs) template std::string operator!=(CustomPtr const& lhs, CustomPtr const& rhs) { - // clang-format off - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(type.1) return reinterpret_cast(lhs.p_) != reinterpret_cast(rhs.p_) ? "true" : "false"; } @@ -89,9 +85,7 @@ std::string operator!=(CustomPtr const& lhs, CustomPtr const& rhs) template std::string operator<(CustomPtr const& lhs, CustomPtr const& rhs) { - // clang-format off - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(type.1) return reinterpret_cast(lhs.p_) < reinterpret_cast(rhs.p_) ? "true" : "false"; } @@ -99,9 +93,7 @@ std::string operator<(CustomPtr const& lhs, CustomPtr const& rhs) template std::string operator>(CustomPtr const& lhs, CustomPtr const& rhs) { - // clang-format off - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(type.1) return reinterpret_cast(lhs.p_) > reinterpret_cast(rhs.p_) ? "true" : "false"; } @@ -109,9 +101,7 @@ std::string operator>(CustomPtr const& lhs, CustomPtr const& rhs) template std::string operator<=(CustomPtr const& lhs, CustomPtr const& rhs) { - // clang-format off - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(type.1) return reinterpret_cast(lhs.p_) <= reinterpret_cast(rhs.p_) ? "true" : "false"; } @@ -119,9 +109,7 @@ std::string operator<=(CustomPtr const& lhs, CustomPtr const& rhs) template std::string operator>=(CustomPtr const& lhs, CustomPtr const& rhs) { - // clang-format off - GSL_SUPPRESS(type.1) // NO-FORMAT: attribute - // clang-format on + GSL_SUPPRESS(type.1) return reinterpret_cast(lhs.p_) >= reinterpret_cast(rhs.p_) ? "true" : "false"; } @@ -137,13 +125,9 @@ struct NonCopyableNonMovable namespace { -// clang-format off -GSL_SUPPRESS(f.4) // NO-FORMAT: attribute -// clang-format on +GSL_SUPPRESS(f.4) bool helper(not_null p) { return *p == 12; } -// clang-format off -GSL_SUPPRESS(f.4) // NO-FORMAT: attribute -// clang-format on +GSL_SUPPRESS(f.4) bool helper_const(not_null p) { return *p == 12; } int* return_pointer() { return nullptr; } diff --git a/tests/owner_tests.cpp b/tests/owner_tests.cpp index 0cb47e8..c6373d2 100644 --- a/tests/owner_tests.cpp +++ b/tests/owner_tests.cpp @@ -21,7 +21,7 @@ using namespace gsl; -GSL_SUPPRESS(f.23) // NO-FORMAT: attribute +GSL_SUPPRESS(f.23) void f(int* i) { *i += 1; } TEST(owner_tests, basic_test) @@ -43,8 +43,7 @@ using void_t = void; template static constexpr bool OwnerCompilesFor = false; template -static constexpr bool OwnerCompilesFor{})>> = - true; +static constexpr bool OwnerCompilesFor{})>> = true; static_assert(OwnerCompilesFor, "OwnerCompilesFor"); static_assert(!OwnerCompilesFor, "!OwnerCompilesFor"); static_assert(!OwnerCompilesFor>, "!OwnerCompilesFor>"); diff --git a/tests/pointers_tests.cpp b/tests/pointers_tests.cpp index fcee2ed..72f761f 100644 --- a/tests/pointers_tests.cpp +++ b/tests/pointers_tests.cpp @@ -44,7 +44,8 @@ TEST(pointers_test, swap) gsl::not_null> a(std::make_unique(0)); gsl::not_null> b(std::make_unique(1)); - static_assert(noexcept(gsl::swap(a, b)), "not null unique_ptr should be noexcept-swappable"); + static_assert(noexcept(gsl::swap(a, b)), + "not null unique_ptr should be noexcept-swappable"); EXPECT_TRUE(*a == 0); EXPECT_TRUE(*b == 1); @@ -65,7 +66,8 @@ TEST(pointers_test, swap) gsl::strict_not_null> a{std::make_unique(0)}; gsl::strict_not_null> b{std::make_unique(1)}; - static_assert(noexcept(gsl::swap(a, b)), "strict not null unique_ptr should be noexcept-swappable"); + static_assert(noexcept(gsl::swap(a, b)), + "strict not null unique_ptr should be noexcept-swappable"); EXPECT_TRUE(*a == 0); EXPECT_TRUE(*b == 1); diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index 3aad961..e0ee7fd 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -61,10 +61,10 @@ void ArrayConvertibilityCheck() static_assert(std::is_same>::value, "std::is_same< decltype(span{stl_nullptr}), span>::value"); - static_assert( - std::is_same>::value, - "std::is_same< decltype(span{std::as_const(stl_nullptr)}), span>::value"); + static_assert(std::is_same>::value, + "std::is_same< decltype(span{std::as_const(stl_nullptr)}), span>::value"); } #endif } diff --git a/tests/span_ext_tests.cpp b/tests/span_ext_tests.cpp index dfd2725..25aa46f 100644 --- a/tests/span_ext_tests.cpp +++ b/tests/span_ext_tests.cpp @@ -114,7 +114,7 @@ TEST(span_ext_test, make_span_from_array_constructor) TEST(span_ext_test, make_span_from_dynamic_array_constructor) { - double(*arr)[3][4] = new double[100][3][4]; + double (*arr)[3][4] = new double[100][3][4]; { auto s = make_span(&arr[0][0][0], 10); diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 9b74ad4..3edf179 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -257,7 +257,9 @@ TEST(span_test, from_pointer_pointer_construction) EXPECT_TRUE(s.data() == &arr[0]); } - //{ // this test succeeds on all platforms, gsl::span is more relaxed than std::span where this would be UB + // this test succeeds on all platforms, gsl::span is more relaxed than std::span where this + // would be UB + //{ // auto workaround_macro = [&]() { span s{&arr[1], &arr[0]}; }; // EXPECT_DEATH(workaround_macro(), expected); //} @@ -342,7 +344,7 @@ TEST(span_test, from_array_constructor) TEST(span_test, from_dynamic_array_constructor) { - double(*arr)[3][4] = new double[100][3][4]; + double (*arr)[3][4] = new double[100][3][4]; { span s(&arr[0][0][0], 10); diff --git a/tests/strict_notnull_tests.cpp b/tests/strict_notnull_tests.cpp index 0626d8f..2879e01 100644 --- a/tests/strict_notnull_tests.cpp +++ b/tests/strict_notnull_tests.cpp @@ -41,24 +41,16 @@ struct RefCounted namespace { -// clang-format off -GSL_SUPPRESS(f.4) // NO-FORMAT: attribute -// clang-format on +GSL_SUPPRESS(f.4) bool helper(not_null p) { return *p == 12; } -// clang-format off -GSL_SUPPRESS(f.4) // NO-FORMAT: attribute -// clang-format on +GSL_SUPPRESS(f.4) bool helper_const(not_null p) { return *p == 12; } -// clang-format off -GSL_SUPPRESS(f.4) // NO-FORMAT: attribute -// clang-format on +GSL_SUPPRESS(f.4) bool strict_helper(strict_not_null p) { return *p == 12; } -// clang-format off -GSL_SUPPRESS(f.4) // NO-FORMAT: attribute -// clang-format on +GSL_SUPPRESS(f.4) bool strict_helper_const(strict_not_null p) { return *p == 12; } int* return_pointer() { return nullptr; } @@ -195,7 +187,6 @@ template static constexpr bool StrictHelperCompilesFor()))>> = true; - template static constexpr bool StrictHelperConstCompilesFor = false; template @@ -203,7 +194,6 @@ static constexpr bool StrictHelperConstCompilesFor()))>> = true; - template static constexpr bool HelperCompilesFor = false; template @@ -219,13 +209,12 @@ TEST(strict_notnull_tests, TestStrictNotNull) strict_not_null snn = &x; #endif static_assert(!StrictHelperCompilesFor, "!StrictHelperCompilesFor"); - static_assert(!StrictHelperConstCompilesFor, - "!StrictHelperCompilesFor"); + static_assert(!StrictHelperConstCompilesFor, "!StrictHelperCompilesFor"); const strict_not_null snn1{&x}; static_assert(StrictHelperCompilesFor>, - "StrictHelperCompilesFor>"); + "StrictHelperCompilesFor>"); helper(snn1); helper_const(snn1); diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index 5b64e20..cb82ec2 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -16,7 +16,7 @@ #include -#include // for move +#include // for move #include #include // for std::ptrdiff_t #include // for uint32_t, int32_t @@ -156,8 +156,8 @@ TEST(utils_tests, narrow) n = -42; EXPECT_THROW(narrow(n), narrowing_error); - EXPECT_TRUE( - narrow>(std::complex(4, 2)) == std::complex(4, 2)); + EXPECT_TRUE(narrow>(std::complex(4, 2)) == + std::complex(4, 2)); EXPECT_THROW(narrow>(std::complex(4.2)), narrowing_error); EXPECT_TRUE(narrow(float(1)) == 1);