Changed behaviour of %op% pattern accordingly to changes to Token::isOp(). Added %cop% as replacement for old %op%

This commit is contained in:
PKEuS 2013-03-01 02:43:59 -08:00
parent 7283152d58
commit f899e6ca30
10 changed files with 81 additions and 35 deletions

View File

@ -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);

View File

@ -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 File

@ -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 File

@ -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 File

@ -486,7 +486,7 @@ private:
}
// Used..
if (Token::Match(tok.previous(), "[[(,+-*/|=] %var% ]|)|,|;|%op%")) {
if (Token::Match(tok.previous(), "[[(,+-*/|=] %var% ]|)|,|;|%op%") && !tok.next()->isAssignmentOp()) {
// 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 File

@ -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 File

@ -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 File

@ -136,6 +136,7 @@ public:
* - "%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 File

@ -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 File

@ -65,6 +65,7 @@ private:
TEST_CASE(matchBoolean);
TEST_CASE(matchOr);
TEST_CASE(matchOp);
TEST_CASE(matchConstOp);
TEST_CASE(isArithmeticalOp);
TEST_CASE(isOp);
@ -453,7 +454,7 @@ private:
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 @@ private:
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,7 +534,6 @@ private:
// 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) {
@ -540,6 +541,30 @@ private:
}
}
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) {