Skip to content

Commit e307430

Browse files
authored
Enable ClangTidy alongside compilation in macOS (#1824)
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent e620979 commit e307430

File tree

18 files changed

+233
-171
lines changed

18 files changed

+233
-171
lines changed

CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ option(SOURCEMETA_CORE_CONTRIB_GOOGLEBENCHMARK "Build the GoogleBenchmark librar
2828

2929
include(Sourcemeta)
3030

31-
# Don't force downstream consumers on it
31+
# Don't force downstream consumers on this
3232
if(PROJECT_IS_TOP_LEVEL)
3333
sourcemeta_enable_simd()
34+
sourcemeta_clang_tidy_attempt_enable()
3435
endif()
3536

3637
# TODO: Turn this into a re-usable utility CMake function
@@ -116,11 +117,13 @@ if(SOURCEMETA_CORE_DOCS)
116117
endif()
117118

118119
if(PROJECT_IS_TOP_LEVEL)
120+
# TODO: Try once more to enable this per target,
121+
# so, we don't need to manually disable it here
122+
sourcemeta_clang_tidy_attempt_disable()
119123
sourcemeta_target_clang_format(SOURCES
120124
src/*.h src/*.cc
121125
benchmark/*.h benchmark/*.cc
122126
test/*.h test/*.cc)
123-
sourcemeta_target_clang_tidy(SOURCES src/*.cc)
124127
endif()
125128

126129
# Testing

Makefile

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ compile: .always
2525
$(CMAKE) --install ./build --prefix ./build/dist --config $(PRESET) --verbose \
2626
--component sourcemeta_core_dev
2727

28-
lint: .always
29-
$(CMAKE) --build ./build --config $(PRESET) --target clang_tidy
30-
3128
test: .always
3229
$(CMAKE) -E env UBSAN_OPTIONS=print_stacktrace=1 \
3330
$(CTEST) --test-dir ./build --build-config $(PRESET) \

cmake/Sourcemeta.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ include("${SOURCEMETA_UTILITIES_DIRECTORY}/commands/copy-file.cmake")
1010
include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/library.cmake")
1111
include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/executable.cmake")
1212
include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/clang-format.cmake")
13-
include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/clang-tidy.cmake")
1413
include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/shellcheck.cmake")
1514
include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/doxygen.cmake")
1615
include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/googletest.cmake")
1716
include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/googlebenchmark.cmake")
17+
include("${SOURCEMETA_UTILITIES_DIRECTORY}/clang-tidy.cmake")
1818

1919
# To let downstream projects directly include this file
2020
if(NOT PROJECT_IS_TOP_LEVEL)

cmake/common/targets/clang-tidy.cmake renamed to cmake/common/clang-tidy.cmake

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
function(sourcemeta_target_clang_tidy_attempt_install)
1+
function(sourcemeta_clang_tidy_attempt_install)
22
cmake_parse_arguments(SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL "" "OUTPUT_DIRECTORY" "" ${ARGN})
33
if(NOT SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY)
44
message(FATAL_ERROR "You must pass the output directory in the OUTPUT_DIRECTORY option")
@@ -76,9 +76,17 @@ function(sourcemeta_target_clang_tidy_attempt_install)
7676
message(STATUS "Installed `clang-tidy` pre-built binary to ${CLANG_TIDY_BINARY_OUTPUT}")
7777
endfunction()
7878

79-
function(sourcemeta_target_clang_tidy)
80-
cmake_parse_arguments(SOURCEMETA_TARGET_CLANG_TIDY "REQUIRED" "" "SOURCES" ${ARGN})
81-
sourcemeta_target_clang_tidy_attempt_install(OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
79+
function(sourcemeta_clang_tidy_attempt_enable)
80+
cmake_parse_arguments(SOURCEMETA_TARGET_CLANG_TIDY "REQUIRED" "" "" ${ARGN})
81+
82+
if(SOURCEMETA_COMPILER_LLVM)
83+
message(STATUS "Enabling ClangTidy alongside compilation")
84+
else()
85+
message(STATUS "Ignoring ClangTidy setup on a compiler other than LLVM")
86+
return()
87+
endif()
88+
89+
sourcemeta_clang_tidy_attempt_install(OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
8290

8391
if(SOURCEMETA_TARGET_CLANG_TIDY_REQUIRED)
8492
find_program(CLANG_TIDY_BIN NAMES clang-tidy NO_DEFAULT_PATH
@@ -94,37 +102,24 @@ function(sourcemeta_target_clang_tidy)
94102
endif()
95103
endif()
96104

97-
98-
# This covers the empty list too
99-
if(NOT SOURCEMETA_TARGET_CLANG_TIDY_SOURCES)
100-
message(FATAL_ERROR "You must pass file globs to analyze in the SOURCES option")
101-
endif()
102-
file(GLOB_RECURSE SOURCEMETA_TARGET_CLANG_TIDY_FILES
103-
${SOURCEMETA_TARGET_CLANG_TIDY_SOURCES})
104-
105105
set(CLANG_TIDY_CONFIG "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/clang-tidy.config")
106106

107-
if(CMAKE_SYSTEM_NAME STREQUAL "MSYS")
108-
# Because `clang-tidy` is typically a Windows `.exe`, transform the path accordingly
109-
execute_process(COMMAND cygpath -w "${CLANG_TIDY_CONFIG}"
110-
OUTPUT_VARIABLE CLANG_TIDY_CONFIG OUTPUT_STRIP_TRAILING_WHITESPACE)
111-
endif()
112-
113-
if(CLANG_TIDY_BIN)
114-
add_custom_target(clang_tidy
115-
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
116-
VERBATIM
117-
COMMAND "${CLANG_TIDY_BIN}" -p "${PROJECT_BINARY_DIR}"
118-
--config-file "${CLANG_TIDY_CONFIG}"
119-
${SOURCEMETA_TARGET_CLANG_TIDY_FILES}
120-
COMMENT "Analyzing sources using ClangTidy")
121-
else()
122-
add_custom_target(clang_tidy
123-
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
124-
VERBATIM
125-
COMMAND "${CMAKE_COMMAND}" -E echo "Could not locate ClangTidy"
126-
COMMAND "${CMAKE_COMMAND}" -E false)
107+
# TODO: Support other platforms too, like Linux
108+
if(APPLE)
109+
execute_process(COMMAND xcrun --show-sdk-path
110+
OUTPUT_VARIABLE MACOSX_SDK_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
111+
execute_process(COMMAND "${CMAKE_CXX_COMPILER}" -print-resource-dir
112+
OUTPUT_VARIABLE MACOSX_RESOURCE_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
113+
set(CMAKE_CXX_CLANG_TIDY
114+
"${CLANG_TIDY_BIN};--config-file=${CLANG_TIDY_CONFIG};-header-filter=${PROJECT_SOURCE_DIR}/src/*"
115+
"--extra-arg=-std=c++${CMAKE_CXX_STANDARD}"
116+
"--extra-arg=-isysroot"
117+
"--extra-arg=${MACOSX_SDK_PATH}"
118+
"--extra-arg=-resource-dir=${MACOSX_RESOURCE_PATH}"
119+
PARENT_SCOPE)
127120
endif()
121+
endfunction()
128122

129-
set_target_properties(clang_tidy PROPERTIES FOLDER "Linting")
123+
function(sourcemeta_clang_tidy_attempt_disable)
124+
unset(CMAKE_CXX_CLANG_TIDY PARENT_SCOPE)
130125
endfunction()

cmake/common/clang-tidy.config

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
# See https://clang.llvm.org/extra/clang-tidy/index.html
3+
# First disable all default checks (with -*)
4+
Checks: '-*,
5+
modernize-*'
6+
# TODO(bavulapati): iterate through the rules and enable them incrementally inorder to send smaller PRs
7+
# bugprone-*,-bugprone-branch-clone,-bugprone-easily-swappable-parameters,-bugprone-empty-catch,
8+
# clang-analyzer-*,
9+
# clang-diagnostic-*,
10+
# modernize-*,
11+
# concurrency-*,
12+
# cppcoreguidelines-*,-cppcoreguidelines-rvalue-reference-param-not-moved,
13+
# performance-*,-performance-enum-size,
14+
# portability-*,
15+
# objc-*,
16+
# misc-*,-misc-no-recursion,-misc-unused-parameters,-misc-const-correctness'
17+
WarningsAsErrors: '*'
18+
FormatStyle: none
19+
UseColor: true

cmake/common/targets/clang-tidy.config

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/core/json/include/sourcemeta/core/json_array.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,31 +56,39 @@ template <typename Value> class JSONArray {
5656
/// Get a mutable end iterator on the array
5757
auto end() noexcept -> iterator { return this->data.end(); }
5858
/// Get a constant begin iterator on the array
59-
auto begin() const noexcept -> const_iterator { return this->data.begin(); }
59+
[[nodiscard]] auto begin() const noexcept -> const_iterator {
60+
return this->data.begin();
61+
}
6062
/// Get a constant end iterator on the array
61-
auto end() const noexcept -> const_iterator { return this->data.end(); }
63+
[[nodiscard]] auto end() const noexcept -> const_iterator {
64+
return this->data.end();
65+
}
6266
/// Get a constant begin iterator on the array
63-
auto cbegin() const noexcept -> const_iterator { return this->data.cbegin(); }
67+
[[nodiscard]] auto cbegin() const noexcept -> const_iterator {
68+
return this->data.cbegin();
69+
}
6470
/// Get a constant end iterator on the array
65-
auto cend() const noexcept -> const_iterator { return this->data.cend(); }
71+
[[nodiscard]] auto cend() const noexcept -> const_iterator {
72+
return this->data.cend();
73+
}
6674
/// Get a mutable reverse begin iterator on the array
6775
auto rbegin() noexcept -> reverse_iterator { return this->data.rbegin(); }
6876
/// Get a mutable reverse end iterator on the array
6977
auto rend() noexcept -> reverse_iterator { return this->data.rend(); }
7078
/// Get a constant reverse begin iterator on the array
71-
auto rbegin() const noexcept -> const_reverse_iterator {
79+
[[nodiscard]] auto rbegin() const noexcept -> const_reverse_iterator {
7280
return this->data.rbegin();
7381
}
7482
/// Get a constant reverse end iterator on the array
75-
auto rend() const noexcept -> const_reverse_iterator {
83+
[[nodiscard]] auto rend() const noexcept -> const_reverse_iterator {
7684
return this->data.rend();
7785
}
7886
/// Get a constant reverse begin iterator on the array
79-
auto crbegin() const noexcept -> const_reverse_iterator {
87+
[[nodiscard]] auto crbegin() const noexcept -> const_reverse_iterator {
8088
return this->data.crbegin();
8189
}
8290
/// Get a constant reverse end iterator on the array
83-
auto crend() const noexcept -> const_reverse_iterator {
91+
[[nodiscard]] auto crend() const noexcept -> const_reverse_iterator {
8492
return this->data.crend();
8593
}
8694

src/core/json/include/sourcemeta/core/json_hash.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ template <typename T> struct HashJSON {
1414
return value.fast_hash();
1515
}
1616

17+
[[nodiscard]]
1718
inline auto is_perfect(const hash_type) const noexcept -> bool {
1819
return false;
1920
}
@@ -45,6 +46,7 @@ template <typename T> struct PropertyHashJSON {
4546
}
4647
};
4748

49+
[[nodiscard]]
4850
inline auto perfect(const T &value, const std::size_t size) const noexcept
4951
-> hash_type {
5052
hash_type result;
@@ -134,6 +136,7 @@ template <typename T> struct PropertyHashJSON {
134136
}
135137
}
136138

139+
[[nodiscard]]
137140
inline auto is_perfect(const hash_type &hash) const noexcept -> bool {
138141
// If there is anything written past the first byte,
139142
// then it is a perfect hash

src/core/json/include/sourcemeta/core/json_object.h

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,21 @@ template <typename Key, typename Value, typename Hash> class FlatMap {
4545
}
4646
}
4747

48-
auto begin() const noexcept -> const_iterator { return this->data.begin(); }
49-
auto end() const noexcept -> const_iterator { return this->data.end(); }
50-
auto cbegin() const noexcept -> const_iterator { return this->data.cbegin(); }
51-
auto cend() const noexcept -> const_iterator { return this->data.cend(); }
48+
[[nodiscard]] auto begin() const noexcept -> const_iterator {
49+
return this->data.begin();
50+
}
51+
[[nodiscard]] auto end() const noexcept -> const_iterator {
52+
return this->data.end();
53+
}
54+
[[nodiscard]] auto cbegin() const noexcept -> const_iterator {
55+
return this->data.cbegin();
56+
}
57+
[[nodiscard]] auto cend() const noexcept -> const_iterator {
58+
return this->data.cend();
59+
}
5260

53-
inline auto hash(const key_type &key) const noexcept -> hash_type {
61+
[[nodiscard]] inline auto hash(const key_type &key) const noexcept
62+
-> hash_type {
5463
return this->hasher(key);
5564
}
5665

@@ -134,7 +143,8 @@ template <typename Key, typename Value, typename Hash> class FlatMap {
134143
}
135144

136145
// As a performance optimisation if the hash is known
137-
inline auto find(const key_type &key, const hash_type key_hash) const
146+
[[nodiscard]] inline auto find(const key_type &key,
147+
const hash_type key_hash) const
138148
-> const_iterator {
139149
assert(this->hash(key) == key_hash);
140150

@@ -161,7 +171,8 @@ template <typename Key, typename Value, typename Hash> class FlatMap {
161171
return this->cend();
162172
}
163173

164-
inline auto try_at(const key_type &key, const hash_type key_hash) const
174+
[[nodiscard]] inline auto try_at(const key_type &key,
175+
const hash_type key_hash) const
165176
-> const mapped_type * {
166177
assert(this->hash(key) == key_hash);
167178

@@ -185,7 +196,8 @@ template <typename Key, typename Value, typename Hash> class FlatMap {
185196
}
186197

187198
// As a performance optimisation if the hash is known
188-
auto contains(const key_type &key, const hash_type key_hash) const -> bool {
199+
[[nodiscard]] auto contains(const key_type &key,
200+
const hash_type key_hash) const -> bool {
189201
assert(this->hash(key) == key_hash);
190202

191203
// Move the perfect hash condition out of the loop for extra performance
@@ -208,7 +220,8 @@ template <typename Key, typename Value, typename Hash> class FlatMap {
208220

209221
// As a performance optimisation if the hash is known
210222

211-
inline auto at(const key_type &key, const hash_type key_hash) const
223+
[[nodiscard]] inline auto at(const key_type &key,
224+
const hash_type key_hash) const
212225
-> const mapped_type & {
213226
assert(this->hash(key) == key_hash);
214227

@@ -262,7 +275,8 @@ template <typename Key, typename Value, typename Hash> class FlatMap {
262275
#endif
263276
}
264277

265-
inline auto at(const size_type index) const noexcept -> const Entry & {
278+
[[nodiscard]] inline auto at(const size_type index) const noexcept
279+
-> const Entry & {
266280
return this->data[index];
267281
}
268282

@@ -317,9 +331,13 @@ template <typename Key, typename Value, typename Hash> class FlatMap {
317331
return this->erase(key, this->hash(key));
318332
}
319333

320-
inline auto size() const noexcept -> size_type { return this->data.size(); }
334+
[[nodiscard]] inline auto size() const noexcept -> size_type {
335+
return this->data.size();
336+
}
321337

322-
inline auto empty() const noexcept -> bool { return this->data.empty(); }
338+
[[nodiscard]] inline auto empty() const noexcept -> bool {
339+
return this->data.empty();
340+
}
323341

324342
inline auto clear() noexcept -> void { this->data.clear(); }
325343

@@ -418,44 +436,48 @@ template <typename Key, typename Value, typename Hash> class JSONObject {
418436
using const_pointer = typename Container::const_pointer;
419437
using const_iterator = typename Container::const_iterator;
420438

421-
inline auto begin() const noexcept -> const_iterator {
439+
[[nodiscard]] inline auto begin() const noexcept -> const_iterator {
422440
return this->data.begin();
423441
}
424442
/// Get a constant end iterator on the object
425-
inline auto end() const noexcept -> const_iterator {
443+
[[nodiscard]] inline auto end() const noexcept -> const_iterator {
426444
return this->data.end();
427445
}
428446
/// Get a constant begin iterator on the object
429-
inline auto cbegin() const noexcept -> const_iterator {
447+
[[nodiscard]] inline auto cbegin() const noexcept -> const_iterator {
430448
return this->data.cbegin();
431449
}
432450
/// Get a constant end iterator on the object
433-
inline auto cend() const noexcept -> const_iterator {
451+
[[nodiscard]] inline auto cend() const noexcept -> const_iterator {
434452
return this->data.cend();
435453
}
436454

437455
/// Attempt to find an entry by key
438-
inline auto find(const Key &key) const -> const_iterator {
456+
[[nodiscard]] inline auto find(const Key &key) const -> const_iterator {
439457
return this->data.find(key, this->data.hash(key));
440458
}
441459

442460
/// Check if an entry with the given key exists
443-
inline auto defines(const Key &key,
444-
const typename Container::hash_type hash) const -> bool {
461+
[[nodiscard]] inline auto
462+
defines(const Key &key, const typename Container::hash_type hash) const
463+
-> bool {
445464
return this->data.contains(key, hash);
446465
}
447466

448467
/// Check the size of the object
449-
inline auto size() const -> std::size_t { return this->data.size(); }
468+
[[nodiscard]] inline auto size() const -> std::size_t {
469+
return this->data.size();
470+
}
450471

451472
/// Access an object entry by its underlying positional index
452-
inline auto at(const size_type index) const noexcept -> const
473+
[[nodiscard]] inline auto at(const size_type index) const noexcept -> const
453474
typename Container::Entry & {
454475
return this->data.at(index);
455476
}
456477

457478
// Hash an object property
458-
inline auto hash(const Key &property) const -> typename Container::hash_type {
479+
[[nodiscard]] inline auto hash(const Key &property) const ->
480+
typename Container::hash_type {
459481
return this->data.hasher(property);
460482
}
461483

0 commit comments

Comments
 (0)