Changed behaviour of Token::is*Op() functions:

- Rename Token::isOp() to Token::isConstOp() (indicating that the operator does _not_ modify the input variables)
- Create new Token::isOp(), returning true also for ++, -- and assignment operators
- Make Token::isExtendedOp() returning also true for all assignment and ++/-- operators
This commit is contained in:
PKEuS 2013-02-28 12:50:29 -08:00
parent ecafe7a129
commit 670c4de8a9
10 changed files with 54 additions and 21 deletions

View File

@ -1079,7 +1079,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
} }
} else if (tok2->varId() && extravar.find(tok2->varId()) != extravar.end()) { } else if (tok2->varId() && extravar.find(tok2->varId()) != extravar.end()) {
dep = true; dep = true;
} else if (tok2->varId() == varid && tok2->next()->isOp()) } else if (tok2->varId() == varid && tok2->next()->isConstOp())
dep = true; dep = true;
} }

View File

@ -324,7 +324,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
unknown = false; unknown = false;
// Dereferencing pointer.. // Dereferencing pointer..
if (tok->strAt(-1) == "*" && (Token::Match(tok->tokAt(-2), "return|throw|;|{|}|:|[|(|,") || tok->tokAt(-2)->isOp() || tok->tokAt(-2)->isAssignmentOp()) && !Token::Match(tok->tokAt(-3), "sizeof|decltype")) if (tok->strAt(-1) == "*" && (Token::Match(tok->tokAt(-2), "return|throw|;|{|}|:|[|(|,") || tok->tokAt(-2)->isOp()) && !Token::Match(tok->tokAt(-3), "sizeof|decltype"))
return true; return true;
// read/write member variable // read/write member variable
@ -1129,7 +1129,7 @@ void CheckNullPointer::nullConstantDereference()
tok = tok->next()->link(); tok = tok->next()->link();
else if (Token::simpleMatch(tok, "* 0")) { else if (Token::simpleMatch(tok, "* 0")) {
if (Token::Match(tok->previous(), "return|throw|;|{|}|:|[|(|,") || tok->previous()->isOp() || tok->previous()->isAssignmentOp()) { if (Token::Match(tok->previous(), "return|throw|;|{|}|:|[|(|,") || tok->previous()->isOp()) {
nullPointerError(tok); nullPointerError(tok);
} }
} }
@ -1406,8 +1406,8 @@ private:
if (Token::Match(tok.previous(), "[;{}=] %var% = 0 ;")) if (Token::Match(tok.previous(), "[;{}=] %var% = 0 ;"))
setnull(checks, tok.varId()); setnull(checks, tok.varId());
else if (!deref && else if (!deref &&
(!tok.previous()->isOp() || tok.previous()->str() == "&") && !tok.previous()->isAssignmentOp() && (!tok.previous()->isOp() || tok.previous()->str() == "&") &&
(!tok.next()->isOp() || tok.next()->str() == ">>")) (!tok.next()->isConstOp() || tok.next()->str() == ">>"))
bailOutVar(checks, tok.varId()); // If its possible that the pointers value changes, bail out. bailOutVar(checks, tok.varId()); // If its possible that the pointers value changes, bail out.
} }

View File

@ -389,7 +389,7 @@ void CheckOther::checkBitwiseOnBoolean()
bitwiseOnBooleanError(tok->next(), var->name(), tok->strAt(2) == "&" ? "&&" : "||"); bitwiseOnBooleanError(tok->next(), var->name(), tok->strAt(2) == "&" ? "&&" : "||");
tok = tok->tokAt(2); tok = tok->tokAt(2);
} }
} else if (Token::Match(tok, "[&|] %var% )|.|return|&&|%oror%|throw|,") && (!tok->previous() || !tok->previous()->isExtendedOp() || tok->strAt(-1) == ")")) { } else if (Token::Match(tok, "[&|] %var% )|.|return|&&|%oror%|throw|,") && (!tok->previous() || !tok->previous()->isExtendedOp() || tok->strAt(-1) == ")" || tok->strAt(-1) == "]")) {
const Variable *var = tok->next()->variable(); const Variable *var = tok->next()->variable();
if (var && var->typeEndToken()->str() == "bool") { if (var && var->typeEndToken()->str() == "bool") {
bitwiseOnBooleanError(tok->next(), var->name(), tok->str() == "&" ? "&&" : "||"); bitwiseOnBooleanError(tok->next(), var->name(), tok->str() == "&" ? "&&" : "||");
@ -3526,7 +3526,7 @@ void CheckOther::sizeofCalculation()
if (Token::simpleMatch(tok, "sizeof (")) { if (Token::simpleMatch(tok, "sizeof (")) {
const Token* const end = tok->linkAt(1); const Token* const end = tok->linkAt(1);
for (const Token *tok2 = tok->tokAt(2); tok2 != end; tok2 = tok2->next()) { for (const Token *tok2 = tok->tokAt(2); tok2 != end; tok2 = tok2->next()) {
if (tok2->isOp() && (!tok2->isExpandedMacro() || _settings->inconclusive) && !Token::Match(tok2, ">|<|&") && (Token::Match(tok2->previous(), "%var%") || tok2->str() != "*")) { if (tok2->isConstOp() && (!tok2->isExpandedMacro() || _settings->inconclusive) && !Token::Match(tok2, ">|<|&") && (Token::Match(tok2->previous(), "%var%") || tok2->str() != "*")) {
if (!(Token::Match(tok2->previous(), "%type%") || Token::Match(tok2->next(), "%type%"))) { if (!(Token::Match(tok2->previous(), "%type%") || Token::Match(tok2->next(), "%type%"))) {
sizeofCalculationError(tok2, tok2->isExpandedMacro()); sizeofCalculationError(tok2, tok2->isExpandedMacro());
break; break;

View File

@ -1530,7 +1530,7 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool cpp
// is there something like: ; "*((&var ..expr.. =" => the variable is assigned // is there something like: ; "*((&var ..expr.. =" => the variable is assigned
if (vartok->previous()->str() == "&") { if (vartok->previous()->str() == "&") {
const Token *tok2 = vartok->tokAt(-2); const Token *tok2 = vartok->tokAt(-2);
if (tok2 && (tok2->isOp() || tok2->str() == "(")) if (tok2 && (tok2->isConstOp() || tok2->str() == "("))
return false; // address of return false; // address of
if (Token::simpleMatch(tok2,")")) if (Token::simpleMatch(tok2,")"))
tok2 = tok2->link()->previous(); tok2 = tok2->link()->previous();

View File

@ -895,7 +895,7 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
} }
if (Token::simpleMatch(tok->previous(), "* 1") || Token::simpleMatch(tok, "1 *")) { if (Token::simpleMatch(tok->previous(), "* 1") || Token::simpleMatch(tok, "1 *")) {
if (tok->previous() && tok->previous()->isOp()) if (tok->previous() && tok->previous()->isConstOp())
tok = tok->previous(); tok = tok->previous();
tok->deleteNext(); tok->deleteNext();
tok->deleteThis(); tok->deleteThis();
@ -916,7 +916,7 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
Token::simpleMatch(tok->previous(), "| 0 )") || Token::simpleMatch(tok->previous(), "| 0 )") ||
Token::simpleMatch(tok->previous(), "( 1 &&") || Token::simpleMatch(tok->previous(), "( 1 &&") ||
Token::simpleMatch(tok->previous(), "&& 1 )")) { Token::simpleMatch(tok->previous(), "&& 1 )")) {
if (tok->previous()->isOp()) if (tok->previous()->isConstOp())
tok = tok->previous(); tok = tok->previous();
tok->deleteNext(); tok->deleteNext();
tok->deleteThis(); tok->deleteThis();

View File

@ -312,7 +312,7 @@ static int multiComparePercent(const Token *tok, const char * * haystack_p,
if (haystack[1] == 'o' && // "%op%" if (haystack[1] == 'o' && // "%op%"
haystack[2] == 'p' && haystack[2] == 'p' &&
haystack[3] == '%') { haystack[3] == '%') {
if (tok->isOp()) if (tok->isConstOp())
return 1; return 1;
*haystack_p = haystack = haystack + 4; *haystack_p = haystack = haystack + 4;
} else if (haystack[1] == 'o' && // "%or%" } else if (haystack[1] == 'o' && // "%or%"
@ -349,7 +349,7 @@ int Token::multiCompare(const Token *tok, const char *haystack, const char *need
haystack[3] == '%' && haystack[3] == '%' &&
haystack[4] == '|') { haystack[4] == '|') {
haystack = haystack + 5; haystack = haystack + 5;
if (tok->isOp()) if (tok->isConstOp())
return 1; return 1;
} else if (haystack[2] == 'r' && // "%or%|" } else if (haystack[2] == 'r' && // "%or%|"
haystack[3] == '%' && haystack[3] == '%' &&
@ -627,7 +627,7 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid)
// Op (%op%) // Op (%op%)
if (p[0] == 'p') { if (p[0] == 'p') {
p += 2; p += 2;
multicompare(p,tok->isOp(),ismulticomp); multicompare(p,tok->isConstOp(),ismulticomp);
} }
// Or (%or%) // Or (%or%)
else { else {

View File

@ -135,7 +135,7 @@ public:
* - "%comp%" Any token such that isComparisonOp() returns true. * - "%comp%" Any token such that isComparisonOp() returns true.
* - "%str%" Any token starting with &quot;-character (C-string). * - "%str%" Any token starting with &quot;-character (C-string).
* - "%varid%" Match with parameter varid * - "%varid%" Match with parameter varid
* - "%op%" Any token such that isOp() returns true. * - "%op%" Any token such that isConstOp() returns true.
* - "%or%" A bitwise-or operator '|' * - "%or%" A bitwise-or operator '|'
* - "%oror%" A logical-or operator '||' * - "%oror%" A logical-or operator '||'
* - "[abc]" Any of the characters 'a' or 'b' or 'c' * - "[abc]" Any of the characters 'a' or 'b' or 'c'
@ -204,19 +204,24 @@ public:
bool isNumber() const { bool isNumber() const {
return _type == eNumber; return _type == eNumber;
} }
bool isArithmeticalOp() const {
return _type == eArithmeticalOp;
}
bool isOp() const { bool isOp() const {
return (isConstOp() ||
isAssignmentOp() ||
_type == eIncDecOp);
}
bool isConstOp() const {
return (isArithmeticalOp() || return (isArithmeticalOp() ||
_type == eLogicalOp || _type == eLogicalOp ||
_type == eComparisonOp || _type == eComparisonOp ||
_type == eBitOp); _type == eBitOp);
} }
bool isExtendedOp() const { bool isExtendedOp() const {
return isOp() || return isConstOp() ||
_type == eExtendedOp; _type == eExtendedOp;
} }
bool isArithmeticalOp() const {
return _type == eArithmeticalOp;
}
bool isComparisonOp() const { bool isComparisonOp() const {
return _type == eComparisonOp; return _type == eComparisonOp;
} }

View File

@ -4214,7 +4214,7 @@ void Tokenizer::simplifyCompoundAssignment()
break; break;
} }
someOperator |= (tok2->isOp() || (tok2->str() == "?") || tok2->isAssignmentOp()); someOperator |= (tok2->isOp() || tok2->str() == "?");
} }
} }

View File

@ -393,7 +393,7 @@ void TokenList::createAst()
const std::string op(operators[i]); const std::string op(operators[i]);
for (Token *tok = _front; tok; tok = tok->next()) { for (Token *tok = _front; tok; tok = tok->next()) {
if (tok->astOperand1()==NULL && op.find(" "+tok->str()+" ")!=std::string::npos) { if (tok->astOperand1()==NULL && op.find(" "+tok->str()+" ")!=std::string::npos) {
if (tok->str() != "++" && tok->str() != "--") { if (tok->type() != Token::eIncDecOp) {
tok->astOperand1(tok->previous()); tok->astOperand1(tok->previous());
tok->astOperand2(tok->next()); tok->astOperand2(tok->next());
} else if (tok->previous() && !tok->previous()->isOp()) { } else if (tok->previous() && !tok->previous()->isOp()) {

View File

@ -68,6 +68,7 @@ private:
TEST_CASE(isArithmeticalOp); TEST_CASE(isArithmeticalOp);
TEST_CASE(isOp); TEST_CASE(isOp);
TEST_CASE(isConstOp);
TEST_CASE(isExtendedOp); TEST_CASE(isExtendedOp);
TEST_CASE(isAssignmentOp); TEST_CASE(isAssignmentOp);
TEST_CASE(isStandardType); TEST_CASE(isStandardType);
@ -569,6 +570,7 @@ private:
append_vector(test_ops, bitOps); append_vector(test_ops, bitOps);
append_vector(test_ops, comparisonOps); append_vector(test_ops, comparisonOps);
append_vector(test_ops, logicalOps); append_vector(test_ops, logicalOps);
append_vector(test_ops, assignmentOps);
std::vector<std::string>::const_iterator test_op, test_ops_end = test_ops.end(); 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) { for (test_op = test_ops.begin(); test_op != test_ops_end; ++test_op) {
@ -580,7 +582,6 @@ private:
// Negative test against other operators // Negative test against other operators
std::vector<std::string> other_ops; std::vector<std::string> other_ops;
append_vector(other_ops, extendedOps); append_vector(other_ops, extendedOps);
append_vector(other_ops, assignmentOps);
std::vector<std::string>::const_iterator other_op, other_ops_end = other_ops.end(); 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) { for (other_op = other_ops.begin(); other_op != other_ops_end; ++other_op) {
@ -590,6 +591,33 @@ private:
} }
} }
void isConstOp() {
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) {
Token tok(NULL);
tok.str(*test_op);
ASSERT_EQUALS(true, tok.isConstOp());
}
// 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) {
Token tok(NULL);
tok.str(*other_op);
ASSERT_EQUALS_MSG(false, tok.isConstOp(), "Failing normal operator: " + *other_op);
}
}
void isExtendedOp() { void isExtendedOp() {
std::vector<std::string> test_ops; std::vector<std::string> test_ops;
append_vector(test_ops, arithmeticalOps); append_vector(test_ops, arithmeticalOps);