Raymii.org
Quis custodiet ipsos custodes?Home | About | All pages | Cluster Status | RSS Feed
Run one specific clang-tidy check on your entire codebase
Published: 05-04-2021 | Author: Remy van Elst | Text only version of this article
❗ This post is over three years old. It may no longer be up to date. Opinions may have changed.
Table of Contents
Recently I did a major refactor on a piece of code that involved thousands of
lines of code which were in one way or another related to string handling.
All of the code handled char*
(C style character pointer arrays) and the
concept of const
or ownership was literally unknown in that part of the
codebase. The refactored code uses std::string
's, but due to the legacy
nature, a large number of methods returned nullptr
's instead of empty
strings (like ""
). I understand why this was done, but finding all those
instances and the fact it only gives a runtime error was a bit of a bummer.
Recently I removed all Google Ads from this site due to their invasive tracking, as well as Google Analytics. Please, if you found this content useful, consider a small donation using any of the options below. It means the world to me if you show your appreciation and you'll help pay the server costs:
GitHub Sponsorship
PCBWay referral link (You get $5, I get $20 after you've placed an order)
Digital Ocea referral link ($200 credit for 60 days. Spend $25 after your credit expires and I'll get $25!)
Luckily clang-tidy
is here to save the day. In my IDE, CLion, it gives a
warning when you return a nullptr
. It however does that only in the file
you're currently editing, and since we're talking millions of files, I wasn't
going to open them by hand. You can run clang-tidy
easily on one file, and
it's not hard to run it on an entire codebase as well, using the script
run-clang-tidy.py
, provided in their packages.
This snippet shows you how to run one specific clang-tidy
check, in my
case, bugprone-string-constructor
, on a (cmake and C++) codebase.
Here's the clang-tidy message in CLion:
Example code with undefined behaviour
This is an example piece of code demonstrating the behavior:
#include <string>
#include <iostream>
class Example {
public:
std::string getName() { return nullptr; }
};
int main() {
Example ex;
std::cout << "Example: " << ex.getName() << std::endl;
return 0;
}
If you try to run the above code example, you'll get a runtime error:
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
Opinions on nullptr
and std::string
differ depending on who you
ask, but as of now it's not possible to construct a std::string
with a
nullptr
.
Run clang-tidy on you entire codebase
Make sure you have clang-tidy
installed:
apt install clang-tidy
Navigate into your project folder:
cd my/cpp/project
If you haven't already, create a build folder (mkdir build; cd build
) and
run cmake
with an extra flag to create the compilation database for
clang-tidy
:
cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug
In the build folder, run run-clang-tidy
. It might be a different command
(run-clang-tidy.py
or run-clang-tidy-VERSIONNUMBER
) depending on your
distro's packaging preference.
run-clang-tidy -extra-arg=-Wno-unknown-warning-option -checks='-*,bugprone-string-constructor' 2>&1 | tee -a clang-tidy-result
This will take a while, when the command is finished, you can look at the
results, or in the file clang-tidy-result
. In my case it gave specific
filenames and line numbers where it found the undefined behavior.
The -extra-arg
was required due to some other compiler extension flag for
our code, you can probably omit that.
The -checks='-*'
disables all checks, the next
,bugprone-string-constructor
enables only the specific string check I
want to run. You can add more specific checks, separate them by a comma. An
example with just 2 checks enabled:
-checks='-*,bugprone-string-constructor,bugprone-string-integer-assignment'
An up to date list of clang-tidy
checks can be found on the LLVM website.