Biswajit Banerjee

### Auto-modernizing C++ code

Using clang-tidy with cmake

The Clang static analyzer tools come with a handy interface called clang-tidy.

I’ve been try to set up this tool in my cmake toolchain with varying levels of success. In particular I’d like to automate the conversion of old code into a version that uses C++11 and some C++14 constructs.

#### Attempt 1

In my first attempt I created a cmake directory at the top level of my source tree and added a clang-tidy.cmake file that contained the following:


file(GLOB_RECURSE ALL_MY_SOURCE_FILES *.cpp *.hpp *.cc *.h)
clang-tidy
COMMAND /usr/bin/clang-tidy
${ALL_MY_SOURCE_FILES} -config='' -export-fixes='clang-tidy-fixes.dat' -- -std=c++14 -I${MY_SOURCE_INCLUDE_DIR}
-I${MY_MPI_INCLUDE_DIR1} -I${MY_MPI_INCLUDE_DIR2}
-I${MY_MPI_INCLUDE_DIR3} -I${MY_BOOST_INCLUDE_DIR}
-I\${MY_VTK_INCLUDE_DIR}
)



At the bottom of my main CMakeList.txt file I added


include(cmake/clang-tidy.cmake)



When I ran cmake and then make clang-tidy, there were several complaints about header files not being found, but the suggested fixes were written to the file clang-tidy-fixes.dat. That file contained numerous suggested fixes in the format


- FilePath:        /path/to/file/parser.h
Offset:          9558
Length:          52
ReplacementText: '(const auto & token : tokens)'



Going through that file and then hand-coding the changes looked daunting, so I looked at automating the code change process.

#### Attempt 2

To make clang-tidy apply the fixes automatically, I replaced


-export-fixes='clang-tidy-fixes.dat'



in clang-tidy.cmake to


-fix-errors



When I ran make clang-tidy after that change, fixes were automatically applied, but also applied multiple times. For example, I got


std::move(std::move(std::move(std::move(a))));




std::move(a);



#### Attempt 3

Clearly, attempt 2 wasn’t solving the problem, and I went back to the clang-tidy manual and found that I could actually export the compile commands from by build using


cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ../src



That command created a compile_commands.json file which contained all the path and header information that a build could need.

I then located the python script for running clang-tidy from


/usr/lib/llvm-3.8/share/clang/run-clang-tidy.py



and, from my build directory containing compile_commands.json, I ran


run-clang-tidy.py ../src -checks=modernize* -fix



No more complaints about missing header files, and all fixes appeared to have been applied only once. It’s much easier to use this process than to try to create a custom target for cmake.