speed up checks by caching commonly looked up stuff in the symbol database (CheckOther). Ticket #4266

This commit is contained in:
Robert Reif 2012-11-14 18:12:33 +01:00 committed by Daniel Marjamäki
parent 6578b78077
commit 04d04c33c2
2 changed files with 450 additions and 380 deletions

View File

@ -40,8 +40,10 @@ void CheckOther::checkIncrementBoolean()
return;
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "%var% ++")) {
if (tok->varId()) {
const Variable *var = symbolDatabase->getVariableFromVarId(tok->varId());
@ -52,6 +54,7 @@ void CheckOther::checkIncrementBoolean()
}
}
}
}
void CheckOther::incrementBooleanError(const Token *tok)
{
@ -71,8 +74,12 @@ void CheckOther::clarifyCalculation()
if (!_settings->isEnabled("style"))
return;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
if (tok->str() == "?" && tok->previous()) {
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (tok->str() == "?") {
// condition
const Token *cond = tok->previous();
if (cond->isName() || cond->isNumber())
@ -118,6 +125,7 @@ void CheckOther::clarifyCalculation()
}
}
}
}
void CheckOther::clarifyCalculationError(const Token *tok, const std::string &op)
{
@ -149,7 +157,11 @@ void CheckOther::clarifyCondition()
const bool isC = _tokenizer->isC();
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "( %var% [=&|^]")) {
for (const Token *tok2 = tok->tokAt(3); tok2; tok2 = tok2->next()) {
if (tok2->str() == "(" || tok2->str() == "[")
@ -166,9 +178,12 @@ void CheckOther::clarifyCondition()
}
}
}
}
// using boolean result in bitwise operation ! x [&|^]
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "!|<|<=|==|!=|>|>=")) {
if (tok->link()) // don't write false positives when templates are used
continue;
@ -206,6 +221,7 @@ void CheckOther::clarifyCondition()
}
}
}
}
void CheckOther::clarifyConditionError(const Token *tok, bool assign, bool boolop)
{
@ -237,7 +253,11 @@ void CheckOther::clarifyStatement()
if (!_settings->isEnabled("style"))
return;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "* %var%")) {
const Token *tok2=tok->previous();
@ -264,6 +284,7 @@ void CheckOther::clarifyStatement()
}
}
}
}
void CheckOther::clarifyStatementError(const Token *tok)
{
@ -286,7 +307,11 @@ void CheckOther::checkBitwiseOnBoolean()
if (!_settings->inconclusive)
return;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "(|.|return|&&|%oror%|throw|, %var% [&|]")) {
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->next()->varId());
if (var && var->typeEndToken()->str() == "bool") {
@ -302,6 +327,7 @@ void CheckOther::checkBitwiseOnBoolean()
}
}
}
}
void CheckOther::bitwiseOnBooleanError(const Token *tok, const std::string &varname, const std::string &op)
{
@ -393,18 +419,22 @@ void CheckOther::invalidPointerCast()
if (!_settings->isEnabled("style") && !_settings->isEnabled("portability"))
return;
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
const Token* toTok = 0;
const Token* nextTok = 0;
// Find cast
if (Token::Match(tok, "( const| %type% const| * )") || Token::Match(tok, "( const| %type% %type% const| * )")) {
if (Token::Match(tok, "( const| %type% const| * )") ||
Token::Match(tok, "( const| %type% %type% const| * )")) {
toTok = tok->next();
nextTok = tok->link()->next();
if (nextTok && nextTok->str() == "(")
nextTok = nextTok->next();
} else if (Token::Match(tok, "reinterpret_cast < const| %type% const| * > (") || Token::Match(tok, "reinterpret_cast < const| %type% %type% const| * > (")) {
} else if (Token::Match(tok, "reinterpret_cast < const| %type% const| * > (") ||
Token::Match(tok, "reinterpret_cast < const| %type% %type% const| * > (")) {
nextTok = tok->tokAt(5);
while (nextTok->str() != "(")
nextTok = nextTok->next();
@ -452,6 +482,7 @@ void CheckOther::invalidPointerCast()
invalidPointerCastError(tok, fromType, toType, toTok->str() == "char");
}
}
}
void CheckOther::invalidPointerCastError(const Token* tok, const std::string& from, const std::string& to, bool inconclusive)
{
@ -471,14 +502,18 @@ void CheckOther::checkSizeofForNumericParameter()
if (!_settings->isEnabled("style"))
return;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
if (Token::Match(tok, "sizeof ( %num% )")
|| Token::Match(tok, "sizeof %num%")
) {
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "sizeof ( %num% )") ||
Token::Match(tok, "sizeof %num%")) {
sizeofForNumericParameterError(tok);
}
}
}
}
void CheckOther::sizeofForNumericParameterError(const Token *tok)
{
@ -494,9 +529,12 @@ void CheckOther::sizeofForNumericParameterError(const Token *tok)
void CheckOther::checkSizeofForArrayParameter()
{
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
if (Token::Match(tok, "sizeof ( %var% )") || Token::Match(tok, "sizeof %var% !![")) {
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "sizeof ( %var% )") ||
Token::Match(tok, "sizeof %var% !![")) {
const Token* varTok = tok->next();
if (varTok->str() == "(") {
varTok = varTok->next();
@ -510,6 +548,7 @@ void CheckOther::checkSizeofForArrayParameter()
}
}
}
}
void CheckOther::sizeofForArrayParameterError(const Token *tok)
{
@ -529,12 +568,14 @@ void CheckOther::sizeofForArrayParameterError(const Token *tok)
void CheckOther::checkSizeofForPointerSize()
{
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
if (!_settings->isEnabled("style"))
return;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
const Token *tokVar;
const Token *variable;
const Token *variable2 = 0;
@ -606,6 +647,7 @@ void CheckOther::checkSizeofForPointerSize()
}
}
}
}
void CheckOther::sizeofForPointerError(const Token *tok, const std::string &varname)
{

View File

@ -4578,11 +4578,11 @@ private:
void incrementBoolean() {
check("bool bValue = true;\n"
"bValue++;\n");
"void f() { bValue++; }\n");
ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
check("_Bool bValue = true;\n"
"bValue++;\n");
"void f() { bValue++; }\n");
ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
check("void f(bool test){\n"
@ -5253,154 +5253,182 @@ private:
}
void checkPointerSizeof() {
check(
check("void f() {\n"
" char *x = malloc(10);\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(*x));\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(int));\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(x));\n"
"free(x);");
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
" free(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(&x));\n"
"free(x);");
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
" free(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
check(
check("void f() {\n"
" int *x = malloc(100 * sizeof(x));\n"
"free(x);");
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
" free(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(x) * 100);\n"
"free(x);");
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
" free(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof *x);\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof x);\n"
"free(x);");
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
" free(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
check(
check("void f() {\n"
" int *x = malloc(100 * sizeof x);\n"
"free(x);");
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
" free(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
check(
check("void f() {\n"
" int *x = calloc(1, sizeof(*x));\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" int *x = calloc(1, sizeof *x);\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" int *x = calloc(1, sizeof(x));\n"
"free(x);");
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
" free(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
check(
check("void f() {\n"
" int *x = calloc(1, sizeof x);\n"
"free(x);");
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
" free(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
check(
check("void f() {\n"
" int *x = calloc(1, sizeof(int));\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" char x[10];\n"
"memset(x, 0, sizeof(x));");
" memset(x, 0, sizeof(x));\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" char* x[10];\n"
"memset(x, 0, sizeof(x));");
" memset(x, 0, sizeof(x));\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" char x[10];\n"
"memset(x, 0, sizeof x);");
" memset(x, 0, sizeof x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(int));\n"
" memset(x, 0, sizeof(int));\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(int));\n"
" memset(x, 0, sizeof(*x));\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(int));\n"
" memset(x, 0, sizeof *x);\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(int));\n"
" memset(x, 0, sizeof x);\n"
"free(x);");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
" free(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(int));\n"
" memset(x, 0, sizeof(x));\n"
"free(x);");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
" free(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(int) * 10);\n"
" memset(x, 0, sizeof(x) * 10);\n"
"free(x);");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
" free(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(int) * 10);\n"
" memset(x, 0, sizeof x * 10);\n"
"free(x);");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
" free(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(int) * 10);\n"
" memset(x, 0, sizeof(*x) * 10);\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(int) * 10);\n"
" memset(x, 0, sizeof *x * 10);\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
check("void f() {\n"
" int *x = malloc(sizeof(int) * 10);\n"
" memset(x, 0, sizeof(int) * 10);\n"
"free(x);");
" free(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check(