Permalink
Browse files

Changed behaviour of %op% pattern accordingly to changes to Token::is…

…Op(). Added %cop% as replacement for old %op%
  • Loading branch information...
1 parent 7283152 commit f899e6ca300c5b60f3f41851a3381137af948670 @PKEuS PKEuS committed Mar 1, 2013
View
@@ -79,13 +79,13 @@ bool CheckAssignIf::assignIfParseScope(const Token * const assignTok,
const MathLib::bigint num)
{
for (const Token *tok2 = startTok; tok2; tok2 = tok2->next()) {
- if (Token::Match(tok2->tokAt(2), "%varid% %op% %num% ;", varid) && tok2->strAt(3) == std::string(1U, bitop)) {
+ if (Token::Match(tok2->tokAt(2), "%varid% %cop% %num% ;", varid) && tok2->strAt(3) == std::string(1U, bitop)) {
const MathLib::bigint num2 = MathLib::toLongNumber(tok2->strAt(4));
if ((bitop == '&') && (0 == (num & num2)))
mismatchingBitAndError(assignTok, num, tok2, num2);
}
if (Token::Match(tok2, "%varid% =", varid)) {
- if (Token::Match(tok2->tokAt(2), "%varid% %op% %num% ;", varid) && tok2->strAt(3) == std::string(1U, bitop)) {
+ if (Token::Match(tok2->tokAt(2), "%varid% %cop% %num% ;", varid) && tok2->strAt(3) == std::string(1U, bitop)) {
const MathLib::bigint num2 = MathLib::toLongNumber(tok2->strAt(4));
if ((bitop == '&') && (0 == (num & num2)))
mismatchingBitAndError(assignTok, num, tok2, num2);
@@ -669,7 +669,7 @@ void CheckBufferOverrun::checkFunctionParameter(const Token &tok, unsigned int p
Token::Match(ftok, "%var% --"))
break;
- if (Token::Match(ftok->previous(), "=|;|{|}|%op% %var% [ %num% ]")) {
+ if (Token::Match(ftok->previous(), ";|{|}|%op% %var% [ %num% ]")) {
const MathLib::bigint index = MathLib::toLongNumber(ftok->strAt(2));
if (index >= 0 && arrayInfo.num(0) > 0 && index >= arrayInfo.num(0)) {
std::list<const Token *> callstack2(callstack);
View
@@ -127,6 +127,7 @@ void CheckInternal::checkMissingPercentCharacter()
magics.insert("%comp%");
magics.insert("%num%");
magics.insert("%op%");
+ magics.insert("%cop%");
magics.insert("%or%");
magics.insert("%oror%");
magics.insert("%str%");
@@ -182,6 +183,7 @@ void CheckInternal::checkUnknownPattern()
knownPatterns.insert("%comp%");
knownPatterns.insert("%num%");
knownPatterns.insert("%op%");
+ knownPatterns.insert("%cop%");
knownPatterns.insert("%or%");
knownPatterns.insert("%oror%");
knownPatterns.insert("%str%");
View
@@ -1286,8 +1286,8 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
Token::Match(tok, "= strcpy|strcat|memmove|memcpy ( %varid% ,", varid) ||
Token::Match(tok, "[;{}] %var% [ %varid% ]", varid)) {
addtoken(&rettail, tok, "use");
- } else if (Token::Match(tok->previous(), ";|{|}|=|(|,|%op% %varid% [", varid) ||
- Token::Match(tok->previous(), ";|{|}|=|(|,|%op% %varid% .", varid)) {
+ } else if (Token::Match(tok->previous(), ";|{|}|=|(|,|%cop% %varid% [", varid) ||
+ Token::Match(tok->previous(), ";|{|}|=|(|,|%cop% %varid% .", varid)) {
// warning is written for "dealloc ; use_ ;".
// but this use doesn't affect the leak-checking
addtoken(&rettail, tok, "use_");
View
@@ -486,7 +486,7 @@ class UninitVar : public ExecutionPath {
}
// Used..
- if (Token::Match(tok.previous(), "[[(,+-*/|=] %var% ]|)|,|;|%op%")) {
+ if (Token::Match(tok.previous(), "[[(,+-*/|=] %var% ]|)|,|;|%op%") && !tok.next()->isAssignmentOp()) {
orbitcowboy
orbitcowboy Jun 5, 2013 Collaborator

In order to avoid a potential nullptr-dereference, you could check tok.next() against NULL before using it.

This line does the job:
if (Token::Match(tok.previous(), "[[(,+-*/|=] %var% ]|)|,|;|%op%") && tok.next() && !tok.next()->isAssignmentOp()) {

PKEuS
PKEuS Jun 5, 2013 Collaborator

This Token::Match call requries 3 tokens. Thus, tok.next() is guaranteed to be no nullptr, if Token::Match returned true on tok.previous().

// Taking address of array..
std::list<ExecutionPath *>::const_iterator it;
for (it = checks.begin(); it != checks.end(); ++it) {
@@ -1357,7 +1357,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
// variable is seen..
if (tok->varId() == var.varId()) {
if (!membervar.empty()) {
- if (Token::Match(tok, "%var% . %var% ;|%op%") && tok->strAt(2) == membervar)
+ if (Token::Match(tok, "%var% . %var% ;|%cop%") && tok->strAt(2) == membervar)
uninitStructMemberError(tok, tok->str() + "." + membervar);
else
return true;
@@ -1521,7 +1521,7 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool cpp
}
}
- if (Token::Match(vartok->previous(), "++|--|%op%")) {
+ if (Token::Match(vartok->previous(), "++|--|%cop%")) {
if (cpp && vartok->previous()->str() == ">>") {
// assume that variable is initialized
return false;
@@ -1581,7 +1581,7 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool cpp
return (var && var->typeStartToken()->isStandardType());
}
- if (Token::Match(vartok->next(), "++|--|%op%"))
+ if (vartok->next() && vartok->next()->isOp() && !vartok->next()->isAssignmentOp())
return true;
if (vartok->strAt(1) == "]")
@@ -1597,7 +1597,7 @@ bool CheckUninitVar::isMemberVariableAssignment(const Token *tok, const std::str
return true;
else if (Token::Match(tok->tokAt(-2), "[(,=] &"))
return true;
- else if (Token::Match(tok->previous(), "%op%") || Token::Match(tok->previous(), "[|="))
+ else if ((tok->previous() && tok->previous()->isConstOp()) || Token::Match(tok->previous(), "[|="))
; // member variable usage
else
return true;
View
@@ -794,7 +794,7 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
// keep parentheses here: Functor()(a ... )
// keep parentheses here: ) ( var ) ;
if ((Token::Match(tok->next(), "( %var% ) ;|)|,|]") ||
- (Token::Match(tok->next(), "( %var% ) %op%") && (tok->tokAt(2)->varId()>0 || !Token::Match(tok->tokAt(4), "[*&]")))) &&
+ (Token::Match(tok->next(), "( %var% ) %cop%") && (tok->tokAt(2)->varId()>0 || !Token::Match(tok->tokAt(4), "[*&]")))) &&
!tok->isName() &&
tok->str() != ">" &&
tok->str() != "]" &&
@@ -853,19 +853,19 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
tok->deleteNext();
tok->deleteThis();
ret = true;
- } else if (Token::Match(tok->previous(), "[=[(,] 0 * %var% ,|]|)|;|=|%op%") ||
- Token::Match(tok->previous(), "[=[(,] 0 * %num% ,|]|)|;|=|%op%") ||
- Token::Match(tok->previous(), "[=[(,] 0 * ( ,|]|)|;|=|%op%") ||
- Token::Match(tok->previous(), "return|case 0 *|&& %var% ,|:|;|=|%op%") ||
- Token::Match(tok->previous(), "return|case 0 *|&& %num% ,|:|;|=|%op%") ||
- Token::Match(tok->previous(), "return|case 0 *|&& ( ,|:|;|=|%op%")) {
+ } else if (Token::Match(tok->previous(), "[=[(,] 0 * %var% ,|]|)|;|=|%cop%") ||
+ Token::Match(tok->previous(), "[=[(,] 0 * %num% ,|]|)|;|%op%") ||
+ Token::Match(tok->previous(), "[=[(,] 0 * (") ||
+ Token::Match(tok->previous(), "return|case 0 *|&& %var% ,|:|;|=|%cop%") ||
+ Token::Match(tok->previous(), "return|case 0 *|&& %num% ,|:|;|%op%") ||
+ Token::Match(tok->previous(), "return|case 0 *|&& (")) {
tok->deleteNext();
if (tok->next()->str() == "(")
Token::eraseTokens(tok, tok->next()->link());
tok->deleteNext();
ret = true;
- } else if (Token::Match(tok->previous(), "[=[(,] 0 && *|& %any% ,|]|)|;|=|%op%") ||
- Token::Match(tok->previous(), "return|case 0 && *|& %any% ,|:|;|=|%op%")) {
+ } else if (Token::Match(tok->previous(), "[=[(,] 0 && *|& %any% ,|]|)|;|=|%cop%") ||
+ Token::Match(tok->previous(), "return|case 0 && *|& %any% ,|:|;|=|%cop%")) {
tok->deleteNext();
tok->deleteNext();
if (tok->next()->str() == "(")
@@ -876,15 +876,15 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
}
if (tok->str() == "1") {
- if (Token::Match(tok->previous(), "[=[(,] 1 %oror% %any% ,|]|)|;|=|%op%") ||
- Token::Match(tok->previous(), "return|case 1 %oror% %any% ,|:|;|=|%op%")) {
+ if (Token::Match(tok->previous(), "[=[(,] 1 %oror% %any% ,|]|)|;|=|%cop%") ||
+ Token::Match(tok->previous(), "return|case 1 %oror% %any% ,|:|;|=|%cop%")) {
tok->deleteNext();
if (tok->next()->str() == "(")
Token::eraseTokens(tok, tok->next()->link());
tok->deleteNext();
ret = true;
- } else if (Token::Match(tok->previous(), "[=[(,] 1 %oror% *|& %any% ,|]|)|;|=|%op%") ||
- Token::Match(tok->previous(), "return|case 1 %oror% *|& %any% ,|:|;|=|%op%")) {
+ } else if (Token::Match(tok->previous(), "[=[(,] 1 %oror% *|& %any% ,|]|)|;|=|%cop%") ||
+ Token::Match(tok->previous(), "return|case 1 %oror% *|& %any% ,|:|;|=|%cop%")) {
tok->deleteNext();
tok->deleteNext();
if (tok->next()->str() == "(")
View
@@ -312,9 +312,16 @@ static int multiComparePercent(const Token *tok, const char * * haystack_p,
if (haystack[1] == 'o' && // "%op%"
haystack[2] == 'p' &&
haystack[3] == '%') {
- if (tok->isConstOp())
+ if (tok->isOp())
return 1;
*haystack_p = haystack = haystack + 4;
+ } else if (haystack[1] == 'c' && // "%cop%"
+ haystack[2] == 'o' &&
+ haystack[3] == 'p' &&
+ haystack[4] == '%') {
+ if (tok->isConstOp())
+ return 1;
+ *haystack_p = haystack = haystack + 5;
} else if (haystack[1] == 'o' && // "%or%"
haystack[2] == 'r' &&
haystack[3] == '%') {
@@ -349,7 +356,7 @@ int Token::multiCompare(const Token *tok, const char *haystack, const char *need
haystack[3] == '%' &&
haystack[4] == '|') {
haystack = haystack + 5;
- if (tok->isConstOp())
+ if (tok->isOp())
return 1;
} else if (haystack[2] == 'r' && // "%or%|"
haystack[3] == '%' &&
@@ -366,6 +373,12 @@ int Token::multiCompare(const Token *tok, const char *haystack, const char *need
if (needle[0] == '|' && needle[1] == '|')
return 1;
}
+ } else if (haystack[0] == '%' && haystack[1] == 'c' && haystack[2] == 'o' && // "%cop%|"
+ haystack[3] == 'p' && haystack[4] == '%' &&
+ haystack[5] == '|') {
+ haystack = haystack + 6;
+ if (tok->isConstOp())
+ return 1;
}
bool emptyStringFound = false;
@@ -600,6 +613,11 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid)
p += 4;
multicompare(p,tok->type() == eChar,ismulticomp);
}
+ // Const operator (%cop%)
+ else if (p[1] == 'p') {
+ p += 3;
+ multicompare(p,tok->isConstOp(),ismulticomp);
+ }
// Comparison operator (%comp%)
else {
p += 4;
@@ -627,7 +645,7 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid)
// Op (%op%)
if (p[0] == 'p') {
p += 2;
- multicompare(p,tok->isConstOp(),ismulticomp);
+ multicompare(p,tok->isOp(),ismulticomp);
}
// Or (%or%)
else {
View
@@ -136,6 +136,7 @@ class CPPCHECKLIB Token {
* - "%str%" Any token starting with &quot;-character (C-string).
* - "%varid%" Match with parameter varid
* - "%op%" Any token such that isConstOp() returns true.
+ * - "%cop%" Any token such that isConstOp() returns true.
* - "%or%" A bitwise-or operator '|'
* - "%oror%" A logical-or operator '||'
* - "[abc]" Any of the characters 'a' or 'b' or 'c'
View
@@ -2255,7 +2255,7 @@ void Tokenizer::simplifyNull()
void Tokenizer::concatenateNegativeNumberAndAnyPositive()
{
for (Token *tok = list.front(); tok; tok = tok->next()) {
- if (!Token::Match(tok, "?|:|,|(|[|{|=|return|case|sizeof|%op% +|-"))
+ if (!Token::Match(tok, "?|:|,|(|[|{|return|case|sizeof|%op% +|-") || tok->type() == Token::eIncDecOp)
continue;
if (tok->next()->str() == "+")
tok->deleteNext();
@@ -4955,7 +4955,7 @@ bool Tokenizer::simplifyFunctionReturn()
else if (Token::Match(tok, "%var% ( ) { return %bool%|%char%|%num%|%str% ; }")) {
const Token* const any = tok->tokAt(5);
- const std::string pattern("(|[|=|%op% " + tok->str() + " ( ) ;|]|)|%op%");
+ const std::string pattern("(|[|=|%cop% " + tok->str() + " ( ) ;|]|)|%cop%");
for (Token *tok2 = list.front(); tok2; tok2 = tok2->next()) {
if (Token::Match(tok2, pattern.c_str())) {
tok2 = tok2->next();
@@ -5944,7 +5944,7 @@ bool Tokenizer::simplifyKnownVariables()
//check if there's not a reference usage inside the code
bool withreference = false;
for (const Token *tok2 = valuetok->tokAt(2); tok2; tok2 = tok2->next()) {
- if (Token::Match(tok2,"(|[|,|{|=|return|%op% & %varid%", vartok->varId())) {
+ if (Token::Match(tok2,"(|[|,|{|return|%op% & %varid%", vartok->varId())) {
withreference = true;
break;
}
@@ -6444,7 +6444,7 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign
}
// array usage
- if (value[0] != '\"' && Token::Match(tok3, ("[(,] " + structname + " %varid% [|%op%").c_str(), varid)) {
+ if (value[0] != '\"' && Token::Match(tok3, ("[(,] " + structname + " %varid% [|%cop%").c_str(), varid)) {
if (!structname.empty()) {
tok3->deleteNext(2);
}
@@ -6468,7 +6468,7 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign
if (((tok3->previous()->varId() > 0) && Token::Match(tok3, ("& " + structname + " %varid%").c_str(), varid)) ||
(Token::Match(tok3, ("[=+-*/%^|[] " + structname + " %varid% [=?+-*/%^|;])]").c_str(), varid) && !Token::Match(tok3, ("= " + structname + " %var% =").c_str())) ||
Token::Match(tok3, ("[(=+-*/%^|[] " + structname + " %varid% <<|>>").c_str(), varid) ||
- Token::Match(tok3, ("<<|>> " + structname + " %varid% %op%|;|]|)").c_str(), varid) ||
+ Token::Match(tok3, ("<<|>> " + structname + " %varid% %cop%|;|]|)").c_str(), varid) ||
Token::Match(tok3->previous(), ("[=+-*/%^|[] ( " + structname + " %varid% !!=").c_str(), varid)) {
if (value[0] == '\"')
break;
@@ -6716,7 +6716,7 @@ bool Tokenizer::simplifyRedundantParentheses()
}
// Simplify "!!operator !!(%var%|)) ( %num%|%bool% ) %op%|;|,|)"
- if (Token::Match(tok, "( %bool%|%num% ) %op%|;|,|)") &&
+ if (Token::Match(tok, "( %bool%|%num% ) %cop%|;|,|)") &&
!Token::simpleMatch(tok->tokAt(-2), "operator") &&
tok->previous() &&
!tok->previous()->isName() &&
@@ -9244,7 +9244,7 @@ void Tokenizer::simplifyOperatorName()
}
done = false;
}
- if (Token::Match(par, "=|.|++|--|%op%")) {
+ if (Token::Match(par, ".|%op%")) {
op += par->str();
par = par->next();
done = false;
View
@@ -65,6 +65,7 @@ class TestToken : public TestFixture {
TEST_CASE(matchBoolean);
TEST_CASE(matchOr);
TEST_CASE(matchOp);
+ TEST_CASE(matchConstOp);
TEST_CASE(isArithmeticalOp);
TEST_CASE(isOp);
@@ -453,7 +454,7 @@ class TestToken : public TestFixture {
givenACodeSampleToTokenize bitwiseOrAssignment("|=");
ASSERT_EQUALS(false, Token::Match(bitwiseOrAssignment.tokens(), "%or%"));
- ASSERT_EQUALS(false, Token::Match(bitwiseOrAssignment.tokens(), "%op%"));
+ ASSERT_EQUALS(true, Token::Match(bitwiseOrAssignment.tokens(), "%op%"));
ASSERT_EQUALS(false, Token::Match(bitwiseOrAssignment.tokens(), "%oror%"));
givenACodeSampleToTokenize logicalOr("||", true);
@@ -523,6 +524,7 @@ class TestToken : public TestFixture {
append_vector(test_ops, bitOps);
append_vector(test_ops, comparisonOps);
append_vector(test_ops, logicalOps);
+ append_vector(test_ops, assignmentOps);
std::vector<std::string>::const_iterator test_op, test_ops_end = test_ops.end();
for (test_op = test_ops.begin(); test_op != test_ops_end; ++test_op) {
@@ -532,14 +534,37 @@ class TestToken : public TestFixture {
// Negative test against other operators
std::vector<std::string> other_ops;
append_vector(other_ops, extendedOps);
- append_vector(other_ops, assignmentOps);
std::vector<std::string>::const_iterator other_op, other_ops_end = other_ops.end();
for (other_op = other_ops.begin(); other_op != other_ops_end; ++other_op) {
ASSERT_EQUALS_MSG(false, Match(*other_op, "%op%"), "Failing other operator: " + *other_op);
}
}
+ void matchConstOp() {
+ std::vector<std::string> test_ops;
+ append_vector(test_ops, arithmeticalOps);
+ append_vector(test_ops, bitOps);
+ append_vector(test_ops, comparisonOps);
+ append_vector(test_ops, logicalOps);
+
+ std::vector<std::string>::const_iterator test_op, test_ops_end = test_ops.end();
+ for (test_op = test_ops.begin(); test_op != test_ops_end; ++test_op) {
+ ASSERT_EQUALS(true, Match(*test_op, "%cop%"));
+ }
+
+ // Negative test against other operators
+ std::vector<std::string> other_ops;
+ append_vector(other_ops, extendedOps);
+ append_vector(other_ops, assignmentOps);
+
+ std::vector<std::string>::const_iterator other_op, other_ops_end = other_ops.end();
+ for (other_op = other_ops.begin(); other_op != other_ops_end; ++other_op) {
+ ASSERT_EQUALS_MSG(false, Match(*other_op, "%cop%"), "Failing other operator: " + *other_op);
+ }
+ }
+
+
void isArithmeticalOp() {
std::vector<std::string>::const_iterator test_op, test_ops_end = arithmeticalOps.end();
for (test_op = arithmeticalOps.begin(); test_op != test_ops_end; ++test_op) {

0 comments on commit f899e6c

Please sign in to comment.