From c463d97386713a3657c001c4314fbb7f69ce9121 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Fri, 8 Jun 2012 09:05:02 -0700 Subject: [PATCH] Refactorization: - Implemented consistent behaviour of Variable::typeStartToken/typeEndToken: Skip const and static on all variables. - Simplified patterns containing "static|" or "const|" when matching typeStartToken. --- lib/checknullpointer.cpp | 14 +++++++------- lib/checkother.cpp | 10 +++++----- lib/checkpostfixoperator.cpp | 2 +- lib/symboldatabase.cpp | 5 +++++ test/testsymboldatabase.cpp | 25 +++++++++++++++++++++++++ 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index e3cbb9cac..56e328b87 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -306,14 +306,14 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Sym return true; if (Token::Match(tok->tokAt(-2), "%var% ( %var% )")) { const Variable* var = symbolDatabase->getVariableFromVarId(tok->tokAt(-2)->varId()); - if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "const| std :: string !!::")) + if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string !!::")) return true; } // streams dereference nullpointers if (Token::Match(tok->previous(), "<<|>> %var%")) { const Variable* var = symbolDatabase->getVariableFromVarId(tok->varId()); - if (var && Token::Match(var->typeStartToken(), "const| char const| *")) { // Only outputing or reading to char* can cause problems + if (var && var->isPointer() && var->typeStartToken()->str() == "char") { // Only outputing or reading to char* can cause problems const Token* tok2 = tok->previous(); // Find start of statement for (; tok2; tok2 = tok2->previous()) { if (Token::Match(tok2->previous(), ";|{|}|:")) @@ -323,7 +323,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Sym return true; if (tok2 && tok2->varId() != 0) { const Variable* var2 = symbolDatabase->getVariableFromVarId(tok2->varId()); - if (var2 && Token::Match(var2->typeStartToken(), "const| std :: istream|ifstream|istringstream|ostream|ofstream|ostringstream|stringstream|fstream|iostream")) + if (var2 && Token::Match(var2->typeStartToken(), "std :: istream|ifstream|istringstream|ostream|ofstream|ostringstream|stringstream|fstream|iostream")) return true; } } @@ -338,7 +338,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Sym ovarid = tok->tokAt(-2)->varId(); if (ovarid) { const Variable* var = symbolDatabase->getVariableFromVarId(ovarid); - if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "const| std :: string !!::")) + if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string !!::")) return true; } @@ -1152,7 +1152,7 @@ void CheckNullPointer::nullConstantDereference() else if (Token::Match(tok->previous(), "!!. %var% (") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) { if (Token::simpleMatch(tok->tokAt(2), "0 )") && tok->varId()) { // constructor call const Variable* var = symbolDatabase->getVariableFromVarId(tok->varId()); - if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "const| std :: string !!::")) + if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string !!::")) nullPointerError(tok); } else { // function call std::list var; @@ -1178,7 +1178,7 @@ void CheckNullPointer::nullConstantDereference() nullPointerError(tok); if (tok2 && tok2->varId() != 0) { const Variable* var = symbolDatabase->getVariableFromVarId(tok2->varId()); - if (var && Token::Match(var->typeStartToken(), "const| std :: istream|ifstream|istringstream|stringstream|fstream|iostream")) + if (var && Token::Match(var->typeStartToken(), "std :: istream|ifstream|istringstream|stringstream|fstream|iostream")) nullPointerError(tok); } } @@ -1192,7 +1192,7 @@ void CheckNullPointer::nullConstantDereference() ovarid = tok->varId(); if (ovarid) { const Variable* var = symbolDatabase->getVariableFromVarId(ovarid); - if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "const| std :: string !!::")) + if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string !!::")) nullPointerError(tok); } } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 63a728fe8..7cc6e5ad4 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1719,7 +1719,7 @@ void CheckOther::checkConstantFunctionParameter() if (!var || !var->isArgument() || !var->isClass() || !var->isConst() || var->isPointer() || var->isArray() || var->isReference()) continue; - const Token* tok = var->typeStartToken()->next(); + const Token* const tok = var->typeStartToken(); // TODO: False negatives. This pattern only checks for string. // Investigate if there are other classes in the std // namespace and add them to the pattern. There are @@ -1748,7 +1748,7 @@ void CheckOther::passedByValueError(const Token *tok, const std::string &parname //--------------------------------------------------------------------------- static bool isChar(const Variable* var) { - return(var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "static| const| char")); + return(var && !var->isPointer() && !var->isArray() && var->typeStartToken()->str() == "char"); } static bool isSignedChar(const Variable* var) @@ -1788,13 +1788,13 @@ void CheckOther::checkCharVariable() // is the result stored in a short|int|long? const Variable *var = symbolDatabase->getVariableFromVarId(tok->next()->varId()); - if (var && Token::Match(var->typeStartToken(), "static| const| short|int|long") && !var->isPointer() && !var->isArray()) + if (var && Token::Match(var->typeStartToken(), "short|int|long") && !var->isPointer() && !var->isArray()) charBitOpError(tok->tokAt(4)); // This is an error.. } else if (Token::Match(tok, "[;{}] %var% = %any% [&^|] ( * %var% ) ;")) { const Variable* var = symbolDatabase->getVariableFromVarId(tok->tokAt(7)->varId()); - if (!var || !var->isPointer() || !Token::Match(var->typeStartToken(), "static| const| char")) + if (!var || !var->isPointer() || var->typeStartToken()->str() != "char") continue; // it's ok with a bitwise and where the other operand is 0xff or less.. if (tok->strAt(4) == "&" && tok->tokAt(3)->isNumber() && MathLib::isGreater("0x100", tok->strAt(3))) @@ -1802,7 +1802,7 @@ void CheckOther::checkCharVariable() // is the result stored in a short|int|long? var = symbolDatabase->getVariableFromVarId(tok->next()->varId()); - if (var && Token::Match(var->typeStartToken(), "static| const| short|int|long") && !var->isPointer() && !var->isArray()) + if (var && Token::Match(var->typeStartToken(), "short|int|long") && !var->isPointer() && !var->isArray()) charBitOpError(tok->tokAt(4)); // This is an error.. } } diff --git a/lib/checkpostfixoperator.cpp b/lib/checkpostfixoperator.cpp index eabf5cc11..5782fb1e5 100644 --- a/lib/checkpostfixoperator.cpp +++ b/lib/checkpostfixoperator.cpp @@ -65,7 +65,7 @@ void CheckPostfixOperator::postfixOperator() if (result && tok->previous()->varId()) { const Variable *var = symbolDatabase->getVariableFromVarId(tok->previous()->varId()); - if (!var || !Token::Match(var->typeEndToken(), "%type%")) + if (!var || var->isPointer() || var->isArray() || var->isReference()) continue; const Token *decltok = var->nameToken(); diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 34c02870a..67aaf1c4d 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -858,6 +858,11 @@ void Variable::evaluate() tok = tok->next(); } + while (_start && _start->next() && (_start->str() == "static" || _start->str() == "const")) + _start = _start->next(); + while (_end && _end->previous() && _end->str() == "const") + _end = _end->previous(); + if (_name) setFlag(fIsArray, arrayDimensions(_dimensions, _name->next())); if (_start) diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 5d8da391d..329e99282 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -108,6 +108,8 @@ private: TEST_CASE(hasGlobalVariables2); TEST_CASE(hasGlobalVariables3); + TEST_CASE(checkTypeStartEndToken); + TEST_CASE(functionArgs1); TEST_CASE(functionArgs2); TEST_CASE(functionArgs3); @@ -746,6 +748,29 @@ private: } } + void checkTypeStartEndToken() { + GET_SYMBOL_DB("static std::string i;\n" + "static const std::string j;\n" + "const std::string* k;\n" + "const char m[];\n" + "void f(const char* const l;) {}"); + + ASSERT(db && db->getVariableListSize() == 6 && db->getVariableFromVarId(1) && db->getVariableFromVarId(2) && db->getVariableFromVarId(3) && db->getVariableFromVarId(4) && db->getVariableFromVarId(5)); + if (db && db->getVariableFromVarId(1) && db->getVariableFromVarId(2) && db->getVariableFromVarId(3) && db->getVariableFromVarId(4) && db->getVariableFromVarId(5)) { + ASSERT_EQUALS("std", db->getVariableFromVarId(1)->typeStartToken()->str()); + ASSERT_EQUALS("std", db->getVariableFromVarId(2)->typeStartToken()->str()); + ASSERT_EQUALS("std", db->getVariableFromVarId(3)->typeStartToken()->str()); + ASSERT_EQUALS("char", db->getVariableFromVarId(4)->typeStartToken()->str()); + ASSERT_EQUALS("char", db->getVariableFromVarId(5)->typeStartToken()->str()); + + ASSERT_EQUALS("string", db->getVariableFromVarId(1)->typeEndToken()->str()); + ASSERT_EQUALS("string", db->getVariableFromVarId(2)->typeEndToken()->str()); + ASSERT_EQUALS("*", db->getVariableFromVarId(3)->typeEndToken()->str()); + ASSERT_EQUALS("char", db->getVariableFromVarId(4)->typeEndToken()->str()); + ASSERT_EQUALS("*", db->getVariableFromVarId(5)->typeEndToken()->str()); + } + } + void check(const char code[], bool debug = true) { // Clear the error log errout.str("");