diff --git a/include/xgboost/collective/socket.h b/include/xgboost/collective/socket.h index bf5fffdaf155..a025edddd409 100644 --- a/include/xgboost/collective/socket.h +++ b/include/xgboost/collective/socket.h @@ -686,8 +686,11 @@ class TCPSocket { * \return size of data actually received return -1 if error occurs */ auto Recv(void *buf, std::size_t len, std::int32_t flags = 0) { - char *_buf = reinterpret_cast(buf); + char *_buf = static_cast(buf); + // See https://github.com/llvm/llvm-project/issues/104241 for skipped tidy analysis + // NOLINTBEGIN(clang-analyzer-unix.BlockInCriticalSection) return recv(handle_, _buf, len, flags); + // NOLINTEND(clang-analyzer-unix.BlockInCriticalSection) } /** * \brief Send string, format is matched with the Python socket wrapper in RABIT. diff --git a/include/xgboost/host_device_vector.h b/include/xgboost/host_device_vector.h index 36c7ed32b83d..d9dfeadbc7eb 100644 --- a/include/xgboost/host_device_vector.h +++ b/include/xgboost/host_device_vector.h @@ -85,7 +85,7 @@ enum GPUAccess { template class HostDeviceVector { - static_assert(std::is_standard_layout::value, "HostDeviceVector admits only POD types"); + static_assert(std::is_standard_layout_v, "HostDeviceVector admits only POD types"); public: explicit HostDeviceVector(size_t size = 0, T v = T(), DeviceOrd device = DeviceOrd::CPU()); diff --git a/include/xgboost/json.h b/include/xgboost/json.h index 1416b8899785..82bc56f76b52 100644 --- a/include/xgboost/json.h +++ b/include/xgboost/json.h @@ -11,9 +11,8 @@ #include #include -#include #include -#include // std::enable_if,std::enable_if_t +#include // std::enable_if_t #include #include @@ -223,6 +222,14 @@ class JsonObject : public Value { ~JsonObject() override = default; }; +namespace detail { +template +using IsSameT = std::enable_if_t, std::remove_cv_t>>; + +template +using IsF64T = std::enable_if_t>; +} // namespace detail + class JsonNumber : public Value { public: using Float = float; @@ -232,15 +239,11 @@ class JsonNumber : public Value { public: JsonNumber() : Value(ValueKind::kNumber) {} - template ::value>::type* = nullptr> - JsonNumber(FloatT value) : Value(ValueKind::kNumber) { // NOLINT - number_ = value; - } - template ::value>::type* = nullptr> - JsonNumber(FloatT value) : Value{ValueKind::kNumber}, // NOLINT - number_{static_cast(value)} {} + template * = nullptr> + JsonNumber(FloatT value) : Value(ValueKind::kNumber), number_{value} {} // NOLINT + template * = nullptr> + JsonNumber(FloatT value) // NOLINT + : Value{ValueKind::kNumber}, number_{static_cast(value)} {} JsonNumber(JsonNumber const& that) = delete; JsonNumber(JsonNumber&& that) noexcept : Value{ValueKind::kNumber}, number_{that.number_} {} @@ -258,6 +261,13 @@ class JsonNumber : public Value { } }; +namespace detail { +template +using Not32SizeT = std::enable_if_t && + !std::is_same_v>; +} + + class JsonInteger : public Value { public: using Int = int64_t; @@ -267,24 +277,18 @@ class JsonInteger : public Value { public: JsonInteger() : Value(ValueKind::kInteger) {} // NOLINT + template * = nullptr> + JsonInteger(IntT value) : Value(ValueKind::kInteger), integer_{value} {} // NOLINT + template * = nullptr> + JsonInteger(IntT value) // NOLINT + : Value(ValueKind::kInteger), integer_{static_cast(value)} {} + template * = nullptr> + JsonInteger(IntT value) // NOLINT + : Value(ValueKind::kInteger), integer_{static_cast(value)} {} template ::value>::type* = nullptr> - JsonInteger(IntT value) : Value(ValueKind::kInteger), integer_{value} {} // NOLINT - template ::value>::type* = nullptr> - JsonInteger(IntT value) : Value(ValueKind::kInteger), // NOLINT - integer_{static_cast(value)} {} - template ::value>::type* = nullptr> - JsonInteger(IntT value) : Value(ValueKind::kInteger), // NOLINT - integer_{static_cast(value)} {} - template ::value && - !std::is_same::value>::type * = nullptr> + typename detail::Not32SizeT* = nullptr> JsonInteger(IntT value) // NOLINT - : Value(ValueKind::kInteger), - integer_{static_cast(value)} {} + : Value(ValueKind::kInteger), integer_{static_cast(value)} {} JsonInteger(JsonInteger &&that) noexcept : Value{ValueKind::kInteger}, integer_{that.integer_} {} @@ -325,12 +329,8 @@ class JsonBoolean : public Value { public: JsonBoolean() : Value(ValueKind::kBoolean) {} // NOLINT // Ambigious with JsonNumber. - template ::value || - std::is_same::value>::type* = nullptr> - JsonBoolean(Bool value) : // NOLINT - Value(ValueKind::kBoolean), boolean_{value} {} + template , bool>* = nullptr> + JsonBoolean(Bool value) : Value(ValueKind::kBoolean), boolean_{value} {} // NOLINT JsonBoolean(JsonBoolean&& value) noexcept: // NOLINT Value(ValueKind::kBoolean), boolean_{value.boolean_} {} @@ -506,71 +506,52 @@ bool IsA(Json const& j) { namespace detail { // Number -template ::value>::type* = nullptr> +template >* = nullptr> JsonNumber::Float& GetImpl(T& val) { // NOLINT return val.GetNumber(); } -template ::value>::type* = nullptr> +template >* = nullptr> JsonNumber::Float const& GetImpl(T& val) { // NOLINT return val.GetNumber(); } // Integer -template ::value>::type* = nullptr> +template >* = nullptr> JsonInteger::Int& GetImpl(T& val) { // NOLINT return val.GetInteger(); } -template ::value>::type* = nullptr> +template >* = nullptr> JsonInteger::Int const& GetImpl(T& val) { // NOLINT return val.GetInteger(); } // String -template ::value>::type* = nullptr> +template >* = nullptr> std::string& GetImpl(T& val) { // NOLINT return val.GetString(); } -template ::value>::type* = nullptr> +template >* = nullptr> std::string const& GetImpl(T& val) { // NOLINT return val.GetString(); } // Boolean -template ::value>::type* = nullptr> +template >* = nullptr> bool& GetImpl(T& val) { // NOLINT return val.GetBoolean(); } template ::value>::type* = nullptr> + typename std::enable_if_t>* = nullptr> bool const& GetImpl(T& val) { // NOLINT return val.GetBoolean(); } // Array -template ::value>::type* = nullptr> +template >* = nullptr> std::vector& GetImpl(T& val) { // NOLINT return val.GetArray(); } -template ::value>::type* = nullptr> +template >* = nullptr> std::vector const& GetImpl(T& val) { // NOLINT return val.GetArray(); } @@ -586,12 +567,11 @@ std::vector const& GetImpl(JsonTypedArray const& val) { } // Object -template ::value>::type* = nullptr> +template >* = nullptr> JsonObject::Map& GetImpl(T& val) { // NOLINT return val.GetObject(); } -template ::value>::type* = nullptr> +template >* = nullptr> JsonObject::Map const& GetImpl(T& val) { // NOLINT return val.GetObject(); } diff --git a/include/xgboost/json_io.h b/include/xgboost/json_io.h index ce3d25c37e19..57f8005ab777 100644 --- a/include/xgboost/json_io.h +++ b/include/xgboost/json_io.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2023, XGBoost Contributors + * Copyright 2019-2024, XGBoost Contributors */ #ifndef XGBOOST_JSON_IO_H_ #define XGBOOST_JSON_IO_H_ @@ -7,11 +7,8 @@ #include #include -#include +#include // for int8_t #include -#include -#include -#include #include #include #include @@ -111,7 +108,7 @@ class JsonReader { }; class JsonWriter { - template ::value>* = nullptr> + template >* = nullptr> void Save(T const& v) { this->Save(Json{v}); } diff --git a/include/xgboost/linalg.h b/include/xgboost/linalg.h index 553486dac330..384ba0942a90 100644 --- a/include/xgboost/linalg.h +++ b/include/xgboost/linalg.h @@ -43,9 +43,9 @@ namespace detail { struct ArrayInterfaceHandler { template static constexpr char TypeChar() { - return (std::is_floating_point::value + return (std::is_floating_point_v ? 'f' - : (std::is_integral::value ? (std::is_signed::value ? 'i' : 'u') : '\0')); + : (std::is_integral_v ? (std::is_signed_v ? 'i' : 'u') : '\0')); } }; @@ -93,7 +93,7 @@ struct RangeTag { */ template constexpr int32_t CalcSliceDim() { - return std::is_same::value ? 0 : 1; + return std::is_same_v ? 0 : 1; } template @@ -114,7 +114,7 @@ template using RemoveCRType = std::remove_const_t>; template -using IndexToTag = std::conditional_t>::value, IntTag, S>; +using IndexToTag = std::conditional_t>, IntTag, S>; template LINALG_HD constexpr auto UnrollLoop(Fn fn) { @@ -159,7 +159,7 @@ inline LINALG_HD int Popc(uint64_t v) { template LINALG_HD void IndexToArr(std::size_t (&arr)[D], Head head) { - static_assert(std::is_integral>::value, "Invalid index type."); + static_assert(std::is_integral_v>, "Invalid index type."); arr[D - 1] = head; } @@ -169,7 +169,7 @@ LINALG_HD void IndexToArr(std::size_t (&arr)[D], Head head) { template LINALG_HD void IndexToArr(std::size_t (&arr)[D], Head head, Rest &&...index) { static_assert(sizeof...(Rest) < D, "Index overflow."); - static_assert(std::is_integral>::value, "Invalid index type."); + static_assert(std::is_integral_v>, "Invalid index type."); arr[D - sizeof...(Rest) - 1] = head; IndexToArr(arr, std::forward(index)...); } @@ -193,7 +193,7 @@ constexpr auto ArrToTuple(T (&arr)[N]) { template LINALG_HD auto UnravelImpl(I idx, common::Span shape) { std::size_t index[D]{0}; - static_assert(std::is_signed::value, + static_assert(std::is_signed_v, "Don't change the type without changing the for loop."); auto const sptr = shape.data(); for (int32_t dim = D; --dim > 0;) { @@ -379,7 +379,7 @@ class TensorView { * \brief Slice dimension for Index tag. */ template - LINALG_HD std::enable_if_t::value, size_t> MakeSliceDim( + LINALG_HD std::enable_if_t, size_t> MakeSliceDim( size_t new_shape[D], size_t new_stride[D], Index i, S &&...slices) const { static_assert(old_dim < kDim); auto offset = stride_[old_dim] * i; @@ -547,7 +547,7 @@ class TensorView { */ [[nodiscard]] LINALG_HD bool CContiguous() const { StrideT stride; - static_assert(std::is_same::value); + static_assert(std::is_same_v); // It's contiguous if the stride can be calculated from shape. detail::CalcStride(shape_, stride); return common::Span{stride_} == common::Span{stride}; @@ -557,7 +557,7 @@ class TensorView { */ [[nodiscard]] LINALG_HD bool FContiguous() const { StrideT stride; - static_assert(std::is_same::value); + static_assert(std::is_same_v); // It's contiguous if the stride can be calculated from shape. detail::CalcStride(shape_, stride); return common::Span{stride_} == common::Span{stride}; diff --git a/include/xgboost/parameter.h b/include/xgboost/parameter.h index 063f1aca7cd0..d8188c030360 100644 --- a/include/xgboost/parameter.h +++ b/include/xgboost/parameter.h @@ -55,7 +55,7 @@ class FieldEntry : public FieldEntry { \ public: \ FieldEntry() { \ static_assert( \ - std::is_same::type>::value, \ + std::is_same_v>, \ "enum class must be backed by int"); \ is_enum_ = true; \ } \ diff --git a/include/xgboost/span.h b/include/xgboost/span.h index 7471c2e44ed6..579737a59033 100644 --- a/include/xgboost/span.h +++ b/include/xgboost/span.h @@ -1,5 +1,5 @@ /** - * Copyright 2018-2023, XGBoost contributors + * Copyright 2018-2024, XGBoost contributors * \brief span class based on ISO++20 span * * About NOLINTs in this file: @@ -129,9 +129,8 @@ namespace detail { * represent ptrdiff_t, which is just int64_t. So we make it deterministic * here. */ -using ptrdiff_t = typename std::conditional< // NOLINT - std::is_same::value, - std::ptrdiff_t, std::int64_t>::type; +using ptrdiff_t = typename std::conditional_t< // NOLINT + std::is_same_v, std::ptrdiff_t, std::int64_t>; } // namespace detail #if defined(_MSC_VER) && _MSC_VER < 1910 @@ -169,8 +168,8 @@ class SpanIterator { span_(_span), index_(_idx) {} friend SpanIterator; - template ::type* = nullptr> - XGBOOST_DEVICE constexpr SpanIterator( // NOLINT + template * = nullptr> + XGBOOST_DEVICE constexpr SpanIterator( // NOLINT const SpanIterator& other_) __span_noexcept : SpanIterator(other_.span_, other_.index_) {} @@ -303,8 +302,8 @@ struct IsAllowedExtentConversion : public std::integral_constant< bool, From == To || From == dynamic_extent || To == dynamic_extent> {}; template -struct IsAllowedElementTypeConversion : public std::integral_constant< - bool, std::is_convertible::value> {}; +struct IsAllowedElementTypeConversion + : public std::integral_constant> {}; // NOLINT template struct IsSpanOracle : std::false_type {}; @@ -313,7 +312,7 @@ template struct IsSpanOracle> : std::true_type {}; template -struct IsSpan : public IsSpanOracle::type> {}; +struct IsSpan : public IsSpanOracle> {}; // Re-implement std algorithms here to adopt CUDA. template @@ -452,35 +451,34 @@ class Span { __span_noexcept : size_(N), data_(&arr[0]) {} template ::value && - !detail::IsSpan::value && - std::is_convertible::value && - std::is_convertible().data())>::value>::type> - Span(Container& _cont) : // NOLINT - size_(_cont.size()), data_(_cont.data()) { + class = typename std::enable_if_t< + !std::is_const_v && !detail::IsSpan::value && + std::is_convertible_v && + std::is_convertible_v().data())>>> + Span(Container& _cont) // NOLINT + : size_(_cont.size()), data_(_cont.data()) { static_assert(!detail::IsSpan::value, "Wrong constructor of Span is called."); } template ::value && - !detail::IsSpan::value && - std::is_convertible::value && - std::is_convertible().data())>::value>::type> - Span(const Container& _cont) : size_(_cont.size()), // NOLINT - data_(_cont.data()) { + class = typename std::enable_if_t< + std::is_const_v && !detail::IsSpan::value && + std::is_convertible_v && + std::is_convertible_v().data())>>> + Span(const Container& _cont) // NOLINT + : size_(_cont.size()), data_(_cont.data()) { static_assert(!detail::IsSpan::value, "Wrong constructor of Span is called."); } template ::value && - detail::IsAllowedExtentConversion::value>> - XGBOOST_DEVICE constexpr Span(const Span& _other) // NOLINT - __span_noexcept : size_(_other.size()), data_(_other.data()) {} + class = typename std::enable_if_t< + detail::IsAllowedElementTypeConversion::value && + detail::IsAllowedExtentConversion::value>> + XGBOOST_DEVICE constexpr Span(const Span& _other) // NOLINT + __span_noexcept : size_(_other.size()), + data_(_other.data()) {} XGBOOST_DEVICE constexpr Span(const Span& _other) __span_noexcept : size_(_other.size()), data_(_other.data()) {} diff --git a/src/collective/in_memory_handler.cc b/src/collective/in_memory_handler.cc index 468f09c53048..37be3f9c7127 100644 --- a/src/collective/in_memory_handler.cc +++ b/src/collective/in_memory_handler.cc @@ -82,7 +82,7 @@ class AllreduceFunctor { } private: - template ::value>* = nullptr> + template >* = nullptr> void AccumulateBitwise(T* buffer, T const* input, std::size_t size, Op reduce_operation) const { switch (reduce_operation) { case Op::kBitwiseAND: @@ -99,7 +99,7 @@ class AllreduceFunctor { } } - template ::value>* = nullptr> + template >* = nullptr> void AccumulateBitwise(T*, T const*, std::size_t, Op) const { LOG(FATAL) << "Floating point types do not support bitwise operations."; } diff --git a/src/common/device_helpers.cuh b/src/common/device_helpers.cuh index 3adc39e73777..00b2a65f85af 100644 --- a/src/common/device_helpers.cuh +++ b/src/common/device_helpers.cuh @@ -81,8 +81,8 @@ struct AtomicDispatcher { // atomicAdd is not defined for size_t. template ::value && - !std::is_same::value> * = // NOLINT + std::enable_if_t && + !std::is_same_v> * = // NOLINT nullptr> XGBOOST_DEV_INLINE T atomicAdd(T *addr, T v) { // NOLINT using Type = typename dh::detail::AtomicDispatcher::Type; @@ -381,7 +381,7 @@ void CopyTo(Src const &src, Dst *dst) { dst->resize(src.size()); using SVT = std::remove_cv_t; using DVT = std::remove_cv_t; - static_assert(std::is_same::value, + static_assert(std::is_same_v, "Host and device containers must have same value type."); dh::safe_cuda(cudaMemcpyAsync(thrust::raw_pointer_cast(dst->data()), src.data(), src.size() * sizeof(SVT), cudaMemcpyDefault)); diff --git a/src/common/json.cc b/src/common/json.cc index 2887eeccf855..da3df5366169 100644 --- a/src/common/json.cc +++ b/src/common/json.cc @@ -224,11 +224,11 @@ void JsonArray::Save(JsonWriter* writer) const { writer->Visit(this); } namespace { // error C2668: 'fpclassify': ambiguous call to overloaded function template -std::enable_if_t::value, bool> IsInfMSVCWar(T v) { +std::enable_if_t, bool> IsInfMSVCWar(T v) { return std::isinf(v); } template -std::enable_if_t::value, bool> IsInfMSVCWar(T) { +std::enable_if_t, bool> IsInfMSVCWar(T) { return false; } } // namespace @@ -247,7 +247,7 @@ bool JsonTypedArray::operator==(Value const& rhs) const { if (vec_.size() != arr.size()) { return false; } - if (std::is_same::value) { + if (std::is_same_v) { for (size_t i = 0; i < vec_.size(); ++i) { bool equal{false}; if (common::CheckNAN(vec_[i])) { @@ -693,10 +693,10 @@ void Json::Dump(Json json, JsonWriter* writer) { writer->Save(json); } -static_assert(std::is_nothrow_move_constructible::value); -static_assert(std::is_nothrow_move_constructible::value); -static_assert(std::is_nothrow_move_constructible::value); -static_assert(std::is_nothrow_move_constructible::value); +static_assert(std::is_nothrow_move_constructible_v); +static_assert(std::is_nothrow_move_constructible_v); +static_assert(std::is_nothrow_move_constructible_v); +static_assert(std::is_nothrow_move_constructible_v); Json UBJReader::ParseArray() { auto marker = PeekNextChar(); @@ -887,17 +887,17 @@ template void WriteTypedArray(JsonTypedArray const* arr, std::vector* stream) { stream->emplace_back('['); stream->push_back('$'); - if (std::is_same::value) { + if (std::is_same_v) { stream->push_back('d'); } else if (std::is_same_v) { stream->push_back('D'); - } else if (std::is_same::value) { + } else if (std::is_same_v) { stream->push_back('i'); - } else if (std::is_same::value) { + } else if (std::is_same_v) { stream->push_back('U'); - } else if (std::is_same::value) { + } else if (std::is_same_v) { stream->push_back('l'); - } else if (std::is_same::value) { + } else if (std::is_same_v) { stream->push_back('L'); } else { LOG(FATAL) << "Not implemented"; diff --git a/src/common/math.h b/src/common/math.h index be5ff7abd500..3c64ec39937b 100644 --- a/src/common/math.h +++ b/src/common/math.h @@ -12,7 +12,7 @@ #include // for max #include // for exp, abs, log, lgamma #include // for numeric_limits -#include // for is_floating_point, conditional, is_signed, is_same, declval, enable_if +#include // for is_floating_point_v, conditional, is_signed, is_same, declval #include // for pair namespace xgboost { @@ -43,15 +43,11 @@ XGBOOST_DEVICE inline double Sigmoid(double x) { */ template XGBOOST_DEVICE constexpr bool CloseTo(T a, U b) { - using Casted = - typename std::conditional< - std::is_floating_point::value || std::is_floating_point::value, - double, - typename std::conditional< - std::is_signed::value || std::is_signed::value, - int64_t, - uint64_t>::type>::type; - return std::is_floating_point::value ? + using Casted = typename std::conditional_t< + std::is_floating_point_v || std::is_floating_point_v, double, + typename std::conditional_t || std::is_signed_v, std::int64_t, + std::uint64_t>>; + return std::is_floating_point_v ? std::abs(static_cast(a) -static_cast(b)) < 1e-6 : a == b; } @@ -65,11 +61,10 @@ XGBOOST_DEVICE constexpr bool CloseTo(T a, U b) { */ template XGBOOST_DEVICE inline void Softmax(Iterator start, Iterator end) { - static_assert(std::is_same().operator*())>::type - >::value, - "Values should be of type bst_float"); + static_assert( + std::is_same_v< + float, typename std::remove_reference_t().operator*())>>, + "Values should be of type bst_float"); bst_float wmax = *start; for (Iterator i = start+1; i != end; ++i) { wmax = fmaxf(*i, wmax); @@ -137,9 +132,7 @@ inline float LogSum(Iterator begin, Iterator end) { // Redefined here to workaround a VC bug that doesn't support overloading for integer // types. template -XGBOOST_DEVICE typename std::enable_if< - std::numeric_limits::is_integer, bool>::type -CheckNAN(T) { +XGBOOST_DEVICE typename std::enable_if_t::is_integer, bool> CheckNAN(T) { return false; } diff --git a/src/common/numeric.cc b/src/common/numeric.cc index f1993231187d..e1abd3ad388d 100644 --- a/src/common/numeric.cc +++ b/src/common/numeric.cc @@ -1,9 +1,9 @@ -/*! - * Copyright 2022 by XGBoost Contributors +/** + * Copyright 2022-2024, XGBoost Contributors */ #include "numeric.h" -#include // std::is_same +#include // std::is_same_v #include "xgboost/context.h" // Context #include "xgboost/host_device_vector.h" // HostDeviceVector @@ -16,7 +16,7 @@ double Reduce(Context const* ctx, HostDeviceVector const& values) { } else { auto const& h_values = values.ConstHostVector(); auto result = cpu_impl::Reduce(ctx, h_values.cbegin(), h_values.cend(), 0.0); - static_assert(std::is_same::value); + static_assert(std::is_same_v); return result; } } diff --git a/src/common/numeric.h b/src/common/numeric.h index 5b45bba8c03e..d54ba015cada 100644 --- a/src/common/numeric.h +++ b/src/common/numeric.h @@ -1,17 +1,18 @@ /** - * Copyright 2022-2023 by XGBoost contributors. + * Copyright 2022-2024, XGBoost contributors. */ #ifndef XGBOOST_COMMON_NUMERIC_H_ #define XGBOOST_COMMON_NUMERIC_H_ #include // OMPException -#include // for std::max -#include // for size_t -#include // for int32_t -#include // for iterator_traits -#include // for accumulate -#include +#include // for max +#include // for size_t +#include // for int32_t +#include // for iterator_traits +#include // for accumulate +#include // for is_same_v +#include // for vector #include "common.h" // AssertGPUSupport #include "threading_utils.h" // MemStackAllocator, DefaultMaxThreads @@ -44,8 +45,8 @@ void RunLengthEncode(Iter begin, Iter end, std::vector* p_out) { */ template void PartialSum(int32_t n_threads, InIt begin, InIt end, T init, OutIt out_it) { - static_assert(std::is_same::value_type>::value); - static_assert(std::is_same::value_type>::value); + static_assert(std::is_same_v::value_type>); + static_assert(std::is_same_v::value_type>); // The number of threads is pegged to the batch size. If the OMP block is parallelized // on anything other than the batch/block size, it should be reassigned auto n = static_cast(std::distance(begin, end)); diff --git a/src/common/observer.h b/src/common/observer.h index 33c10d53d17a..2abebc7a4470 100644 --- a/src/common/observer.h +++ b/src/common/observer.h @@ -105,9 +105,9 @@ class TrainingObserver { /*\brief Observe objects with `XGBoostParamer' type. */ template , Parameter>::value>::type* = nullptr> - void Observe(const Parameter &p, std::string name) const { + typename std::enable_if_t, Parameter>>* = + nullptr> + void Observe(const Parameter& p, std::string name) const { if (XGBOOST_EXPECT(!kObserve, true)) { return; } Json obj {toJson(p)}; diff --git a/src/common/quantile.cu b/src/common/quantile.cu index eab37f45ed30..c6c665258c8a 100644 --- a/src/common/quantile.cu +++ b/src/common/quantile.cu @@ -8,8 +8,9 @@ #include #include -#include // std::numeric_limits -#include // for partial_sum +#include // for numeric_limits +#include // for partial_sum +#include // for is_same_v #include #include "../collective/allgather.h" @@ -108,7 +109,7 @@ void PruneImpl(common::Span cuts_ptr, template void CopyTo(Span out, Span src) { CHECK_EQ(out.size(), src.size()); - static_assert(std::is_same, std::remove_cv_t>::value); + static_assert(std::is_same_v, std::remove_cv_t>); dh::safe_cuda(cudaMemcpyAsync(out.data(), src.data(), out.size_bytes(), cudaMemcpyDefault)); diff --git a/src/common/stats.cuh b/src/common/stats.cuh index 66ab3953ec87..4e38458b157f 100644 --- a/src/common/stats.cuh +++ b/src/common/stats.cuh @@ -15,7 +15,7 @@ #include // std::size_t #include // std::distance #include // std::numeric_limits -#include // std::is_floating_point,std::iterator_traits +#include // std::is_floating_point_v,std::iterator_traits #include "algorithm.cuh" // SegmentedArgMergeSort #include "cuda_context.cuh" // CUDAContext @@ -37,9 +37,9 @@ struct QuantileSegmentOp { AlphaIt alpha_it; Span d_results; - static_assert(std::is_floating_point::value_type>::value, + static_assert(std::is_floating_point_v::value_type>, "Invalid value for quantile."); - static_assert(std::is_floating_point::value_type>::value, + static_assert(std::is_floating_point_v::value_type>, "Invalid alpha."); XGBOOST_DEVICE void operator()(std::size_t seg_idx) { @@ -102,9 +102,9 @@ struct WeightedQuantileSegOp { Span d_weight_cdf; Span d_sorted_idx; Span d_results; - static_assert(std::is_floating_point::value_type>::value, + static_assert(std::is_floating_point_v::value_type>, "Invalid alpha."); - static_assert(std::is_floating_point::value_type>::value, + static_assert(std::is_floating_point_v::value_type>, "Invalid value for quantile."); XGBOOST_DEVICE void operator()(std::size_t seg_idx) { @@ -146,7 +146,7 @@ auto MakeWQSegOp(SegIt seg_it, ValIt val_it, AlphaIt alpha_it, Span * std::distance(seg_begin, seg_end) should be equal to n_segments + 1 */ template ::value>* = nullptr> + std::enable_if_t>* = nullptr> void SegmentedQuantile(Context const* ctx, AlphaIt alpha_it, SegIt seg_begin, SegIt seg_end, ValIt val_begin, ValIt val_end, HostDeviceVector* quantiles) { dh::device_vector sorted_idx; @@ -197,8 +197,8 @@ void SegmentedQuantile(Context const* ctx, double alpha, SegIt seg_begin, SegIt * @param w_begin Iterator for weight for each input element */ template ::value_type, void>::value>* = nullptr> + typename std::enable_if_t< + !std::is_same_v::value_type, void>>* = nullptr> void SegmentedWeightedQuantile(Context const* ctx, AlphaIt alpha_it, SegIt seg_beg, SegIt seg_end, ValIt val_begin, ValIt val_end, WIter w_begin, WIter w_end, HostDeviceVector* quantiles) { diff --git a/src/common/stats.h b/src/common/stats.h index 2f42a698e3d7..89321759bd12 100644 --- a/src/common/stats.h +++ b/src/common/stats.h @@ -49,7 +49,7 @@ float Quantile(Context const* ctx, double alpha, Iter const& begin, Iter const& } auto val = [&](size_t i) { return *(begin + sorted_idx[i]); }; - static_assert(std::is_same::value); + static_assert(std::is_same_v); if (alpha <= (1 / (n + 1))) { return val(0); diff --git a/src/common/transform.h b/src/common/transform.h index 3329439a5323..688bc48da21c 100644 --- a/src/common/transform.h +++ b/src/common/transform.h @@ -128,7 +128,7 @@ class Transform { } #if defined(__CUDACC__) - template ::type* = nullptr, + template * = nullptr, typename... HDV> void LaunchCUDA(Functor _func, HDV*... _vectors) const { UnpackShard(device_, _vectors...); @@ -151,9 +151,8 @@ class Transform { } #else /*! \brief Dummy function defined when compiling for CPU. */ - template ::type* = nullptr, - typename... HDV> - void LaunchCUDA(Functor _func, HDV*...) const { + template * = nullptr, typename... HDV> + void LaunchCUDA(Functor _func, HDV *...) const { // Remove unused parameter compiler warning. (void) _func; diff --git a/src/data/array_interface.h b/src/data/array_interface.h index f96ecd0c86a8..93fb55dd5626 100644 --- a/src/data/array_interface.h +++ b/src/data/array_interface.h @@ -12,7 +12,7 @@ #include // for numeric_limits #include // for map #include // for string -#include // for alignment_of, remove_pointer_t, invoke_result_t +#include // for alignment_of_v, remove_pointer_t, invoke_result_t #include // for vector #include "../common/bitfield.h" // for RBitField8 @@ -334,7 +334,7 @@ struct ToDType { }; template struct ToDType::value && sizeof(long double) == 16>> { + std::enable_if_t && sizeof(long double) == 16>> { static constexpr ArrayInterfaceHandler::Type kType = ArrayInterfaceHandler::kF16; }; // uint @@ -555,7 +555,7 @@ class ArrayInterface { } [[nodiscard]] XGBOOST_DEVICE std::size_t ElementAlignment() const { return this->DispatchCall([](auto *typed_data_ptr) { - return std::alignment_of>::value; + return std::alignment_of_v>; }); } @@ -567,9 +567,8 @@ class ArrayInterface { #if defined(XGBOOST_USE_CUDA) // No operator defined for half -> size_t using Type = std::conditional_t< - std::is_same<__half, - std::remove_cv_t>>::value && - std::is_same>::value, + std::is_same_v<__half, std::remove_cv_t>> && + std::is_same_v>, unsigned long long, T>; // NOLINT return static_cast(static_cast(p_values[offset])); #else diff --git a/src/data/simple_dmatrix.cc b/src/data/simple_dmatrix.cc index e4b82b7de59f..a9bac5062d03 100644 --- a/src/data/simple_dmatrix.cc +++ b/src/data/simple_dmatrix.cc @@ -294,16 +294,14 @@ SimpleDMatrix::SimpleDMatrix(AdapterT* adapter, float missing, int nthread, IteratorAdapter; // If AdapterT is either IteratorAdapter or FileAdapter type, use the total batch size to // determine the correct number of rows, as offset_vec may be too short - if (std::is_same::value || - std::is_same::value) { + if (std::is_same_v || std::is_same_v) { info_.num_row_ = total_batch_size; // Ensure offset_vec.size() - 1 == [number of rows] while (offset_vec.size() - 1 < total_batch_size) { offset_vec.emplace_back(offset_vec.back()); } } else { - CHECK((std::is_same::value || - std::is_same::value)) + CHECK((std::is_same_v || std::is_same_v)) << "Expecting CSCAdapter"; info_.num_row_ = offset_vec.size() - 1; } diff --git a/src/objective/lambdarank_obj.cc b/src/objective/lambdarank_obj.cc index 36495d0caa88..d99307d107d4 100644 --- a/src/objective/lambdarank_obj.cc +++ b/src/objective/lambdarank_obj.cc @@ -344,7 +344,7 @@ class LambdaRankNDCG : public LambdaRankObj { common::Span discount, bst_group_t g) { auto delta = [&](auto y_high, auto y_low, std::size_t rank_high, std::size_t rank_low, bst_group_t g) { - static_assert(std::is_floating_point::value); + static_assert(std::is_floating_point_v); return DeltaNDCG(y_high, y_low, rank_high, rank_low, inv_IDCG(g), discount); }; this->CalcLambdaForGroup(iter, g_predt, g_label, w, g_rank, g, delta, g_gpair); diff --git a/src/tree/constraints.cu b/src/tree/constraints.cu index 121d800946b7..b222402fcfce 100644 --- a/src/tree/constraints.cu +++ b/src/tree/constraints.cu @@ -1,5 +1,5 @@ /** - * Copyright 2019-2023, XGBoost contributors + * Copyright 2019-2024, XGBoost contributors */ #include #include diff --git a/src/tree/gpu_hist/evaluate_splits.cu b/src/tree/gpu_hist/evaluate_splits.cu index 0131f166fa18..387eeda91b28 100644 --- a/src/tree/gpu_hist/evaluate_splits.cu +++ b/src/tree/gpu_hist/evaluate_splits.cu @@ -41,7 +41,7 @@ XGBOOST_DEVICE float LossChangeMissing(const GradientPairInt64 &scan, template class EvaluateSplitAgent { public: - using ArgMaxT = cub::KeyValuePair; + using ArgMaxT = cub::KeyValuePair; using BlockScanT = cub::BlockScan; using MaxReduceT = cub::WarpReduce; using SumReduceT = cub::WarpReduce; diff --git a/src/tree/io_utils.h b/src/tree/io_utils.h index a0d31cc83bd3..7a8f055fe7c9 100644 --- a/src/tree/io_utils.h +++ b/src/tree/io_utils.h @@ -1,10 +1,10 @@ /** - * Copyright 2023 by XGBoost Contributors + * Copyright 2023-2024, XGBoost Contributors */ #ifndef XGBOOST_TREE_IO_UTILS_H_ #define XGBOOST_TREE_IO_UTILS_H_ #include // for string -#include // for enable_if_t, is_same, conditional_t +#include // for enable_if_t, is_same_v, conditional_t #include // for vector #include "xgboost/json.h" // for Json @@ -23,26 +23,24 @@ using IndexArrayT = std::conditional_t, I32Array // typed array, not boolean template -std::enable_if_t::value && !std::is_same::value, T> GetElem( +std::enable_if_t && !std::is_same_v, T> GetElem( std::vector const& arr, size_t i) { return arr[i]; } // typed array boolean template -std::enable_if_t::value && std::is_same::value && - std::is_same::value, - bool> +std::enable_if_t< + !std::is_same_v && std::is_same_v && std::is_same_v, bool> GetElem(std::vector const& arr, size_t i) { return arr[i] == 1; } // json array template -std::enable_if_t< - std::is_same::value, - std::conditional_t::value, int64_t, - std::conditional_t::value, bool, float>>> +std::enable_if_t, + std::conditional_t, int64_t, + std::conditional_t, bool, float>>> GetElem(std::vector const& arr, size_t i) { - if (std::is_same::value && !IsA(arr[i])) { + if (std::is_same_v && !IsA(arr[i])) { return get(arr[i]) == 1; } return get(arr[i]); diff --git a/src/tree/tree_model.cc b/src/tree/tree_model.cc index 9b28a08e594b..2a5a40b970a1 100644 --- a/src/tree/tree_model.cc +++ b/src/tree/tree_model.cc @@ -12,7 +12,7 @@ #include #include #include -#include +#include // for is_floating_point_v #include "../common/categorical.h" // for GetNodeCats #include "../common/common.h" // for EscapeU8 @@ -35,7 +35,7 @@ namespace { template std::enable_if_t, std::string> ToStr(Float value) { int32_t constexpr kFloatMaxPrecision = std::numeric_limits::max_digits10; - static_assert(std::is_floating_point::value, + static_assert(std::is_floating_point_v, "Use std::to_string instead for non-floating point values."); std::stringstream ss; ss << std::setprecision(kFloatMaxPrecision) << value; @@ -45,7 +45,7 @@ std::enable_if_t, std::string> ToStr(Float value template std::string ToStr(linalg::VectorView value, bst_target_t limit) { int32_t constexpr kFloatMaxPrecision = std::numeric_limits::max_digits10; - static_assert(std::is_floating_point::value, + static_assert(std::is_floating_point_v, "Use std::to_string instead for non-floating point values."); std::stringstream ss; ss << std::setprecision(kFloatMaxPrecision); @@ -1091,8 +1091,8 @@ void LoadModelImpl(Json const& in, TreeParam const& param, std::vector(n_nodes); nodes = std::remove_reference_t(n_nodes); - static_assert(std::is_integral(lefts, 0))>::value); - static_assert(std::is_floating_point(loss_changes, 0))>::value); + static_assert(std::is_integral_v(lefts, 0))>); + static_assert(std::is_floating_point_v(loss_changes, 0))>); // Set node for (int32_t i = 0; i < n_nodes; ++i) { diff --git a/tests/ci_build/Dockerfile.clang_tidy b/tests/ci_build/Dockerfile.clang_tidy index 941e2a852b92..2e7751a20185 100644 --- a/tests/ci_build/Dockerfile.clang_tidy +++ b/tests/ci_build/Dockerfile.clang_tidy @@ -11,20 +11,28 @@ RUN \ apt-get update && \ apt-get install -y wget git python3 python3-pip software-properties-common \ apt-transport-https ca-certificates gnupg-agent && \ - apt-get install -y llvm-15 clang-tidy-15 clang-15 libomp-15-dev && \ - apt-get install -y cmake + apt-get install -y ninja-build + +# Install clang-tidy: https://apt.llvm.org/ +RUN \ + apt-add-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-19 main" && \ + wget -O llvm-snapshot.gpg.key https://apt.llvm.org/llvm-snapshot.gpg.key && \ + apt-key add ./llvm-snapshot.gpg.key && \ + rm llvm-snapshot.gpg.key && \ + apt-get update && \ + apt-get install -y clang-tidy-19 clang-19 libomp-19-dev # Set default clang-tidy version RUN \ - update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-15 100 && \ - update-alternatives --install /usr/bin/clang clang /usr/bin/clang-15 100 + update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-19 100 && \ + update-alternatives --install /usr/bin/clang clang /usr/bin/clang-19 100 RUN \ apt-get install libgtest-dev libgmock-dev -y # Install Python packages RUN \ - pip3 install pyyaml + pip3 install cmake ENV GOSU_VERSION=1.10 diff --git a/tests/ci_build/lint_python.py b/tests/ci_build/lint_python.py index f8bbbc2848b0..d2573e6f4915 100644 --- a/tests/ci_build/lint_python.py +++ b/tests/ci_build/lint_python.py @@ -16,6 +16,8 @@ class LintersPaths: BLACK = ( # core "python-package/", + # CI + "tests/ci_build/tidy.py", # tests "tests/python/test_config.py", "tests/python/test_callback.py", @@ -119,6 +121,7 @@ class LintersPaths: "demo/guide-python/learning_to_rank.py", "demo/aft_survival/aft_survival_viz_demo.py", # CI + "tests/ci_build/tidy.py", "tests/ci_build/lint_python.py", "tests/ci_build/test_r_package.py", "tests/ci_build/test_utils.py", diff --git a/tests/ci_build/tidy.py b/tests/ci_build/tidy.py index 7116eb78e039..13bbedc0b4b5 100755 --- a/tests/ci_build/tidy.py +++ b/tests/ci_build/tidy.py @@ -1,4 +1,6 @@ #!/usr/bin/env python +from __future__ import annotations + import argparse import json import os @@ -9,20 +11,17 @@ from multiprocessing import Pool, cpu_count from time import time -import yaml +def call(args: list[str]) -> tuple[int, int, str, list[str]]: + """Subprocess run wrapper.""" + completed = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + error_msg = completed.stdout.decode("utf-8") + # `workspace` is a name used in the CI container. Normally we should keep the dir + # as `xgboost`. + matched = re.search( + "(workspace|xgboost)/.*(src|tests|include)/.*warning:", error_msg, re.MULTILINE + ) -def call(args): - '''Subprocess run wrapper.''' - completed = subprocess.run(args, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - error_msg = completed.stdout.decode('utf-8') - # `workspace` is a name used in Jenkins CI. Normally we should keep the - # dir as `xgboost`. - matched = re.search('(workspace|xgboost)/.*(src|tests|include)/.*warning:', - error_msg, - re.MULTILINE) if matched is None: return_code = 0 else: @@ -30,195 +29,203 @@ def call(args): return (completed.returncode, return_code, error_msg, args) -class ClangTidy(object): - ''' clang tidy wrapper. +class ClangTidy: + """clang tidy wrapper. Args: args: Command line arguments. cpp_lint: Run linter on C++ source code. cuda_lint: Run linter on CUDA source code. use_dmlc_gtest: Whether to use gtest bundled in dmlc-core. - ''' - def __init__(self, args): + """ + + def __init__(self, args: argparse.Namespace) -> None: self.cpp_lint = args.cpp self.cuda_lint = args.cuda self.use_dmlc_gtest: bool = args.use_dmlc_gtest self.cuda_archs = args.cuda_archs.copy() if args.cuda_archs else [] if args.tidy_version: - self.exe = 'clang-tidy-' + str(args.tidy_version) + self.exe = "clang-tidy-" + str(args.tidy_version) else: - self.exe = 'clang-tidy' + self.exe = "clang-tidy" - print('Run linter on CUDA: ', self.cuda_lint) - print('Run linter on C++:', self.cpp_lint) - print('Use dmlc gtest:', self.use_dmlc_gtest) - print('CUDA archs:', ' '.join(self.cuda_archs)) + print("Run linter on CUDA: ", self.cuda_lint) + print("Run linter on C++:", self.cpp_lint) + print("Use dmlc gtest:", self.use_dmlc_gtest) + print("CUDA archs:", " ".join(self.cuda_archs)) if not self.cpp_lint and not self.cuda_lint: - raise ValueError('Both --cpp and --cuda are set to 0.') + raise ValueError("Both --cpp and --cuda are set to 0.") self.root_path = os.path.abspath(os.path.curdir) - print('Project root:', self.root_path) - self.cdb_path = os.path.join(self.root_path, 'cdb') + print("Project root:", self.root_path) + self.cdb_path = os.path.join(self.root_path, "cdb") - def __enter__(self): + def __enter__(self) -> "ClangTidy": self.start = time() if os.path.exists(self.cdb_path): shutil.rmtree(self.cdb_path) self._generate_cdb() return self - def __exit__(self, *args): + def __exit__(self, *args: list) -> None: if os.path.exists(self.cdb_path): shutil.rmtree(self.cdb_path) self.end = time() - print('Finish running clang-tidy:', self.end - self.start) + print("Finish running clang-tidy:", self.end - self.start) - def _generate_cdb(self): - '''Run CMake to generate compilation database.''' + def _generate_cdb(self) -> None: + """Run CMake to generate compilation database.""" os.mkdir(self.cdb_path) os.chdir(self.cdb_path) - cmake_args = ['cmake', '..', '-DCMAKE_EXPORT_COMPILE_COMMANDS=ON', - '-DGOOGLE_TEST=ON'] + cmake_args = [ + "cmake", + self.root_path, + "-GNinja", # prevents cmake from using --option-files for include path. + "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", + "-DGOOGLE_TEST=ON", + "-DCMAKE_CXX_FLAGS='-Wno-clang-diagnostic-deprecated-declarations'", + ] if self.use_dmlc_gtest: - cmake_args.append('-DUSE_DMLC_GTEST=ON') + cmake_args.append("-DUSE_DMLC_GTEST=ON") else: - cmake_args.append('-DUSE_DMLC_GTEST=OFF') + cmake_args.append("-DUSE_DMLC_GTEST=OFF") if self.cuda_lint: - cmake_args.extend(['-DUSE_CUDA=ON', '-DUSE_NCCL=ON']) + cmake_args.extend(["-DUSE_CUDA=ON", "-DUSE_NCCL=ON"]) if self.cuda_archs: - arch_list = ';'.join(self.cuda_archs) - cmake_args.append(f'-DGPU_COMPUTE_VER={arch_list}') + arch_list = ";".join(self.cuda_archs) + cmake_args.append(f"-DCMAKE_CUDA_ARCHITECTURES={arch_list}") subprocess.run(cmake_args) os.chdir(self.root_path) - def convert_nvcc_command_to_clang(self, command): - '''Convert nvcc flags to corresponding clang flags.''' + def convert_nvcc_command_to_clang(self, command: str) -> str: + """Convert nvcc flags to corresponding clang flags.""" components = command.split() compiler: str = components[0] - if compiler.find('nvcc') != -1: - compiler = 'clang++' + if compiler.find("nvcc") != -1: + compiler = "clang++" components[0] = compiler # check each component in a command converted_components = [compiler] for i in range(1, len(components)): - if components[i] == '-lineinfo': + if components[i] == "-lineinfo": continue - elif components[i] == '-fuse-ld=gold': + elif components[i] == "-fuse-ld=gold": continue - elif components[i] == '-rdynamic': + elif components[i] == "-fuse-ld=lld": + continue + elif components[i].find("--default-stream") != -1: + continue + elif components[i] == "-rdynamic": continue elif components[i] == "-Xfatbin=-compress-all": continue elif components[i] == "-forward-unknown-to-host-compiler": continue - elif (components[i] == '-x' and - components[i+1] == 'cu'): + elif components[i] == "-x" and components[i + 1] == "cu": # -x cu -> -x cuda - converted_components.append('-x') - converted_components.append('cuda') - components[i+1] = '' + converted_components.append("-x") + converted_components.append("cuda") + components[i + 1] = "" continue - elif components[i].find('-Xcompiler') != -1: + elif components[i].find("-Xcompiler") != -1: continue - elif components[i].find('--expt') != -1: + elif components[i].find("--expt-") != -1: continue - elif components[i].find('-ccbin') != -1: + elif components[i].find("-ccbin") != -1: continue - elif components[i].find('--generate-code') != -1: - keyword = 'code=sm' + elif components[i].find("--generate-code") != -1: + keyword = "code=sm" pos = components[i].find(keyword) - capability = components[i][pos + len(keyword) + 1: - pos + len(keyword) + 3] + capability = components[i][ + pos + len(keyword) + 1 : pos + len(keyword) + 3 + ] if pos != -1: - converted_components.append( - '--cuda-gpu-arch=sm_' + capability) - elif components[i].find('--std=c++14') != -1: - converted_components.append('-std=c++14') - elif components[i].startswith('-isystem='): - converted_components.extend(components[i].split('=')) + converted_components.append("--cuda-gpu-arch=sm_" + capability) + elif components[i].find("--std=c++14") != -1: + converted_components.append("-std=c++14") + elif components[i].startswith("-isystem="): + converted_components.extend(components[i].split("=")) else: converted_components.append(components[i]) - converted_components.append('-isystem /usr/local/cuda/include/') + converted_components.append("-isystem /usr/local/cuda/include/") - command = '' + command = "" for c in converted_components: - command = command + ' ' + c + command = command + " " + c command = command.strip() return command - def _configure_flags(self, path, command): - src = os.path.join(self.root_path, 'src') - src = src.replace('/', '\\/') - include = os.path.join(self.root_path, 'include') - include = include.replace('/', '\\/') - - header_filter = '(' + src + '|' + include + ')' - common_args = [self.exe, - "-header-filter=" + header_filter, - '-config='+self.clang_tidy] - common_args.append(path) - common_args.append('--') + def _configure_flags(self, path: str, command: str) -> list[list[str]]: + src = os.path.join(self.root_path, "src").replace("/", "\\/") + include = os.path.join(self.root_path, "include").replace("/", "\\/") + + header_filter = "(" + src + "|" + include + ")" + common_args = [ + self.exe, + path, + "--header-filter=" + header_filter, + "--config-file=" + self.tidy_file, + ] + common_args.append("--") command = self.convert_nvcc_command_to_clang(command) - command = command.split()[1:] # remove clang/c++/g++ - if '-c' in command: - index = command.index('-c') - del command[index+1] - command.remove('-c') - if '-o' in command: - index = command.index('-o') - del command[index+1] - command.remove('-o') + command_split = command.split()[1:] # remove clang/c++/g++ + if "-c" in command_split: + index = command_split.index("-c") + del command_split[index + 1] + command_split.remove("-c") + if "-o" in command_split: + index = command_split.index("-o") + del command_split[index + 1] + command_split.remove("-o") - common_args.extend(command) + common_args.extend(command_split) # Two passes, one for device code another for host code. - if path.endswith('cu'): + if path.endswith("cu"): args = [common_args.copy(), common_args.copy()] - args[0].append('--cuda-host-only') - args[1].append('--cuda-device-only') + args[0].append("--cuda-host-only") + args[1].append("--cuda-device-only") else: args = [common_args.copy()] for a in args: - a.append('-Wno-unused-command-line-argument') + a.append("-Wno-unused-command-line-argument") return args - def _configure(self): - '''Load and configure compile_commands and clang_tidy.''' + def _configure(self) -> list[list[str]]: + """Load and configure compile_commands and clang_tidy.""" - def should_lint(path): - if not self.cpp_lint and path.endswith('.cc'): + def should_lint(path: str) -> bool: + if not self.cpp_lint and path.endswith(".cc"): return False - isxgb = path.find('dmlc-core') == -1 + isxgb = path.find("dmlc-core") == -1 isxgb = isxgb and (not path.startswith(self.cdb_path)) if isxgb: print(path) return True + return False - cdb_file = os.path.join(self.cdb_path, 'compile_commands.json') - with open(cdb_file, 'r') as fd: + cdb_file = os.path.join(self.cdb_path, "compile_commands.json") + with open(cdb_file, "r") as fd: self.compile_commands = json.load(fd) - tidy_file = os.path.join(self.root_path, '.clang-tidy') - with open(tidy_file) as fd: - self.clang_tidy = yaml.safe_load(fd) - self.clang_tidy = str(self.clang_tidy) + self.tidy_file = os.path.join(self.root_path, ".clang-tidy") all_files = [] for entry in self.compile_commands: - path = entry['file'] + path = entry["file"] if should_lint(path): - args = self._configure_flags(path, entry['command']) + args = self._configure_flags(path, entry["command"]) all_files.extend(args) return all_files - def run(self): - '''Run clang-tidy.''' + def run(self) -> bool: + """Run clang-tidy.""" all_files = self._configure() passed = True - BAR = '-'*32 + BAR = "-" * 32 with Pool(cpu_count()) as pool: results = pool.map(call, all_files) for i, (process_status, tidy_status, msg, args) in enumerate(results): @@ -226,54 +233,50 @@ def run(self): # for cub in thrust is not correct. if tidy_status == 1: passed = False - print(BAR, '\n' - 'Command args:', ' '.join(args), ', ', - 'Process return code:', process_status, ', ', - 'Tidy result code:', tidy_status, ', ', - 'Message:\n', msg, - BAR, '\n') + print( + BAR, + "\n" "Command args:", + " ".join(args), + ", ", + "Process return code:", + process_status, + ", ", + "Tidy result code:", + tidy_status, + ", ", + "Message:\n", + msg, + BAR, + "\n", + ) if not passed: - print('Errors in `thrust` namespace can be safely ignored.', - 'Please address rest of the clang-tidy warnings.') + print( + "Errors in `thrust` namespace can be safely ignored.", + "Please address rest of the clang-tidy warnings.", + ) return passed -def test_tidy(args): - '''See if clang-tidy and our regex is working correctly. There are -many subtleties we need to be careful. For instances: - - * Is the string re-directed to pipe encoded as UTF-8? or is it -bytes? +def test_tidy(args: argparse.Namespace) -> None: + """See if clang-tidy and our regex is working correctly. There are many subtleties + we need to be careful. Tests here are not thorough, at least we want to guarantee + tidy is not missing anything on the CI. - * On Jenkins there's no 'xgboost' directory, are we catching the -right keywords? - - * Should we use re.DOTALL? - - * Should we use re.MULTILINE? - - Tests here are not thorough, at least we want to guarantee tidy is - not missing anything on Jenkins. - - ''' + """ root_path = os.path.abspath(os.path.curdir) - tidy_file = os.path.join(root_path, '.clang-tidy') - test_file_path = os.path.join(root_path, - 'tests', 'ci_build', 'test_tidy.cc') - - with open(tidy_file) as fd: - tidy_config = fd.read() - tidy_config = str(tidy_config) - tidy_config = '-config='+tidy_config + tidy_file = os.path.join(root_path, ".clang-tidy") + test_file_path = os.path.join(root_path, "tests", "ci_build", "test_tidy.cc") + + tidy_config = "--config-file=" + tidy_file if not args.tidy_version: - tidy = 'clang-tidy' + tidy = "clang-tidy" else: - tidy = 'clang-tidy-' + str(args.tidy_version) - args = [tidy, tidy_config, test_file_path] - (proc_code, tidy_status, error_msg, _) = call(args) + tidy = "clang-tidy-" + str(args.tidy_version) + cmd = [tidy, tidy_config, test_file_path] + (proc_code, tidy_status, error_msg, _) = call(cmd) assert proc_code == 0 assert tidy_status == 1 - print('clang-tidy is working.') + print("clang-tidy is working.") if __name__ == "__main__": diff --git a/tests/cpp/common/test_intrusive_ptr.cc b/tests/cpp/common/test_intrusive_ptr.cc index 5b07476255a4..3b6f4083d55e 100644 --- a/tests/cpp/common/test_intrusive_ptr.cc +++ b/tests/cpp/common/test_intrusive_ptr.cc @@ -1,3 +1,6 @@ +/** + * Copyright 2020-2024, XGBoost contributors + */ #include #include @@ -12,10 +15,8 @@ class NotCopyConstructible { NotCopyConstructible &operator=(NotCopyConstructible const &that) = delete; NotCopyConstructible(NotCopyConstructible&& that) = default; }; -static_assert( - !std::is_trivially_copy_constructible::value); -static_assert( - !std::is_trivially_copy_assignable::value); +static_assert(!std::is_trivially_copy_constructible_v); +static_assert(!std::is_trivially_copy_assignable_v); class ForIntrusivePtrTest { public: diff --git a/tests/cpp/common/test_span.cc b/tests/cpp/common/test_span.cc index b29c562bc3eb..486896c24891 100644 --- a/tests/cpp/common/test_span.cc +++ b/tests/cpp/common/test_span.cc @@ -1,5 +1,5 @@ /** - * Copyright 2018-2023, XGBoost contributors + * Copyright 2018-2024, XGBoost contributors */ #include "test_span.h" @@ -174,19 +174,11 @@ TEST(Span, FromFirstLast) { } } -struct BaseClass { - virtual void operator()() {} -}; -struct DerivedClass : public BaseClass { - void operator()() override {} -}; - TEST(Span, FromOther) { - // convert constructor { - Span derived; - Span base { derived }; + Span derived; + Span base{derived}; ASSERT_EQ(base.size(), derived.size()); ASSERT_EQ(base.data(), derived.data()); } diff --git a/tests/cpp/data/test_adapter.cc b/tests/cpp/data/test_adapter.cc index f34cfceed2f3..6833dc19e46d 100644 --- a/tests/cpp/data/test_adapter.cc +++ b/tests/cpp/data/test_adapter.cc @@ -93,11 +93,11 @@ TEST(Adapter, CSCAdapterColsMoreThanRows) { // A mock for JVM data iterator. class CSRIterForTest { - std::vector data_ {1, 2, 3, 4, 5}; - std::vector().index)>::type> - feature_idx_ {0, 1, 0, 1, 1}; - std::vector().offset)>::type> - row_ptr_ {0, 2, 4, 5, 5}; + std::vector data_{1, 2, 3, 4, 5}; + std::vector().index)>> feature_idx_{ + 0, 1, 0, 1, 1}; + std::vector().offset)>> row_ptr_{ + 0, 2, 4, 5, 5}; size_t iter_ {0}; public: diff --git a/tests/cpp/data/test_sparse_page_dmatrix.cc b/tests/cpp/data/test_sparse_page_dmatrix.cc index b52d49176ef6..a557b7f622b9 100644 --- a/tests/cpp/data/test_sparse_page_dmatrix.cc +++ b/tests/cpp/data/test_sparse_page_dmatrix.cc @@ -49,7 +49,7 @@ void TestSparseDMatrixLoadFile(Context const* ctx) { 1}; Page out; for (auto const &page : m.GetBatches(ctx)) { - if (std::is_same::value) { + if (std::is_same_v) { out.Push(page); } else { out.PushCSC(page); @@ -89,7 +89,7 @@ void TestRetainPage() { for (auto it = begin; it != end; ++it) { iterators.push_back(it.Page()); pages.emplace_back(Page{}); - if (std::is_same::value) { + if (std::is_same_v) { pages.back().Push(*it); } else { pages.back().PushCSC(*it); @@ -105,7 +105,7 @@ void TestRetainPage() { // make sure it's const and the caller can not modify the content of page. for (auto &page : p_fmat->GetBatches({&ctx})) { - static_assert(std::is_const>::value); + static_assert(std::is_const_v>); } } diff --git a/tests/cpp/data/test_sparse_page_dmatrix.cu b/tests/cpp/data/test_sparse_page_dmatrix.cu index f74ca28eb85e..81940c5a6867 100644 --- a/tests/cpp/data/test_sparse_page_dmatrix.cu +++ b/tests/cpp/data/test_sparse_page_dmatrix.cu @@ -166,7 +166,7 @@ TEST(SparsePageDMatrix, RetainEllpackPage) { // make sure it's const and the caller can not modify the content of page. for (auto& page : m->GetBatches(&ctx, param)) { - static_assert(std::is_const>::value); + static_assert(std::is_const_v>); } // The above iteration clears out all references inside DMatrix. diff --git a/tests/cpp/tree/test_quantile_hist.cc b/tests/cpp/tree/test_quantile_hist.cc index 74fd6ec5ff79..518e4d0248ea 100644 --- a/tests/cpp/tree/test_quantile_hist.cc +++ b/tests/cpp/tree/test_quantile_hist.cc @@ -62,7 +62,7 @@ void TestPartitioner(bst_target_t n_targets) { auto ptr = gmat.cut.Ptrs()[split_ind + 1]; float split_value = gmat.cut.Values().at(ptr / 2); RegTree tree{n_targets, n_features}; - if constexpr (std::is_same::value) { + if constexpr (std::is_same_v) { GetSplit(&tree, split_value, &candidates); } else { GetMultiSplitForTest(&tree, split_value, &candidates); @@ -119,7 +119,7 @@ void VerifyColumnSplitPartitioner(bst_target_t n_targets, size_t n_samples, { RegTree tree{n_targets, n_features}; CommonRowPartitioner partitioner{&ctx, n_samples, base_rowid, true}; - if constexpr (std::is_same::value) { + if constexpr (std::is_same_v) { GetSplit(&tree, min_value, &candidates); } else { GetMultiSplitForTest(&tree, min_value, &candidates); @@ -132,7 +132,7 @@ void VerifyColumnSplitPartitioner(bst_target_t n_targets, size_t n_samples, { RegTree tree{n_targets, n_features}; CommonRowPartitioner partitioner{&ctx, n_samples, base_rowid, true}; - if constexpr (std::is_same::value) { + if constexpr (std::is_same_v) { GetSplit(&tree, mid_value, &candidates); } else { GetMultiSplitForTest(&tree, mid_value, &candidates); @@ -187,7 +187,7 @@ void TestColumnSplitPartitioner(bst_target_t n_targets) { auto ptr = gmat.cut.Ptrs()[split_ind + 1]; mid_value = gmat.cut.Values().at(ptr / 2); RegTree tree{n_targets, n_features}; - if constexpr (std::is_same::value) { + if constexpr (std::is_same_v) { GetSplit(&tree, mid_value, &candidates); } else { GetMultiSplitForTest(&tree, mid_value, &candidates);