diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..eed57afe --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,56 @@ +FormatStyle: file +HeaderFilterRegex: '(ethash/|lib/support/).*\.hpp' +WarningsAsErrors: '*' +Checks: > + bugprone-*, + -bugprone-easily-swappable-parameters, + -bugprone-implicit-widening-of-multiplication-result, + cert-dcl21-cpp, + cert-dcl50-cpp, + cert-dcl58-cpp, + cert-env33-c, + cert-err33-c, + cert-err34-c, + cert-err52-cpp, + cert-err60-cpp, + cert-flp30-c, + cert-mem57-cpp, + cert-msc50-cpp, + cert-msc51-cpp, + cert-oop57-cpp, + cert-oop58-cpp, + clang-analyzer-*, + cppcoreguidelines-*, + -cppcoreguidelines-avoid-c-arrays, + -cppcoreguidelines-avoid-magic-numbers, + -cppcoreguidelines-avoid-non-const-global-variables, + -cppcoreguidelines-init-variables, + -cppcoreguidelines-macro-usage, + -cppcoreguidelines-no-malloc, + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + -cppcoreguidelines-pro-bounds-constant-array-index, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-type-const-cast, + -cppcoreguidelines-pro-type-reinterpret-cast, + -cppcoreguidelines-pro-type-static-cast-downcast, + -cppcoreguidelines-pro-type-union-access, + google-global-names-in-headers, + google-runtime-int, + hicpp-exception-baseclass, + hicpp-multiway-paths-covered, + hicpp-no-assembler, + misc-*, + -misc-non-private-member-variables-in-classes, + modernize-*, + -modernize-avoid-c-arrays, + -modernize-use-auto, + -modernize-use-trailing-return-type, + performance-*, + portability-*, + readability-*, + -readability-braces-around-statements, + -readability-function-cognitive-complexity, + -readability-implicit-bool-conversion, + -readability-magic-numbers, + -readability-qualified-auto, diff --git a/circle.yml b/circle.yml index 4cb9fabd..7a91b70d 100644 --- a/circle.yml +++ b/circle.yml @@ -154,9 +154,9 @@ jobs: linux-clang-sanitizers: docker: - - image: ethereum/cpp-build-env:17-clang-12 + - image: ethereum/cpp-build-env:17-clang-13 environment: - - CMAKE_OPTIONS: -DSANITIZE=address,undefined,unsigned-integer-overflow,shift-exponent,implicit-conversion,nullability + - CMAKE_OPTIONS: -DSANITIZE=address,undefined,unsigned-integer-overflow,shift-exponent,implicit-conversion,nullability -DCMAKE_CXX_CLANG_TIDY=clang-tidy - ASAN_OPTIONS: allocator_may_return_null=1 - UBSAN_OPTIONS: halt_on_error=1 steps: diff --git a/test/benchmarks/ethash_benchmarks.cpp b/test/benchmarks/ethash_benchmarks.cpp index ee91d898..6112c1b7 100644 --- a/test/benchmarks/ethash_benchmarks.cpp +++ b/test/benchmarks/ethash_benchmarks.cpp @@ -66,7 +66,7 @@ BENCHMARK(create_context)->Arg(1)->Arg(333)->Unit(benchmark::kMillisecond); static void ethash_calculate_dataset_item_1024(benchmark::State& state) { - auto& ctx = get_ethash_epoch_context_0(); + const auto& ctx = get_ethash_epoch_context_0(); for (auto _ : state) { @@ -147,7 +147,7 @@ static void verify_managed(benchmark::State& state) for (auto _ : state) { - auto& context = ethash::get_global_epoch_context(epoch_number); + const auto& context = ethash::get_global_epoch_context(epoch_number); ethash::verify_against_boundary(context, header_hash, mix_hash, nonce, boundary); } } diff --git a/test/benchmarks/keccak_benchmarks.cpp b/test/benchmarks/keccak_benchmarks.cpp index b6bcb0f8..9f53893b 100644 --- a/test/benchmarks/keccak_benchmarks.cpp +++ b/test/benchmarks/keccak_benchmarks.cpp @@ -7,7 +7,7 @@ #include -void fake_keccakf1600(uint64_t* state) noexcept +void fake_keccakf1600(uint64_t* state) noexcept // NOLINT(readability-non-const-parameter) { // Do nothing to measure performance of the code outside the keccakf function. (void)state; diff --git a/test/benchmarks/keccak_utils.cpp b/test/benchmarks/keccak_utils.cpp index 20999070..211975c8 100644 --- a/test/benchmarks/keccak_utils.cpp +++ b/test/benchmarks/keccak_utils.cpp @@ -66,13 +66,13 @@ inline void keccak_default(uint64_t* out, const uint8_t* data, size_t size) noex static constexpr size_t block_size = (1600 - bits * 2) / 8; static constexpr size_t block_words = block_size / sizeof(uint64_t); - bool aligned = (uintptr_t)data % 8 == 0; + bool aligned = reinterpret_cast(data) % 8 == 0; uint64_t state[25] = {}; uint64_t block[block_words]; - uint64_t* p; + const uint64_t* p = nullptr; while (size >= block_size) { @@ -82,7 +82,7 @@ inline void keccak_default(uint64_t* out, const uint8_t* data, size_t size) noex p = block; } else - p = (uint64_t*)data; + p = reinterpret_cast(data); xor_into_state(state, p, block_words); fake_keccakf1600(state); data += block_size; @@ -141,7 +141,7 @@ inline void keccak_fastest(uint64_t* out, const uint8_t* data, size_t size) while (size >= sizeof(uint64_t)) { - uint64_t* p_state_word = (uint64_t*)p_state_bytes; + uint64_t* p_state_word = reinterpret_cast(p_state_bytes); *p_state_word ^= load_le(data); data += sizeof(uint64_t); size -= sizeof(uint64_t); @@ -164,7 +164,7 @@ inline void keccak_fastest(uint64_t* out, const uint8_t* data, size_t size) void fake_keccak256_default_aligned(uint64_t* out, const uint8_t* data, size_t size) noexcept { - keccak_default_aligned<256>(out, (uint64_t*)data, size / 8); + keccak_default_aligned<256>(out, reinterpret_cast(data), size / 8); } void fake_keccak256_default(uint64_t* out, const uint8_t* data, size_t size) noexcept @@ -179,5 +179,5 @@ void fake_keccak256_fastest(uint64_t* out, const uint8_t* data, size_t size) noe void fake_keccak256_fastest_word4(uint64_t out[4], const uint64_t data[4]) noexcept { - keccak_fastest(out, (const uint8_t*)data, 32); + keccak_fastest(out, reinterpret_cast(data), 32); } diff --git a/test/benchmarks/threadsync_utils.cpp b/test/benchmarks/threadsync_utils.cpp index a2aab9fa..b10ce570 100644 --- a/test/benchmarks/threadsync_utils.cpp +++ b/test/benchmarks/threadsync_utils.cpp @@ -25,7 +25,7 @@ std::shared_ptr build_fake_cache(int id) noexcept static std::shared_ptr build_sentinel() noexcept { static thread_local fake_cache sentinel; - return std::shared_ptr(&sentinel, [](fake_cache*) {}); + return {&sentinel, [](fake_cache* /*unused*/) {}}; } namespace diff --git a/test/experimental/difficulty.cpp b/test/experimental/difficulty.cpp index ab100633..eadd9b4b 100644 --- a/test/experimental/difficulty.cpp +++ b/test/experimental/difficulty.cpp @@ -24,6 +24,8 @@ inline int clz(uint32_t x) noexcept extern "C" { +// Reduce complexity of this function and enable `readability-function-cognitive-complexity` +// in clang-tidty. NO_SANITIZE("unsigned-integer-overflow") NO_SANITIZE("unsigned-shift-base") ethash_hash256 ethash_difficulty_to_boundary(const ethash_hash256* difficulty) noexcept @@ -144,7 +146,7 @@ ethash_hash256 ethash_difficulty_to_boundary(const ethash_hash256* difficulty) n } // Convert to big-endian. - ethash_hash256 boundary; + ethash_hash256 boundary = {}; for (size_t i = 0; i < num_words; ++i) boundary.word32s[i] = ethash::be::uint32(q[num_words - 1 - i]); return boundary; diff --git a/test/fakeminer/fakeminer.cpp b/test/fakeminer/fakeminer.cpp index 3144b9fc..1b56601a 100644 --- a/test/fakeminer/fakeminer.cpp +++ b/test/fakeminer/fakeminer.cpp @@ -21,7 +21,12 @@ namespace class ethash_interface { public: - virtual ~ethash_interface() noexcept = default; + ethash_interface() = default; + virtual ~ethash_interface() = default; + ethash_interface(const ethash_interface&) = delete; + ethash_interface& operator=(const ethash_interface&) = delete; + ethash_interface(ethash_interface&&) = delete; + ethash_interface& operator=(ethash_interface&&) = delete; virtual void search( const ethash::hash256& header_hash, uint64_t nonce, size_t iterations) const noexcept = 0; diff --git a/test/unittests/test_cases.hpp b/test/unittests/test_cases.hpp index b14fe08b..11fb918e 100644 --- a/test/unittests/test_cases.hpp +++ b/test/unittests/test_cases.hpp @@ -20,6 +20,7 @@ struct hash_test_case const char* final_hash_hex; }; +// NOLINTNEXTLINE(misc-definitions-in-headers) hash_test_case hash_test_cases[] = { { 0, diff --git a/test/unittests/test_ethash.cpp b/test/unittests/test_ethash.cpp index d9740b88..e896ddf7 100644 --- a/test/unittests/test_ethash.cpp +++ b/test/unittests/test_ethash.cpp @@ -774,17 +774,16 @@ TEST(ethash, small_dataset) auto solution = search_light(*context, {}, boundary, 940, 10); EXPECT_TRUE(solution.solution_found); EXPECT_EQ(solution.nonce, 948); - auto final_hash_hex = "004b92ceeb2045f9745917e4d9868a0db16b06d60ee1d8d33b9ff859053f4bb8"; + const auto final_hash_hex = "004b92ceeb2045f9745917e4d9868a0db16b06d60ee1d8d33b9ff859053f4bb8"; EXPECT_EQ(to_hex(solution.final_hash), final_hash_hex); - auto mix_hash_hex = "a5a4f053b8424f1c0a4403898d106f0488c8a819334c542ac4fabc0d2cbd7f26"; + const auto mix_hash_hex = "a5a4f053b8424f1c0a4403898d106f0488c8a819334c542ac4fabc0d2cbd7f26"; EXPECT_EQ(to_hex(solution.mix_hash), mix_hash_hex); solution = search(*context_full, {}, boundary, 940, 10); EXPECT_TRUE(solution.solution_found); EXPECT_EQ(solution.nonce, 948); - final_hash_hex = "004b92ceeb2045f9745917e4d9868a0db16b06d60ee1d8d33b9ff859053f4bb8"; EXPECT_EQ(to_hex(solution.final_hash), final_hash_hex); - mix_hash_hex = "a5a4f053b8424f1c0a4403898d106f0488c8a819334c542ac4fabc0d2cbd7f26"; + EXPECT_EQ(to_hex(solution.mix_hash), mix_hash_hex); solution = search_light(*context, {}, boundary, 483, 10); EXPECT_FALSE(solution.solution_found); diff --git a/test/unittests/test_global_context.cpp b/test/unittests/test_global_context.cpp index fde9031a..fddb589a 100644 --- a/test/unittests/test_global_context.cpp +++ b/test/unittests/test_global_context.cpp @@ -112,6 +112,7 @@ TEST(managed_multithreaded, get_epoch_context_random) static constexpr int num_threads = 4; std::vector> futures; + futures.reserve(num_threads); for (int i = 0; i < num_threads; ++i) { @@ -141,6 +142,7 @@ TEST(managed_multithreaded, get_epoch_context_full) static constexpr int num_threads = 4; std::vector> futures; + futures.reserve(num_threads); for (int i = 0; i < num_threads; ++i) { diff --git a/test/unittests/test_keccak.cpp b/test/unittests/test_keccak.cpp index ad1418a9..c4838729 100644 --- a/test/unittests/test_keccak.cpp +++ b/test/unittests/test_keccak.cpp @@ -226,10 +226,10 @@ TEST(keccak, unaligned) for (size_t offset = 1; offset < sizeof(uint64_t); ++offset) { - uint8_t *data = &buffer[offset]; - std::memcpy(data, test_text, text_length); + uint8_t* data = &buffer[offset]; + std::memcpy(data, test_text, text_length); // NOLINT(bugprone-not-null-terminated-result) - for (auto &t : test_cases) + for (auto& t : test_cases) { const auto h256 = keccak256(data, t.input_size); ASSERT_EQ(to_hex(h256), t.expected_hash256) << t.input_size;