From 670c4de8a929f4f035771e05358f507075d40f6d Mon Sep 17 00:00:00 2001 From: PKEuS Date: Thu, 28 Feb 2013 12:50:29 -0800 Subject: [PATCH] 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 --- lib/checkmemoryleak.cpp | 2 +- lib/checknullpointer.cpp | 8 ++++---- lib/checkother.cpp | 4 ++-- lib/checkuninitvar.cpp | 2 +- lib/templatesimplifier.cpp | 4 ++-- lib/token.cpp | 6 +++--- lib/token.h | 15 ++++++++++----- lib/tokenize.cpp | 2 +- lib/tokenlist.cpp | 2 +- test/testtoken.cpp | 30 +++++++++++++++++++++++++++++- 10 files changed, 54 insertions(+), 21 deletions(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index acc666f05..e2b451a90 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -1079,7 +1079,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::listvarId() && extravar.find(tok2->varId()) != extravar.end()) { dep = true; - } else if (tok2->varId() == varid && tok2->next()->isOp()) + } else if (tok2->varId() == varid && tok2->next()->isConstOp()) dep = true; } diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 16a8d9154..f073b3728 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -324,7 +324,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown) unknown = false; // 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; // read/write member variable @@ -1129,7 +1129,7 @@ void CheckNullPointer::nullConstantDereference() tok = tok->next()->link(); 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); } } @@ -1406,8 +1406,8 @@ private: if (Token::Match(tok.previous(), "[;{}=] %var% = 0 ;")) setnull(checks, tok.varId()); else if (!deref && - (!tok.previous()->isOp() || tok.previous()->str() == "&") && !tok.previous()->isAssignmentOp() && - (!tok.next()->isOp() || tok.next()->str() == ">>")) + (!tok.previous()->isOp() || tok.previous()->str() == "&") && + (!tok.next()->isConstOp() || tok.next()->str() == ">>")) bailOutVar(checks, tok.varId()); // If its possible that the pointers value changes, bail out. } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index f29476149..015607f79 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -389,7 +389,7 @@ void CheckOther::checkBitwiseOnBoolean() bitwiseOnBooleanError(tok->next(), var->name(), tok->strAt(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(); if (var && var->typeEndToken()->str() == "bool") { bitwiseOnBooleanError(tok->next(), var->name(), tok->str() == "&" ? "&&" : "||"); @@ -3526,7 +3526,7 @@ void CheckOther::sizeofCalculation() if (Token::simpleMatch(tok, "sizeof (")) { const Token* const end = tok->linkAt(1); 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%"))) { sizeofCalculationError(tok2, tok2->isExpandedMacro()); break; diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 95df4105d..46cb5d3d6 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1530,7 +1530,7 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool cpp // is there something like: ; "*((&var ..expr.. =" => the variable is assigned if (vartok->previous()->str() == "&") { const Token *tok2 = vartok->tokAt(-2); - if (tok2 && (tok2->isOp() || tok2->str() == "(")) + if (tok2 && (tok2->isConstOp() || tok2->str() == "(")) return false; // address of if (Token::simpleMatch(tok2,")")) tok2 = tok2->link()->previous(); diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 7ad8bc724..d7580a93b 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -895,7 +895,7 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens) } 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->deleteNext(); tok->deleteThis(); @@ -916,7 +916,7 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens) Token::simpleMatch(tok->previous(), "| 0 )") || Token::simpleMatch(tok->previous(), "( 1 &&") || Token::simpleMatch(tok->previous(), "&& 1 )")) { - if (tok->previous()->isOp()) + if (tok->previous()->isConstOp()) tok = tok->previous(); tok->deleteNext(); tok->deleteThis(); diff --git a/lib/token.cpp b/lib/token.cpp index 954df51eb..bb49749e5 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -312,7 +312,7 @@ static int multiComparePercent(const Token *tok, const char * * haystack_p, if (haystack[1] == 'o' && // "%op%" haystack[2] == 'p' && haystack[3] == '%') { - if (tok->isOp()) + if (tok->isConstOp()) return 1; *haystack_p = haystack = haystack + 4; } 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[4] == '|') { haystack = haystack + 5; - if (tok->isOp()) + if (tok->isConstOp()) return 1; } else if (haystack[2] == 'r' && // "%or%|" haystack[3] == '%' && @@ -627,7 +627,7 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid) // Op (%op%) if (p[0] == 'p') { p += 2; - multicompare(p,tok->isOp(),ismulticomp); + multicompare(p,tok->isConstOp(),ismulticomp); } // Or (%or%) else { diff --git a/lib/token.h b/lib/token.h index d61c16836..fed3d07f9 100644 --- a/lib/token.h +++ b/lib/token.h @@ -135,7 +135,7 @@ public: * - "%comp%" Any token such that isComparisonOp() returns true. * - "%str%" Any token starting with "-character (C-string). * - "%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 '|' * - "%oror%" A logical-or operator '||' * - "[abc]" Any of the characters 'a' or 'b' or 'c' @@ -204,19 +204,24 @@ public: bool isNumber() const { return _type == eNumber; } - bool isArithmeticalOp() const { - return _type == eArithmeticalOp; - } bool isOp() const { + return (isConstOp() || + isAssignmentOp() || + _type == eIncDecOp); + } + bool isConstOp() const { return (isArithmeticalOp() || _type == eLogicalOp || _type == eComparisonOp || _type == eBitOp); } bool isExtendedOp() const { - return isOp() || + return isConstOp() || _type == eExtendedOp; } + bool isArithmeticalOp() const { + return _type == eArithmeticalOp; + } bool isComparisonOp() const { return _type == eComparisonOp; } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index a94473082..b6cfcc012 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -4214,7 +4214,7 @@ void Tokenizer::simplifyCompoundAssignment() break; } - someOperator |= (tok2->isOp() || (tok2->str() == "?") || tok2->isAssignmentOp()); + someOperator |= (tok2->isOp() || tok2->str() == "?"); } } diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index b2bf03295..9ec11e827 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -393,7 +393,7 @@ void TokenList::createAst() const std::string op(operators[i]); for (Token *tok = _front; tok; tok = tok->next()) { 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->astOperand2(tok->next()); } else if (tok->previous() && !tok->previous()->isOp()) { diff --git a/test/testtoken.cpp b/test/testtoken.cpp index 393bde526..f31512cdf 100644 --- a/test/testtoken.cpp +++ b/test/testtoken.cpp @@ -68,6 +68,7 @@ private: TEST_CASE(isArithmeticalOp); TEST_CASE(isOp); + TEST_CASE(isConstOp); TEST_CASE(isExtendedOp); TEST_CASE(isAssignmentOp); TEST_CASE(isStandardType); @@ -569,6 +570,7 @@ private: append_vector(test_ops, bitOps); append_vector(test_ops, comparisonOps); append_vector(test_ops, logicalOps); + append_vector(test_ops, assignmentOps); std::vector::const_iterator test_op, test_ops_end = test_ops.end(); for (test_op = test_ops.begin(); test_op != test_ops_end; ++test_op) { @@ -580,7 +582,6 @@ private: // Negative test against other operators std::vector other_ops; append_vector(other_ops, extendedOps); - append_vector(other_ops, assignmentOps); std::vector::const_iterator other_op, other_ops_end = other_ops.end(); for (other_op = other_ops.begin(); other_op != other_ops_end; ++other_op) { @@ -590,6 +591,33 @@ private: } } + void isConstOp() { + std::vector test_ops; + append_vector(test_ops, arithmeticalOps); + append_vector(test_ops, bitOps); + append_vector(test_ops, comparisonOps); + append_vector(test_ops, logicalOps); + + std::vector::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 other_ops; + append_vector(other_ops, extendedOps); + append_vector(other_ops, assignmentOps); + + std::vector::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() { std::vector test_ops; append_vector(test_ops, arithmeticalOps);