As a static analysis tool, Cppcheck has a set of default rules. However, when you are further into your development and realize that you need to create your own rules to catch specific bugs, this is the right blog for you. There are two ways to set your own Cppcheck rules: create an XML-based rule file, or create a C++-based rule file.
Creating an XML-based Rule File
Creating an XML-based rule file is more simple and straightforward but the bad news is the handling of this “simple” rule is deprecated and will be removed in Cppcheck version 2.5. In order to create a Cppcheck rule, one needs to have knowledge of regular expressions. A regular expression is used to find the line of code we want to check with. By having the regular expression in hand, we already can apply a rule with the following command option:
# Command usage
cppcheck --rule=<REGULAR_EXPRESSION> <FILE>
# An example of catching code redundancy
cppcheck --rule="if \\( p \\) { free \\( p \\) ; }" dealloc.cpp
The following is the output of the command above:
Checking dealloc.cpp...
[dealloc.cpp:2]: (style) found 'if ( p ) { free ( p ) ; }'
We can customize the responded message by creating an XML-based rule file with the regular expression. The following is a simple XML example that catches redundant code. Click here for more examples.
<?xml version="1.0"?>
<rule version="1">
<pattern>if \\( p \\) { free \\( p \\) ; }</pattern>
<message>
<id>redundantCondition</id>
<severity>style</severity>
<summary>Redundant condition. It is valid to free a NULL pointer.</summary>
</message>
</rule>
The pattern tag is where we insert the regular expression and the elements within the message tag are the messages that will be printed out on the terminal when the regular expression matches a line of code in a file. Once we have created the XML based rule file, we can use the following command option to locate the file, and apply the rule:
# Command usage cppcheck --rule-file=<RULE_FILE> <FILE> # An example of catching code redundancy cppcheck --rule-file=dealloc.rule dealloc.cpp
The following is the output of the command above:
Checking dealloc.cpp... [dealloc.cpp:2]: (style) Redundant condition. It is valid to free a NULL pointer.
Creating a C++-Based Rule File
A C++-based rule file will give us the flexibility to create a more sophisticated rule. In order to apply a C++-based rule file, we will have to recompile the Cppcheck tool with the rule file.
Build Cppcheck From Source
To build Cppcheck from the source, we first have to download the Cppcheck source code with the following command:
git clone <https://github.com/danmar/cppcheck/>
Rules are organized into Check classes. For example, there is a class with the name CheckStl that contains various stl rules. The CheckOther class can always be used if no other class suits you. When you have added your rule, you must recompile Cppcheck before you can test it. One of the ways to compile Cppcheck is by using g++.
To get started, search through the Cppcheck repo to find the source file and header file that have the same name as the class you want to add the custom rule to. For example, the CheckOther class and its methods are located in the checkother.cpp and checkother.h.
Let’s say you want to add a new rule to the CheckOther class. First, you have to create two new methods, one for detecting the pattern and one for error messaging. The following c++ code is an example of a rule to detect division by zero:
// Detect division by zero
void CheckOther::divisionByZero()
{
// Loop through all tokens
for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next())
{
// check if there is a division by zero
if (Token::Match(tok, "/ 0"))
{
// report error
divisionByZeroError(tok);
}
}
}
// Report error
void CheckOther::divisionByZeroError(const Token *tok)
{
reportError(tok, // location
Severity::error, // severity
"divisionByZero", // id
"Division by zero"); // message
}
The Token::Match function matches tokens against expressions. There are a few rules about the Token::Match expressions:
- The tokens are either completely matched or not matched at all. For example, the token “abc” is not matched by “ab”.
- Spaces are used as separators.
- With normal regular expressions, there are special meanings for
+ * ? ( )but these are just normal characters inToken::Matchpatterns.
Once the rule methods are added to the checkother.cpp, the checkother.h needs to get updated as well. The following are the things you need to add to the header file:
- Declare the pattern detecting method as a public method in the
CheckOtherclass and call it in therunChecksmethod:class CPPCHECKLIB CheckOther : public Check { public: void runChecks(...) OVERRIDE { // Checks ... checkOther.divisionByZero(); // Call the pattern detecting method ... } ... void divisionByZero(); // Declare the pattern detecting method ... } - Declare the error messaging method as a private method in the
CheckOtherclass and call it in thegetErrorMessagesmethod:class CPPCHECKLIB CheckOther : public Check { private: // Error messages.. ... void divisionByZeroError(const Token *tok); // Declare the error messaging method ... void getErrorMessages(...) const OVERRIDE { // error ... c.divisionByZeroError(nullptr); // Call the error messaging method ... } }
Once the code is in place, we are ready to compile Cppcheck with the following command:
g++ -o cppcheck -std=c++11 -Iexternals -Iexternals/simplecpp -Iexternals/tinyxml2 -Iexternals/picojson -Ilib cli/*.cpp lib/*.cpp externals/simplecpp/simplecpp.cpp externals/tinyxml2/*.cpp
Compiling the Cppcheck code will result in an executable. Move the Cppcheck executable to a location in your PATH. There you have it, a Cppcheck with a custom rule is ready to be used.
DojoFive brings modern tools, techniques, and best practices from the web and mobile development environments, paired with leading-edge innovations in firmware to our customers to help them build successful products and successful clients. We have talented engineers on hand ready to help you with all aspects of your EmbedOps journey. Bring your interesting problems that need solving – we are always happy to help out. You can reach out at any time on LinkedIn or through email!
Sign up to get our content updates!
Unlock the full potential of your embedded projects with our expert insights! Dive into our comprehensive resources to stay ahead in firmware development. Subscribe now to get the latest best practices and guides delivered straight to your inbox.
Sign Up for Updates


