Merge branch 'master' of github.com:danmar/cppcheck
This commit is contained in:
commit
df4eec714c
|
@ -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;
|
||||
|
|
126
lib/tokenize.cpp
126
lib/tokenize.cpp
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue