Refactorized checkautovariables.cpp. Removed indendation counters.

Fixed #3478
This commit is contained in:
PKEuS 2012-01-08 15:32:22 +01:00
parent e09b0330e4
commit c273d6d31d
2 changed files with 30 additions and 68 deletions

View File

@ -51,7 +51,7 @@ bool CheckAutoVariables::isAutoVar(unsigned int varId)
{ {
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varId); const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varId);
if (!var || !var->isLocal() || var->isStatic() || var->isArray() || var->typeEndToken()->str() == "*") if (!var || !var->isLocal() || var->isStatic() || var->isArray() || var->isPointer())
return false; return false;
if (Token::simpleMatch(var->nameToken()->previous(), "&")) { if (Token::simpleMatch(var->nameToken()->previous(), "&")) {
@ -85,17 +85,7 @@ void CheckAutoVariables::autoVariables()
if (scope->type != Scope::eFunction) if (scope->type != Scope::eFunction)
continue; continue;
unsigned int indentlevel = 0; for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
for (const Token *tok = scope->classDef->next()->link(); tok; tok = tok->next()) {
// indentlevel..
if (tok->str() == "{")
++indentlevel;
else if (tok->str() == "}") {
if (indentlevel <= 1)
break;
--indentlevel;
}
//Critical assignment //Critical assignment
if (Token::Match(tok, "[;{}] * %var% = & %var%") && errorAv(tok->tokAt(2), tok->tokAt(5))) { if (Token::Match(tok, "[;{}] * %var% = & %var%") && errorAv(tok->tokAt(2), tok->tokAt(5))) {
const Variable * var = symbolDatabase->getVariableFromVarId(tok->tokAt(5)->varId()); const Variable * var = symbolDatabase->getVariableFromVarId(tok->tokAt(5)->varId());
@ -174,24 +164,8 @@ void CheckAutoVariables::returnPointerToLocalArray()
tok = tok->tokAt(-2); tok = tok->tokAt(-2);
// have we reached a function that returns a pointer // have we reached a function that returns a pointer
if (Token::Match(tok->tokAt(-2), "%type% *")) { if (tok->previous() && tok->previous()->str() == "*") {
// go to the '(' for (const Token *tok2 = scope->classStart; tok2 && tok2 != scope->classEnd; tok2 = tok2->next()) {
const Token *tok2 = scope->classDef->next();
// go to the ')'
tok2 = tok2->next()->link();
unsigned int indentlevel = 0;
for (; tok2; tok2 = tok2->next()) {
// indentlevel..
if (tok2->str() == "{")
++indentlevel;
else if (tok2->str() == "}") {
if (indentlevel <= 1)
break;
--indentlevel;
}
// Return pointer to local array variable.. // Return pointer to local array variable..
if (Token::Match(tok2, "return %var% ;")) { if (Token::Match(tok2, "return %var% ;")) {
const unsigned int varid = tok2->next()->varId(); const unsigned int varid = tok2->next()->varId();
@ -273,25 +247,8 @@ void CheckAutoVariables::returnReference()
tok = tok->tokAt(-2); tok = tok->tokAt(-2);
// have we reached a function that returns a reference? // have we reached a function that returns a reference?
if (Token::Match(tok->tokAt(-2), "%type% &") || if (tok->previous() && tok->previous()->str() == "&") {
Token::simpleMatch(tok->tokAt(-2), "> &")) { for (const Token *tok2 = scope->classStart; tok2 && tok2 != scope->classEnd; tok2 = tok2->next()) {
// go to the '('
const Token *tok2 = scope->classDef->next();
// go to the ')'
tok2 = tok2->link();
unsigned int indentlevel = 0;
for (; tok2; tok2 = tok2->next()) {
// indentlevel..
if (tok2->str() == "{")
++indentlevel;
else if (tok2->str() == "}") {
if (indentlevel <= 1)
break;
--indentlevel;
}
// return.. // return..
if (Token::Match(tok2, "return %var% ;")) { if (Token::Match(tok2, "return %var% ;")) {
// is the returned variable a local variable? // is the returned variable a local variable?
@ -300,7 +257,7 @@ void CheckAutoVariables::returnReference()
if (var1 && var1->isLocal() && !var1->isStatic()) { if (var1 && var1->isLocal() && !var1->isStatic()) {
// If reference variable is used, check what it references // If reference variable is used, check what it references
if (Token::Match(var1->nameToken()->previous(), "& %var% =")) { if (Token::Match(var1->nameToken(), "%var% =")) {
const Token *tok3 = var1->nameToken()->tokAt(2); const Token *tok3 = var1->nameToken()->tokAt(2);
if (!Token::Match(tok3, "%var% [;.]")) if (!Token::Match(tok3, "%var% [;.]"))
continue; continue;
@ -308,7 +265,7 @@ void CheckAutoVariables::returnReference()
// Only report error if variable that is referenced is // Only report error if variable that is referenced is
// a auto variable // a auto variable
const Variable *var2 = symbolDatabase->getVariableFromVarId(tok3->varId()); const Variable *var2 = symbolDatabase->getVariableFromVarId(tok3->varId());
if (!var2 || !var2->isLocal() || var2->isStatic()) if (!var2 || !var2->isLocal() || var2->isStatic() || (var2->isPointer() && tok3->strAt(1) == "."))
continue; continue;
} }
@ -371,23 +328,7 @@ void CheckAutoVariables::returncstr()
// have we reached a function that returns a const char * // have we reached a function that returns a const char *
if (Token::simpleMatch(tok->tokAt(-3), "const char *")) { if (Token::simpleMatch(tok->tokAt(-3), "const char *")) {
// go to the '(' for (const Token *tok2 = scope->classStart; tok2 && tok2 != scope->classEnd; tok2 = tok2->next()) {
const Token *tok2 = scope->classDef->next();
// go to the ')'
tok2 = tok2->next()->link();
unsigned int indentlevel = 0;
for (; tok2; tok2 = tok2->next()) {
// indentlevel..
if (tok2->str() == "{")
++indentlevel;
else if (tok2->str() == "}") {
if (indentlevel <= 1)
break;
--indentlevel;
}
// return.. // return..
if (Token::Match(tok2, "return %var% . c_str ( ) ;")) { if (Token::Match(tok2, "return %var% . c_str ( ) ;")) {
// is the returned variable a local variable? // is the returned variable a local variable?

View File

@ -84,6 +84,7 @@ private:
TEST_CASE(returnReference2); TEST_CASE(returnReference2);
TEST_CASE(returnReference3); TEST_CASE(returnReference3);
TEST_CASE(returnReference4); TEST_CASE(returnReference4);
TEST_CASE(returnReference5);
// return c_str().. // return c_str()..
TEST_CASE(returncstr1); TEST_CASE(returncstr1);
@ -477,6 +478,26 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void returnReference5() {
check("struct A {\n"
" int i;\n"
"};\n"
"struct B {\n"
" A a;\n"
"};\n"
"struct C {\n"
" B *b;\n"
" const A& a() const {\n"
" const B *pb = b;\n"
" const A &ra = pb->a;\n"
" return ra;\n"
" }\n"
"};");
ASSERT_EQUALS("", errout.str());
}
void returncstr1() { void returncstr1() {
check("const char *foo()\n" check("const char *foo()\n"
"{\n" "{\n"