From 101cdea022167a6b5c7aefa2a1faa5e47d9168b4 Mon Sep 17 00:00:00 2001
From: Eidolon <furyhunter600@gmail.com>
Date: Sat, 5 Nov 2022 18:31:06 -0500
Subject: [PATCH] cmake: Add optional clang-tidy integration

clang-tidy performs static analysis over the compilation unit,
producing more comprehensive compile warnings than are normally
generated by the compiler. For example, it will trace branches in a
function to find the exact conditions in which a null dereference
can occur.

Note that this produces an absurd amount of warnings for our existing
C code, and significantly slows compile times. It is pretty effective
at its job though. I think it would be good to turn on by default for
upcoming C++ code.
---
 CMakeLists.txt                         |  3 +++
 cmake/Modules/clang-tidy-default.cmake | 21 +++++++++++++++++++++
 src/CMakeLists.txt                     | 10 ++++++++++
 3 files changed, 34 insertions(+)
 create mode 100644 cmake/Modules/clang-tidy-default.cmake

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 915912af5..7fc050ea0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -53,6 +53,9 @@ else()
 	set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT OFF)
 endif()
 
+# Clang tidy options will be ignored if CMAKE_<LANG>_CLANG_TIDY are set.
+option(SRB2_CONFIG_ENABLE_CLANG_TIDY_C "Enable default clang-tidy check configuration for C" OFF)
+option(SRB2_CONFIG_ENABLE_CLANG_TIDY_CXX "Enable default clang-tidy check configuration for C++" OFF)
 option(
 	SRB2_CONFIG_SYSTEM_LIBRARIES
 	"Link dependencies using CMake's find_package and do not use internal builds"
diff --git a/cmake/Modules/clang-tidy-default.cmake b/cmake/Modules/clang-tidy-default.cmake
new file mode 100644
index 000000000..2be3af10d
--- /dev/null
+++ b/cmake/Modules/clang-tidy-default.cmake
@@ -0,0 +1,21 @@
+find_program(CLANG_TIDY clang-tidy)
+
+# Note: Apple Clang does not ship with clang tools. If you want clang-tidy on
+# macOS, it's best to install the Homebrew llvm bottle and set CLANG_TIDY
+# in your build directory. The llvm package is keg-only, so it will not
+# collide with Apple Clang.
+
+function(target_set_default_clang_tidy target lang checks)
+    if("${CLANG_TIDY}" STREQUAL "CLANG_TIDY-NOTFOUND")
+        return()
+    endif()
+
+    get_target_property(c_clang_tidy_prop SRB2SDL2 C_CLANG_TIDY)
+    if(NOT ("${c_clang_tidy_prop}" STREQUAL "c_clang_tidy_prop-NOTFOUND"))
+        return()
+    endif()
+
+    set_target_properties("${target}" PROPERTIES
+	    ${lang}_CLANG_TIDY "${CLANG_TIDY};-checks=${checks}"
+    )
+endfunction()
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2f4467a32..18c16eeb4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,3 +1,5 @@
+include(clang-tidy-default)
+
 add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32)
 
 if("${CMAKE_COMPILER_IS_GNUCC}" AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows" AND NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}" AND NOT "${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}")
@@ -329,3 +331,11 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL Windows AND NOT "${SRB2_CONFIG_INTERNAL_LIBRA
 		COMMENT "Copying runtime DLLs"
 	)
 endif()
+
+# Setup clang-tidy
+if(SRB2_CONFIG_ENABLE_CLANG_TIDY_C)
+	target_set_default_clang_tidy(SRB2SDL2 C "-*,clang-analyzer-*,-clang-analyzer-cplusplus-*")
+endif()
+if(SRB2_CONFIG_ENABLE_CLANG_TIDY_CXX)
+	target_set_default_clang_tidy(SRB2SDL2 CXX "-*,clang-analyzer-*,modernize-*")
+endif()
-- 
GitLab