Merge branch 'master' of github.com:danmar/cppcheck

This commit is contained in:
Kimmo Varis 2010-09-10 17:44:02 +03:00
commit df4eec714c
5 changed files with 164 additions and 29 deletions

View File

@ -385,6 +385,8 @@ void CheckClass::createSymbolDatabase()
else
classPattern = "operator " + func->tokenDef->str() + " (";
}
else if (func->type == Func::Destructor)
classPattern = "~ " + func->tokenDef->str() + " (";
else
classPattern = func->tokenDef->str() + " (";
@ -821,7 +823,7 @@ void CheckClass::SpaceInfo::initializeVarList(const Func &func, std::list<std::s
{
if (Assign && Token::Match(ftok, "%var% ("))
{
initVar(ftok->strAt(0));
initVar(ftok->str());
// assignment in the initializer..
// : var(value = x)
@ -986,7 +988,7 @@ void CheckClass::SpaceInfo::initializeVarList(const Func &func, std::list<std::s
}
if (tok->isName())
{
assignVar(tok->strAt(0));
assignVar(tok->str());
}
}
}
@ -996,37 +998,37 @@ void CheckClass::SpaceInfo::initializeVarList(const Func &func, std::list<std::s
// Assignment of member variable?
else if (Token::Match(ftok, "%var% ="))
{
assignVar(ftok->strAt(0));
assignVar(ftok->str());
}
// Assignment of array item of member variable?
else if (Token::Match(ftok, "%var% [ %any% ] ="))
{
assignVar(ftok->strAt(0));
assignVar(ftok->str());
}
// Assignment of array item of member variable?
else if (Token::Match(ftok, "%var% [ %any% ] [ %any% ] ="))
{
assignVar(ftok->strAt(0));
assignVar(ftok->str());
}
// Assignment of array item of member variable?
else if (Token::Match(ftok, "* %var% ="))
{
assignVar(ftok->strAt(1));
assignVar(ftok->next()->str());
}
// Assignment of struct member of member variable?
else if (Token::Match(ftok, "%var% . %any% ="))
{
assignVar(ftok->strAt(0));
assignVar(ftok->str());
}
// The functions 'clear' and 'Clear' are supposed to initialize variable.
if (Token::Match(ftok, "%var% . clear|Clear ("))
{
assignVar(ftok->strAt(0));
assignVar(ftok->str());
}
}
}
@ -1762,7 +1764,7 @@ void CheckClass::virtualDestructor()
continue;
// Empty destructor
if (destructor->tokenDef->tokAt(3)->link() == destructor->tokenDef->tokAt(4))
if (destructor->token->tokAt(3)->link() == destructor->token->tokAt(4))
continue;
const Token *derived = info->classDef;

View File

@ -2042,6 +2042,9 @@ bool Tokenizer::tokenize(std::istream &code,
// Split up variable declarations.
simplifyVarDecl();
// f(x=g()) => x=g(); f(x)
simplifyAssignmentInFunctionCall();
simplifyVariableMultipleAssign();
// Remove redundant parantheses
@ -5250,6 +5253,8 @@ void Tokenizer::simplifyStdType()
void Tokenizer::simplifyIfAssign()
{
// See also simplifyFunctionAssign
for (Token *tok = _tokens; tok; tok = tok->next())
{
if (!Token::Match(tok->next(), "if|while ( !| (| %var% =") &&
@ -5546,31 +5551,51 @@ bool Tokenizer::simplifyLogicalOperators()
// "if (p or q)" => "if (p || q)"
for (Token *tok = _tokens; tok; tok = tok->next())
{
if (Token::Match(tok, "if|while ( not %var%"))
if (Token::Match(tok, "if|while ( not|compl %var%"))
{
tok->tokAt(2)->str("!");
tok->tokAt(2)->str(tok->strAt(2) == "not" ? "!" : "~");
ret = true;
}
else if (Token::Match(tok, "&& not %var%"))
else if (Token::Match(tok, "&& not|compl %var%"))
{
tok->next()->str("!");
tok->next()->str(tok->strAt(1) == "not" ? "!" : "~");
ret = true;
}
else if (Token::Match(tok, "|| not %var%"))
else if (Token::Match(tok, "|| not|compl %var%"))
{
tok->next()->str("!");
tok->next()->str(tok->strAt(1) == "not" ? "!" : "~");
ret = true;
}
// "%var%|) and %var%|("
else if (Token::Match(tok->previous(), "%any% and|or %any%") &&
((tok->previous()->isName() || tok->previous()->str() == ")") ||
(tok->next()->isName() || tok->next()->str() == "(")))
else if (Token::Match(tok->previous(), "%any% %var% %any%"))
{
if (tok->str() == "and")
tok->str("&&");
else
tok->str("||");
ret = true;
if (!Token::Match(tok, "and|or|bitand|bitor|xor|not_eq"))
continue;
const Token *tok2 = tok;
while (0 != (tok2 = tok2->previous()))
{
if (tok2->str() == ")")
tok2 = tok2->link();
else if (Token::Match(tok2, "(|;|{|}"))
break;
}
if (tok2 && Token::Match(tok2->previous(), "if|while ("))
{
if (tok->str() == "and")
tok->str("&&");
else if (tok->str() == "or")
tok->str("||");
else if (tok->str() == "bitand")
tok->str("&");
else if (tok->str() == "bitor")
tok->str("|");
else if (tok->str() == "xor")
tok->str("^");
else if (tok->str() == "not_eq")
tok->str("!=");
ret = true;
}
}
}
return ret;
@ -8089,6 +8114,40 @@ void Tokenizer::simplifyStructDecl()
// unnamed anonymous struct/union so remove it
else if (tok->next()->str() == ";")
{
if (tok1->str() == "union")
{
// Try to create references in the union..
Token *tok2 = tok1->tokAt(2);
while (tok2)
{
if (Token::Match(tok2, "%type% %var% ;"))
tok2 = tok2->tokAt(3);
else
break;
}
if (!Token::simpleMatch(tok2, "} ;"))
continue;
Token *vartok = 0;
tok2 = tok1->tokAt(2);
while (Token::Match(tok2, "%type% %var% ;"))
{
if (!vartok)
{
vartok = tok2->next();
tok2 = tok2->tokAt(3);
}
else
{
tok2->insertToken("&");
tok2 = tok2->tokAt(2);
tok2->insertToken(vartok->str());
tok2->next()->varId(vartok->varId());
tok2->insertToken("=");
tok2 = tok2->tokAt(4);
}
}
}
tok1->deleteThis();
if (tok1->next() == tok)
{
@ -8197,6 +8256,45 @@ void Tokenizer::simplifyKeyword()
}
}
void Tokenizer::simplifyAssignmentInFunctionCall()
{
for (Token *tok = _tokens; tok; tok = tok->next())
{
if (tok->str() == "(")
tok = tok->link();
else if (Token::Match(tok, "[;{}] %var% ( %var% =") && Token::simpleMatch(tok->tokAt(2)->link(), ") ;"))
{
const std::string funcname(tok->strAt(1));
const Token * const vartok = tok->tokAt(3);
// Goto ',' or ')'..
for (Token *tok2 = tok->tokAt(4); tok2; tok2 = tok2->next())
{
if (tok2->str() == "(")
tok2 = tok2->link();
else if (tok2->str() == ";")
break;
else if (tok2->str() == ")" || tok2->str() == ",")
{
tok2 = tok2->previous();
tok2->insertToken(vartok->str());
tok2->next()->varId(vartok->varId());
tok2->insertToken("(");
Token::createMutualLinks(tok2->next(), tok->tokAt(2)->link());
tok2->insertToken(funcname);
tok2->insertToken(";");
Token::eraseTokens(tok, vartok);
break;
}
}
}
}
}
// Remove __asm..
void Tokenizer::simplifyAsm()
{

View File

@ -136,6 +136,10 @@ public:
*/
std::map<std::string, ClassInfo> _classInfoList;
/** Simplify assignment in function call "f(x=g());" => "x=g();f(x);"
*/
void simplifyAssignmentInFunctionCall();
/**
* Simplify constant calculations such as "1+2" => "3"
* @return true if modifications to token-list are done.

View File

@ -259,6 +259,11 @@ private:
TEST_CASE(borland);
TEST_CASE(sql);
TEST_CASE(simplifyLogicalOperators);
// foo(p = new char[10]); => p = new char[10]; foo(p);
simplifyAssignmentInFunctionCall();
}
@ -3433,6 +3438,15 @@ private:
// ticket #1976
const char code1[] = "class Fred { public: union { int a ; int b ; } ; } ;";
ASSERT_EQUALS(code1, tokenizeAndStringify(code1));
// ticket #2039
const char code2[] = "void f() {\n"
" union {\n"
" int x;\n"
" long y;\n"
" };\n"
"}";
ASSERT_EQUALS("void f ( ) {\n\nint x ;\nlong & y = x ;\n\n}", tokenizeAndStringify(code2));
}
void vardec_static()
@ -4541,6 +4555,23 @@ private:
ASSERT_EQUALS("; asm ( ) ;", tokenizeAndStringify(code1,false));
}
void simplifyLogicalOperators()
{
ASSERT_EQUALS("if ( a && b )", tokenizeAndStringify("if (a and b)"));
ASSERT_EQUALS("if ( a || b )", tokenizeAndStringify("if (a or b)"));
ASSERT_EQUALS("if ( a & b )", tokenizeAndStringify("if (a bitand b)"));
ASSERT_EQUALS("if ( a | b )", tokenizeAndStringify("if (a bitor b)"));
ASSERT_EQUALS("if ( a ^ b )", tokenizeAndStringify("if (a xor b)"));
ASSERT_EQUALS("if ( ~ b )", tokenizeAndStringify("if (compl b)"));
ASSERT_EQUALS("if ( ! b )", tokenizeAndStringify("if (not b)"));
ASSERT_EQUALS("if ( a != b )", tokenizeAndStringify("if (a not_eq b)"));
}
void simplifyAssignmentInFunctionCall()
{
ASSERT_EQUALS("; x = g ( ) ; f ( x ) ;", tokenizeAndStringify(";f(x=g());"));
}
};
REGISTER_TEST(TestTokenizer)

View File

@ -2211,17 +2211,17 @@ private:
" func();\n"
" } while(a--);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (style) Unused variable: x\n"
"[test.cpp:4]: (style) Unused variable: z\n", errout.str());
ASSERT_EQUALS("", errout.str());
TODO_ASSERT_EQUALS("[test.cpp:4]: (style) Unused variable: x\n"
"[test.cpp:4]: (style) Unused variable: z\n", errout.str());
}
void localvarStruct4()
{
/* This must not SIGSEGV: */
// FIXME!!
//functionVariableUsage("void foo()\n"
// "{\n"
// " struct { \n");
functionVariableUsage("void foo()\n"
"{\n"
" struct { \n");
}
void localvarOp()