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:
parent
ecafe7a129
commit
670c4de8a9
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
15
lib/token.h
15
lib/token.h
|
@ -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 "-character (C-string).
|
* - "%str%" Any token starting with "-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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4214,7 +4214,7 @@ void Tokenizer::simplifyCompoundAssignment()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
someOperator |= (tok2->isOp() || (tok2->str() == "?") || tok2->isAssignmentOp());
|
someOperator |= (tok2->isOp() || tok2->str() == "?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue