Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom clang tidy plugin #30886

Merged
merged 28 commits into from
Jun 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
720823a
Don't use CMake option command for non-booleans
jbytheway May 24, 2019
b0a8a50
Initial version of a no-long check
jbytheway May 24, 2019
53d0233
Enable cata checks in clang-tidy
jbytheway May 24, 2019
3b73b6f
Try to support building and running on Travis
jbytheway May 26, 2019
8f5cb00
build.sh: Replace a 3 with $num_jobs
jbytheway May 26, 2019
91946b2
Configure Travis to run clang-tidy plugin
jbytheway May 26, 2019
5c72b74
Add tests for NoLongCheck
jbytheway May 27, 2019
41f4086
Use CMake option rather than env var
jbytheway May 28, 2019
fa8f41f
Add some docs regarding how to use the plugin
jbytheway May 28, 2019
8c9108e
Also catch unsigned long in cata-no-long check
jbytheway Jun 8, 2019
85a1907
More tests for cata-no-long check
jbytheway Jun 8, 2019
85d7b9f
Check function return types are not long
jbytheway Jun 8, 2019
65ac6f8
Tweak function tests for cata-no-long
jbytheway Jun 8, 2019
6b8be84
Check for static_cast<long> in cata-no-long
jbytheway Jun 8, 2019
d688b0d
cata-no-long: Handle qualified and reference types
jbytheway Jun 8, 2019
adc3f21
Astyle clang-tidy plugin code
jbytheway Jun 9, 2019
30287ab
Enforce astyle on clang-tidy plugin code
jbytheway Jun 9, 2019
9eb11d1
Avoid some false positives in cata-no-long check
jbytheway Jun 10, 2019
dce24e5
NoLongCheck now tests for long-specific macros
jbytheway Jun 10, 2019
10c463b
Avoid false-positives on return values
jbytheway Jun 11, 2019
037c250
Avoid false positives on deduced return types
jbytheway Jun 11, 2019
a30b6fe
Change naming convention in NoLongCheck test
jbytheway Jun 12, 2019
8fe1cda
Avoid false-positives on deduced variable types
jbytheway Jun 12, 2019
cef5be2
cata-no-long: Avoid false-positives on auto&
jbytheway Jun 13, 2019
9cce062
Avoid false positive on autogenerated code
jbytheway Jun 13, 2019
63e5e1e
Avoid false-positives on templated return types
jbytheway Jun 14, 2019
ac2ec51
Mention size_t as an alternative to unsigned int
jbytheway Jun 19, 2019
2d801ea
Fix a couple of casts to unsigned long
jbytheway Jun 19, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# fix their errors or recategorise them as checks we don't care about.
Checks: "\
bugprone-*,\
cata-*,\
cert-*,\
-cert-err58-cpp,\
clang-diagnostic-*,\
Expand Down
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@ jobs:
osx_image: xcode10.1
compiler: clang

- env: CLANG=clang++-8 TILES=1 SOUND=1 CXXFLAGS=-Wno-unused-command-line-argument CMAKE=1 CATA_CLANG_TIDY=clang-tidy-8
- env: CLANG=clang++-8 TILES=1 SOUND=1 CXXFLAGS=-Wno-unused-command-line-argument CMAKE=1 CATA_CLANG_TIDY=plugin
name: "Clang-tidy CMake build with Tiles and Sound"
compiler: clang
addons: &clang8
apt:
packages: ["clang-8", "clang-tidy-8", "libsdl2-dev", "libsdl2-ttf-dev", "libsdl2-image-dev", "libsdl2-mixer-dev"]
packages: ["clang-8", "libclang-8-dev", "llvm-8-dev", "llvm-8-tools", "libsdl2-dev", "libsdl2-ttf-dev", "libsdl2-image-dev", "libsdl2-mixer-dev"]
sources: [*apt_sources, llvm-toolchain-xenial-8]

# Finally check the compiler variants
Expand Down
12 changes: 10 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ SET(CMAKE_MODULE_PATH
${CMAKE_SOURCE_DIR}/CMakeModules
)

SET(CMAKE_TLS_VERIFY ON)

# Build options
option(TILES "Build graphical tileset version." "OFF")
option(CURSES "Build curses version." "ON" )
Expand All @@ -17,8 +19,11 @@ option(USE_HOME_DIR "Use user's home directory for save files." "ON" )
option(LOCALIZE "Support for language localizations. Also enable UTF support." "ON" )
option(LANGUAGES "Compile localization files for specified languages." "" )
option(DYNAMIC_LINKING "Use dynamic linking. Or use static to remove MinGW dependency instead." "ON")
option(GIT_BINARY "Git binary name or path." "")
OPTION(PREFIX "Location of Data & GFX directories" "")
option(CATA_CLANG_TIDY_PLUGIN "Build Cata's custom clang-tidy plugin" "OFF")
set(CATA_CLANG_TIDY_INCLUDE_DIR "" CACHE STRING "Path to internal clang-tidy headers required for plugin (e.g. ClangTidy.h)")
set(CATA_CHECK_CLANG_TIDY "" CACHE STRING "Path to check_clang_tidy.py for plugin tests")
set(GIT_BINARY "" CACHE STRING "Git binary name or path.")
set(PREFIX "" CACHE STRING "Location of Data & GFX directories")

include(CTest)

Expand Down Expand Up @@ -341,6 +346,9 @@ if (NOT MSVC)
add_subdirectory(src/chkjson)
endif()
add_subdirectory(tests)
if (CATA_CLANG_TIDY_PLUGIN)
add_subdirectory(tools/clang-tidy-plugin)
endif()

CONFIGURE_FILE(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,8 @@ TESTSRC := $(wildcard tests/*.cpp)
TESTHDR := $(wildcard tests/*.h)
JSON_FORMATTER_SOURCES := tools/format/format.cpp src/json.cpp
CHKJSON_SOURCES := src/chkjson/chkjson.cpp src/json.cpp
CLANG_TIDY_PLUGIN_SOURCES := \
$(wildcard tools/clang-tidy-plugin/*.cpp tools/clang-tidy-plugin/*/*.cpp)
TOOLHDR := $(wildcard tools/*/*.h)
# Using sort here because it has the side-effect of deduplicating the list
ASTYLE_SOURCES := $(sort \
Expand All @@ -694,6 +696,7 @@ ASTYLE_SOURCES := $(sort \
$(TESTHDR) \
$(JSON_FORMATTER_SOURCES) \
$(CHKJSON_SOURCES) \
$(CLANG_TIDY_PLUGIN_SOURCES) \
$(TOOLHDR))

_OBJS = $(SOURCES:$(SRC_DIR)/%.cpp=%.o)
Expand Down
29 changes: 28 additions & 1 deletion build-scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ then
build_type=Debug
fi

cmake_extra_opts=

if [ "$CATA_CLANG_TIDY" = "plugin" ]
then
cmake_extra_opts="$cmake_extra_opts -DCATA_CLANG_TIDY_PLUGIN=ON"
# Need to specify the particular LLVM / Clang versions to use, lest it
# use the llvm-7 that comes by default on the Travis Xenial image.
cmake_extra_opts="$cmake_extra_opts -DLLVM_DIR=/usr/lib/llvm-8/lib/cmake/llvm"
cmake_extra_opts="$cmake_extra_opts -DClang_DIR=/usr/lib/llvm-8/lib/cmake/clang"
fi

mkdir build
cd build
cmake \
Expand All @@ -49,9 +60,25 @@ then
-DCMAKE_BUILD_TYPE="$build_type" \
-DTILES=${TILES:-0} \
-DSOUND=${SOUND:-0} \
$cmake_extra_opts \
..
if [ -n "$CATA_CLANG_TIDY" ]
then
if [ "$CATA_CLANG_TIDY" = "plugin" ]
then
make -j$num_jobs CataAnalyzerPlugin
export PATH=$PWD/tools/clang-tidy-plugin/clang-tidy-plugin-support/bin:$PATH
if ! which FileCheck
then
ls -l tools/clang-tidy-plugin/clang-tidy-plugin-support/bin
ls -l /usr/bin
echo "Missing FileCheck"
exit 1
fi
CATA_CLANG_TIDY=clang-tidy
lit -v tools/clang-tidy-plugin/test
fi

"$CATA_CLANG_TIDY" --version

# Run clang-tidy analysis instead of regular build & test
Expand Down Expand Up @@ -95,7 +122,7 @@ then
analyze_files_in_random_order "$remaining_cpp_files"
else
# Regular build
make -j3
make -j$num_jobs
cd ..
# Run regular tests
[ -f "${bin_path}cata_test" ] && run_tests "${bin_path}cata_test"
Expand Down
9 changes: 8 additions & 1 deletion build-scripts/clang-tidy-wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,12 @@ then
exit 0
fi

plugin=build/tools/clang-tidy-plugin/libCataAnalyzerPlugin.so

set -x
"$CATA_CLANG_TIDY" "$@"
if [ -f "$plugin" ]
then
LD_PRELOAD=$plugin "$CATA_CLANG_TIDY" "$@"
else
"$CATA_CLANG_TIDY" "$@"
fi
2 changes: 1 addition & 1 deletion build-scripts/requirements.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ if [ -n "${CODE_COVERAGE}" ]; then
fi

if [ -n "$CATA_CLANG_TIDY" ]; then
travis_retry pip install --user compiledb
travis_retry pip install --user compiledb lit
fi

# Influenced by https://github.com/zer0main/battleship/blob/master/build/windows/requirements.sh
Expand Down
50 changes: 50 additions & 0 deletions doc/DEVELOPER_TOOLING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,56 @@ On Windows, there is an astyle extension for Visual Studio.

See the [JSON style guide](JSON_STYLE.md).

## clang-tidy

Cataclysm has a [clang-tidy configuration file](../.clang-tidy) and if you have
`clang-tidy` available you can run it to perform static analysis of the
codebase. We test with `clang-tidy` from LLVM 8.0.1 on Travis, so for the most
consistent results, you might want to use that version.

### Custom clang-tidy plugin

We have written our own clang-tidy checks in a custom plugin. Unfortunately,
`clang-tidy` as distributed by LLVM doesn't support plugins, so making this
work requires some extra steps.

If you are on Ubuntu Xenial then you might be able to get it working the same
way Travis does. Add the LLVM 8 Xenial source [listed
here](https://apt.llvm.org/) to your `sources.list`, install the `clang-8
libclang-8-dev llvm-8-dev llvm-8-tools` packages and build Cataclysm with CMake
adding `-DCATA_CLANG_TIDY_PLUGIN=ON`.

On other distributions you will probably need to build `clang-tidy` yourself.
* Check out the `llvm`, `clang`, and `clang-tools-extra` repositories in the
required layout (as described for example
[here](https://quuxplusone.github.io/blog/2018/04/16/building-llvm-from-source/).
* Patch in plugin support for `clang-tidy` using [this
patch](https://github.com/jbytheway/clang-tidy-plugin-support/blob/master/plugin-support.patch).
* Configure LLVM using CMake, including the
`-DCMAKE_EXE_LINKER_FLAGS="-rdynamic"` option.
* Add the `build/bin` directory to your path so that `clang-tidy` and
`FileCheck` are found from there.

Then you can use your locally build `clang-tidy` to compile Cataclysm. You'll
need to use the CMake version of the Cataclysm build rather than the `Makefile`
build. Add the following CMake options:
```sh
-DCATA_CLANG_TIDY_PLUGIN=ON
-DCATA_CLANG_TIDY_INCLUDE_DIR="$extra_dir/clang-tidy"
-DCATA_CHECK_CLANG_TIDY="$extra_dir/test/clang-tidy/check_clang_tidy.py"
```
where `$extra_dir` is the location of your `clang-tools-extra` checkout.

If you wish to run the tests for the custom clang-tidy plugin you will also
need `lit`. This will be built as part of `llvm`, or you can install it via
`pip` or your local package manager if you prefer.

Then, assuming `build` is your Cataclysm build directory, you can run the tests
with
```sh
lit -v build/tools/clang-tidy-plugin/test
```

## include-what-you-use

[include-what-you-use](https://github.com/include-what-you-use/include-what-you-use)
Expand Down
4 changes: 2 additions & 2 deletions tests/colony_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ TEST_CASE( "insert and erase", "[colony]" )
} while( count < 15000 );

// Erase randomly till half-empty
CHECK( test_colony.size() == static_cast<unsigned long>( 30000 - count ) );
CHECK( test_colony.size() == static_cast<size_t>( 30000 - count ) );

for( int i = 0; i < count; ++i ) {
test_colony.insert( 1 );
Expand Down Expand Up @@ -497,7 +497,7 @@ TEST_CASE( "insert and erase", "[colony]" )
}

// Multiple sequential small insert/erase commands
CHECK( test_colony.size() == static_cast<unsigned long>( count ) );
CHECK( test_colony.size() == static_cast<size_t>( count ) );
}

TEST_CASE( "range erase", "[colony]" )
Expand Down
54 changes: 54 additions & 0 deletions tools/clang-tidy-plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
include(ExternalProject)

find_package(LLVM REQUIRED CONFIG)
find_package(Clang REQUIRED CONFIG)

add_library(
CataAnalyzerPlugin MODULE
CataTidyModule.cpp NoLongCheck.cpp)

target_include_directories(
CataAnalyzerPlugin SYSTEM PRIVATE
${LLVM_INCLUDE_DIRS} ${CLANG_INCLUDE_DIRS})

if ("${CATA_CLANG_TIDY_INCLUDE_DIR}" STREQUAL "")
SET(ctps_releases
https://github.com/jbytheway/clang-tidy-plugin-support/releases/download)
SET(ctps_version llvm-8.0.1-r12)
SET(ctps_src
${CMAKE_CURRENT_BINARY_DIR}/clang-tidy-plugin-support)

ExternalProject_Add(
clang-tidy-plugin-support
URL ${ctps_releases}/${ctps_version}/clang-tidy-plugin-support-${ctps_version}.tar.xz
URL_HASH SHA256=00ffab0df11250f394830735514c62ae787bd2eb6eb9d5e97471206d270c54e2
SOURCE_DIR ${ctps_src}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)

add_dependencies(CataAnalyzerPlugin clang-tidy-plugin-support)
target_include_directories(
CataAnalyzerPlugin SYSTEM PRIVATE ${ctps_src}/include)
else()
target_include_directories(
CataAnalyzerPlugin SYSTEM PRIVATE ${CATA_CLANG_TIDY_INCLUDE_DIR})
endif()

target_compile_definitions(
CataAnalyzerPlugin PRIVATE ${LLVM_DEFINITIONS})

# We need to turn off exceptions and RTTI to match the LLVM build.
# I feel there ought to be a way to extract these flags from the
# LLVMConfig.cmake as we have done for e.g. LLVM_INCLUDE_DIRS above, but I
# haven't found one.
if(MSVC)
else()
target_compile_options(
CataAnalyzerPlugin PRIVATE -fno-exceptions -fno-rtti)
endif()

configure_file(test/lit.site.cfg.in test/lit.site.cfg @ONLY)
configure_file(test/.clang-tidy test/.clang-tidy COPYONLY)
28 changes: 28 additions & 0 deletions tools/clang-tidy-plugin/CataTidyModule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "ClangTidy.h"
#include "ClangTidyModule.h"
#include "ClangTidyModuleRegistry.h"
#include "NoLongCheck.h"

namespace clang
{
namespace tidy
{
namespace cata
{

class CataModule : public ClangTidyModule
{
public:
void addCheckFactories( ClangTidyCheckFactories &CheckFactories ) override {
CheckFactories.registerCheck<NoLongCheck>( "cata-no-long" );
}
};

} // namespace cata

// Register the MiscTidyModule using this statically initialized variable.
static ClangTidyModuleRegistry::Add<cata::CataModule>
X( "cata-module", "Adds Cataclysm-DDA checks." );

} // namespace tidy
} // namespace clang
Loading