Skip to content
68 changes: 58 additions & 10 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,12 +1,60 @@
Checks: "-*,
bugprone*,
-bugprone-easily-swappable-parameters,
-bugprone-macro-parentheses,
clang-analyzer*,
readability*,
-readability-magic-numbers,
-readability-identifier-length"
Checks: '
-*,
bugprone-argument-comment,
bugprone-sizeof-*,
bugprone-use-after-move,
clang-diagnostic-*,
-clang-diagnostic-nrvo,
-clang-diagnostic-missing-designated-field-initializers,
cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-special-member-functions,
google-build-using-namespace,
misc-definitions-in-headers,
modernize-use-emplace,
modernize-use-using,
performance-faster-string-find,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-algorithm,
performance-inefficient-string-concatenation,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-move-constructor-init,
performance-no-automatic-move,
performance-no-int-to-ptr,
performance-noexcept-move-constructor,
performance-trivially-destructible,
performance-type-promotion-in-math-fn,
performance-unnecessary-copy-initialization,
performance-unnecessary-value-param,
readability-operators-representation,
readability-redundant-string-init,
readability-braces-around-statements,
'

WarningsAsErrors: '
bugprone-use-after-move,
'

CheckOptions:
- key: readability-implicit-bool-conversion.AllowIntegerConditions
value: '1'
- key: bugprone-easily-swappable-parameters.MinimumLength
value: 4
- key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor
value: true
- key: cppcoreguidelines-special-member-functions.AllowImplicitlyDeletedCopyOrMove
value: 1
- key: modernize-use-using.IgnoreExternC
value: true
- key: performance-move-const-arg.CheckTriviallyCopyableMove
value: false
- key: performance-unnecessary-value-param.AllowedTypes
value: '[Pp]ointer$;[Pp]tr$;[Rr]ef(erence)?$'
- key: performance-unnecessary-copy-initialization.AllowedTypes
value: '[Pp]ointer$;[Pp]tr$;[Rr]ef(erence)?$'
- key: readability-operators-representation.BinaryOperators
value: '&&;&=;&;|;~;!;!=;||;|=;^;^='
- key: readability-redundant-string-init.StringNames
value: '::std::basic_string'
- key: readability-named-parameter.InsertPlainNamesInForwardDecls
value: true
...
7 changes: 7 additions & 0 deletions .github/scripts/build-cpp-runtime-bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ set -e # Exit on error
# Source environment setup (for compiler)
source /etc/bashrc || true

# Temporary: pip-install clang-tidy 17 to test whether the system clang-tidy
# version is the cause of the template crash. Pin setuptools <81 because the
# wheel's wrapper imports pkg_resources, which setuptools 81 removed.
# Remove once resolved.
pip install 'setuptools<81' clang-tidy==17.0.1

# Source MKL environment (required for IVF)
if [ -f /opt/intel/oneapi/setvars.sh ]; then
source /opt/intel/oneapi/setvars.sh --include-intel-llvm 2>/dev/null || true
Expand All @@ -41,6 +47,7 @@ CMAKE_ARGS=(
"-DCMAKE_INSTALL_LIBDIR=lib"
"-DSVS_RUNTIME_ENABLE_LVQ_LEANVEC=${ENABLE_LVQ_LEANVEC:-ON}"
"-DSVS_RUNTIME_ENABLE_IVF=ON"
"-DSVS_EXPERIMENTAL_CLANG_TIDY=ON"
)

if [ -n "$SVS_URL" ]; then
Expand Down
30 changes: 30 additions & 0 deletions bindings/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,23 @@ target_compile_options(${TARGET_NAME} PRIVATE
-fvisibility=hidden
)

# Optional clang-tidy integration. Reuses the top-level repo's
# cmake/clang-tidy.cmake module so the runtime build runs the same
# .clang-tidy config as the rest of the library.
option(SVS_EXPERIMENTAL_CLANG_TIDY
"Run the clang-tidy static analyzer on the cpp runtime bindings."
OFF
)
if(SVS_EXPERIMENTAL_CLANG_TIDY)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../cmake")
include(clang-tidy)
if(CLANG_TIDY_COMMAND)
set_target_properties(${TARGET_NAME}
PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}"
)
endif()
endif()

if(UNIX AND NOT APPLE)
# Don't export 3rd-party symbols from the lib
target_link_options(${TARGET_NAME} PRIVATE "SHELL:-Wl,--exclude-libs,ALL")
Expand Down Expand Up @@ -142,6 +159,19 @@ if (SVS_RUNTIME_ENABLE_LVQ_LEANVEC)
FetchContent_MakeAvailable(svs)
list(APPEND CMAKE_PREFIX_PATH "${svs_SOURCE_DIR}")
find_package(svs REQUIRED)

# Strip svs::svs_compile_options gcc-only flags for clang-tidy
if(SVS_EXPERIMENTAL_CLANG_TIDY AND TARGET svs::svs_compile_options)
get_target_property(_svs_co_opts svs::svs_compile_options INTERFACE_COMPILE_OPTIONS)
if(_svs_co_opts)
list(FILTER _svs_co_opts EXCLUDE REGEX "^-fconcepts-diagnostics-depth")
list(FILTER _svs_co_opts EXCLUDE REGEX "^-ftemplate-backtrace-limit")
set_property(TARGET svs::svs_compile_options
PROPERTY INTERFACE_COMPILE_OPTIONS "${_svs_co_opts}"
)
endif()
endif()

target_link_libraries(${TARGET_NAME} PRIVATE
svs::svs
svs::svs_compile_options
Expand Down
36 changes: 32 additions & 4 deletions cmake/clang-tidy.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,46 @@
#####

if(SVS_EXPERIMENTAL_CLANG_TIDY)
find_program(CLANG_TIDY_EXE NAMES clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy)
find_program(CLANG_TIDY_EXE
NAMES
clang-tidy-17 clang-tidy-18 clang-tidy
)

if(NOT CLANG_TIDY_EXE)
message(WARNING "SVS_EXPERIMENTAL_CLANG_TIDY is ON but clang-tidy is not found!")
set(CLANG_TIDY_COMMAND "" CACHE STRING "" FORCE)
else()
# Walk up to find .clang-tidy when built standalone from bindings/cpp.
if(EXISTS "${CMAKE_SOURCE_DIR}/.clang-tidy")
set(SVS_CLANG_TIDY_CONFIG "${CMAKE_SOURCE_DIR}/.clang-tidy")
set(SVS_CLANG_TIDY_HEADER_FILTER "${CMAKE_SOURCE_DIR}/include/svs/.*")
elseif(EXISTS "${CMAKE_SOURCE_DIR}/../../.clang-tidy")
set(SVS_CLANG_TIDY_CONFIG "${CMAKE_SOURCE_DIR}/../../.clang-tidy")
set(SVS_CLANG_TIDY_HEADER_FILTER "${CMAKE_SOURCE_DIR}/include/svs/.*")
else()
message(FATAL_ERROR "SVS_EXPERIMENTAL_CLANG_TIDY is ON but no .clang-tidy was found")
endif()

set(CLANG_TIDY_COMMAND
"${CLANG_TIDY_EXE}"
"--format-style=file"
"--config-file=${CMAKE_SOURCE_DIR}/.clang-tidy"
"--header-filter=${CMAKE_SOURCE_DIR}/include/svs/*"
"--config-file=${SVS_CLANG_TIDY_CONFIG}"
"--header-filter=${SVS_CLANG_TIDY_HEADER_FILTER}"
"--warnings-as-errors=clang-diagnostic-*,bugprone-use-after-move"
# Suppress noise from args (e.g. --gcc-toolchain) that affect link-time
# paths but are unused during clang-tidy's parse-only invocation.
"--extra-arg=-Wno-unused-command-line-argument"
)
message("Clang tidy command: ${CLANG_TIDY_COMMAND}")

# Point clang-tidy at gcc's toolchain so it can find libstdc++ headers.
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
get_filename_component(_svs_gcc_bin_dir "${CMAKE_CXX_COMPILER}" DIRECTORY)
get_filename_component(_svs_gcc_toolchain "${_svs_gcc_bin_dir}" DIRECTORY)
list(APPEND CLANG_TIDY_COMMAND
"--extra-arg=--gcc-toolchain=${_svs_gcc_toolchain}"
)
endif()

message(STATUS "Clang tidy command: ${CLANG_TIDY_COMMAND}")
endif()
endif()
19 changes: 12 additions & 7 deletions cmake/options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,19 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "In
endif()
endif()

# Provide better diagnostics for broken templates.
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(
svs_compile_options
INTERFACE
-fconcepts-diagnostics-depth=10
-ftemplate-backtrace-limit=0
)
# Provide better diagnostics for broken templates.
# These flags are gcc-only; clang-tidy uses the clang frontend to parse the
# compile command and would error with "unknown argument", so skip them when
# clang-tidy is enabled.
if (NOT SVS_EXPERIMENTAL_CLANG_TIDY)
target_compile_options(
svs_compile_options
INTERFACE
-fconcepts-diagnostics-depth=10
-ftemplate-backtrace-limit=0
)
endif()

if (CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 12.0)
# GCC-12 throws errors in its own intrinsics library with uninitialized variables.
Expand Down
Loading