Refactorization:
- Implemented consistent behaviour of Variable::typeStartToken/typeEndToken: Skip const and static on all variables. - Simplified patterns containing "static|" or "const|" when matching typeStartToken.
This commit is contained in:
parent
69846b2a06
commit
c463d97386
|
@ -306,14 +306,14 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Sym
|
||||||
return true;
|
return true;
|
||||||
if (Token::Match(tok->tokAt(-2), "%var% ( %var% )")) {
|
if (Token::Match(tok->tokAt(-2), "%var% ( %var% )")) {
|
||||||
const Variable* var = symbolDatabase->getVariableFromVarId(tok->tokAt(-2)->varId());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// streams dereference nullpointers
|
// streams dereference nullpointers
|
||||||
if (Token::Match(tok->previous(), "<<|>> %var%")) {
|
if (Token::Match(tok->previous(), "<<|>> %var%")) {
|
||||||
const Variable* var = symbolDatabase->getVariableFromVarId(tok->varId());
|
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
|
const Token* tok2 = tok->previous(); // Find start of statement
|
||||||
for (; tok2; tok2 = tok2->previous()) {
|
for (; tok2; tok2 = tok2->previous()) {
|
||||||
if (Token::Match(tok2->previous(), ";|{|}|:"))
|
if (Token::Match(tok2->previous(), ";|{|}|:"))
|
||||||
|
@ -323,7 +323,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Sym
|
||||||
return true;
|
return true;
|
||||||
if (tok2 && tok2->varId() != 0) {
|
if (tok2 && tok2->varId() != 0) {
|
||||||
const Variable* var2 = symbolDatabase->getVariableFromVarId(tok2->varId());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,7 +338,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Sym
|
||||||
ovarid = tok->tokAt(-2)->varId();
|
ovarid = tok->tokAt(-2)->varId();
|
||||||
if (ovarid) {
|
if (ovarid) {
|
||||||
const Variable* var = symbolDatabase->getVariableFromVarId(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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1152,7 +1152,7 @@ void CheckNullPointer::nullConstantDereference()
|
||||||
else if (Token::Match(tok->previous(), "!!. %var% (") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) {
|
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
|
if (Token::simpleMatch(tok->tokAt(2), "0 )") && tok->varId()) { // constructor call
|
||||||
const Variable* var = symbolDatabase->getVariableFromVarId(tok->varId());
|
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);
|
nullPointerError(tok);
|
||||||
} else { // function call
|
} else { // function call
|
||||||
std::list<const Token *> var;
|
std::list<const Token *> var;
|
||||||
|
@ -1178,7 +1178,7 @@ void CheckNullPointer::nullConstantDereference()
|
||||||
nullPointerError(tok);
|
nullPointerError(tok);
|
||||||
if (tok2 && tok2->varId() != 0) {
|
if (tok2 && tok2->varId() != 0) {
|
||||||
const Variable* var = symbolDatabase->getVariableFromVarId(tok2->varId());
|
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);
|
nullPointerError(tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1192,7 +1192,7 @@ void CheckNullPointer::nullConstantDereference()
|
||||||
ovarid = tok->varId();
|
ovarid = tok->varId();
|
||||||
if (ovarid) {
|
if (ovarid) {
|
||||||
const Variable* var = symbolDatabase->getVariableFromVarId(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);
|
nullPointerError(tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1719,7 +1719,7 @@ void CheckOther::checkConstantFunctionParameter()
|
||||||
if (!var || !var->isArgument() || !var->isClass() || !var->isConst() || var->isPointer() || var->isArray() || var->isReference())
|
if (!var || !var->isArgument() || !var->isClass() || !var->isConst() || var->isPointer() || var->isArray() || var->isReference())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Token* tok = var->typeStartToken()->next();
|
const Token* const tok = var->typeStartToken();
|
||||||
// TODO: False negatives. This pattern only checks for string.
|
// TODO: False negatives. This pattern only checks for string.
|
||||||
// Investigate if there are other classes in the std
|
// Investigate if there are other classes in the std
|
||||||
// namespace and add them to the pattern. There are
|
// 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)
|
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)
|
static bool isSignedChar(const Variable* var)
|
||||||
|
@ -1788,13 +1788,13 @@ void CheckOther::checkCharVariable()
|
||||||
|
|
||||||
// is the result stored in a short|int|long?
|
// is the result stored in a short|int|long?
|
||||||
const Variable *var = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
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..
|
charBitOpError(tok->tokAt(4)); // This is an error..
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::Match(tok, "[;{}] %var% = %any% [&^|] ( * %var% ) ;")) {
|
else if (Token::Match(tok, "[;{}] %var% = %any% [&^|] ( * %var% ) ;")) {
|
||||||
const Variable* var = symbolDatabase->getVariableFromVarId(tok->tokAt(7)->varId());
|
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;
|
continue;
|
||||||
// it's ok with a bitwise and where the other operand is 0xff or less..
|
// 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)))
|
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?
|
// is the result stored in a short|int|long?
|
||||||
var = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
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..
|
charBitOpError(tok->tokAt(4)); // This is an error..
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ void CheckPostfixOperator::postfixOperator()
|
||||||
|
|
||||||
if (result && tok->previous()->varId()) {
|
if (result && tok->previous()->varId()) {
|
||||||
const Variable *var = symbolDatabase->getVariableFromVarId(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;
|
continue;
|
||||||
|
|
||||||
const Token *decltok = var->nameToken();
|
const Token *decltok = var->nameToken();
|
||||||
|
|
|
@ -858,6 +858,11 @@ void Variable::evaluate()
|
||||||
tok = tok->next();
|
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)
|
if (_name)
|
||||||
setFlag(fIsArray, arrayDimensions(_dimensions, _name->next()));
|
setFlag(fIsArray, arrayDimensions(_dimensions, _name->next()));
|
||||||
if (_start)
|
if (_start)
|
||||||
|
|
|
@ -108,6 +108,8 @@ private:
|
||||||
TEST_CASE(hasGlobalVariables2);
|
TEST_CASE(hasGlobalVariables2);
|
||||||
TEST_CASE(hasGlobalVariables3);
|
TEST_CASE(hasGlobalVariables3);
|
||||||
|
|
||||||
|
TEST_CASE(checkTypeStartEndToken);
|
||||||
|
|
||||||
TEST_CASE(functionArgs1);
|
TEST_CASE(functionArgs1);
|
||||||
TEST_CASE(functionArgs2);
|
TEST_CASE(functionArgs2);
|
||||||
TEST_CASE(functionArgs3);
|
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) {
|
void check(const char code[], bool debug = true) {
|
||||||
// Clear the error log
|
// Clear the error log
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
Loading…
Reference in New Issue