From 45b6d09373bdcbac061c5777ab0c7cc993de9dab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 4 Jan 2011 07:50:54 +0100 Subject: [PATCH] Writing rules: Added part 3. Introduction to writing rules with C++. --- man/writing-rules-3.docbook | 152 ++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 man/writing-rules-3.docbook diff --git a/man/writing-rules-3.docbook b/man/writing-rules-3.docbook new file mode 100644 index 000000000..787ff9910 --- /dev/null +++ b/man/writing-rules-3.docbook @@ -0,0 +1,152 @@ + +
+ + Writing Cppcheck rules + + Part 3 - Introduction to writing rules with C++ + + + DanielMarjamäki + + + Cppcheck + + + + 2011 + + +
+ Introduction + + The goal for this article is to introduce how + Cppcheck rules are written with C++. With C++ it is + possible to write more complex rules than is possible with regular + expressions. +
+ +
+ Basics + + A C++ rule is written in a C++ function. + + Rules are organized into Check classes. For instance there is a + class with the name CheckStl that contains various stl + rules. The CheckOther 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. +
+ +
+ Division by zero + + This simple regular expression will check for division by + zero: + + cppcheck --rule="/ 0" + + Here is the corresponding C++ check: + + // Detect division by zero +void CheckOther::divisionByZero() +{ + // Loop through all tokens + for (const Token *tok = _tokenizer->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() +{ + reportError(tok, Severity::error, "divisionByZero", "Division by zero"); +} + + The Token::Match matches tokens against + expressions. A few rules about Token::Match expressions are: + + + + tokens are either completely matched or not matched at all. The + token "abc" is not matched by "ab". + + + + Spaces are used as separators. + + + + With normal regular expressions there are special meanings for + + * ? ( ). These are just normal characters in + Token::Match patterns. + + +
+ +
+ Condition before deallocation + + In the first Writing rules article I described a + rule that looks for redundant conditions. Here is the regular expression + that was shown: + + if \( p \) { free \( p \) ; } + + The corresponding Token::Match expression + is: + + if ( %var% ) { free ( %var% ) ; } + + Any variable name is matched by %var%. + + Here is a C++ function: + + // Find redundant condition before deallocation +void CheckOther::dealloc() +{ + // Loop through all tokens + for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) + { + // Is there a condition and a deallocation? + if (Token::Match(tok, "if ( %var% ) { free ( %var% ) ; }")) + { + // Get variable name used in condition: + const std::string varname1 = tok->strAt(2); + + // Get variable name used in deallocation: + const std::string varname2 = tok->strAt(7); + + // Is the same variable used? + if (varname1 == varname2) + { + // report warning + deallocWarning(tok); + } + } + } +} + +// Report warning +void CheckOther::deallocWarning() +{ + reportError(tok, Severity::warning, "dealloc", "Redundant condition before deallocation"); +} + + The strAt function is used to fetch strings from the token list. The + parameter specifies the token offset. +
+