This commit is contained in:
Sebastien Debrard 2011-03-19 13:03:38 +01:00
commit 2e99f2cc83
7 changed files with 222 additions and 36 deletions

View File

@ -33,7 +33,16 @@
<Unit filename="cli/cmdlineparser.h" />
<Unit filename="cli/cppcheckexecutor.cpp" />
<Unit filename="cli/cppcheckexecutor.h" />
<Unit filename="cli/filelister.cpp" />
<Unit filename="cli/filelister.h" />
<Unit filename="cli/filelister_unix.cpp" />
<Unit filename="cli/filelister_unix.h" />
<Unit filename="cli/filelister_win32.cpp" />
<Unit filename="cli/filelister_win32.h" />
<Unit filename="cli/main.cpp" />
<Unit filename="cli/pathmatch.cpp" />
<Unit filename="cli/pathmatch.h" />
<Unit filename="cli/resource.h" />
<Unit filename="cli/threadexecutor.cpp" />
<Unit filename="cli/threadexecutor.h" />
<Unit filename="gui/aboutdialog.cpp" />
@ -42,6 +51,8 @@
<Unit filename="gui/applicationdialog.h" />
<Unit filename="gui/applicationlist.cpp" />
<Unit filename="gui/applicationlist.h" />
<Unit filename="gui/checkstatistics.cpp" />
<Unit filename="gui/checkstatistics.h" />
<Unit filename="gui/checkthread.cpp" />
<Unit filename="gui/checkthread.h" />
<Unit filename="gui/common.h" />
@ -77,6 +88,15 @@
<Unit filename="gui/statsdialog.cpp" />
<Unit filename="gui/statsdialog.h" />
<Unit filename="gui/test.cpp" />
<Unit filename="gui/test/main.cpp" />
<Unit filename="gui/test/testtranslationhandler.cpp" />
<Unit filename="gui/test/testtranslationhandler.h" />
<Unit filename="gui/test/testxmlreport.cpp" />
<Unit filename="gui/test/testxmlreport.h" />
<Unit filename="gui/test/testxmlreportv1.cpp" />
<Unit filename="gui/test/testxmlreportv1.h" />
<Unit filename="gui/test/testxmlreportv2.cpp" />
<Unit filename="gui/test/testxmlreportv2.h" />
<Unit filename="gui/threadhandler.cpp" />
<Unit filename="gui/threadhandler.h" />
<Unit filename="gui/threadresult.cpp" />
@ -87,6 +107,10 @@
<Unit filename="gui/txtreport.h" />
<Unit filename="gui/xmlreport.cpp" />
<Unit filename="gui/xmlreport.h" />
<Unit filename="gui/xmlreportv1.cpp" />
<Unit filename="gui/xmlreportv1.h" />
<Unit filename="gui/xmlreportv2.cpp" />
<Unit filename="gui/xmlreportv2.h" />
<Unit filename="lib/check.h" />
<Unit filename="lib/checkautovariables.cpp" />
<Unit filename="lib/checkautovariables.h" />
@ -102,6 +126,8 @@
<Unit filename="lib/checkheaders.h" />
<Unit filename="lib/checkmemoryleak.cpp" />
<Unit filename="lib/checkmemoryleak.h" />
<Unit filename="lib/checknullpointer.cpp" />
<Unit filename="lib/checknullpointer.h" />
<Unit filename="lib/checkobsoletefunctions.cpp" />
<Unit filename="lib/checkobsoletefunctions.h" />
<Unit filename="lib/checkother.cpp" />
@ -110,6 +136,8 @@
<Unit filename="lib/checkpostfixoperator.h" />
<Unit filename="lib/checkstl.cpp" />
<Unit filename="lib/checkstl.h" />
<Unit filename="lib/checkuninitvar.cpp" />
<Unit filename="lib/checkuninitvar.h" />
<Unit filename="lib/checkunusedfunctions.cpp" />
<Unit filename="lib/checkunusedfunctions.h" />
<Unit filename="lib/classinfo.h" />
@ -133,6 +161,8 @@
<Unit filename="lib/preprocessor.h" />
<Unit filename="lib/settings.cpp" />
<Unit filename="lib/settings.h" />
<Unit filename="lib/symboldatabase.cpp" />
<Unit filename="lib/symboldatabase.h" />
<Unit filename="lib/timer.cpp" />
<Unit filename="lib/timer.h" />
<Unit filename="lib/token.cpp" />
@ -152,14 +182,19 @@
<Unit filename="test/testcppcheck.cpp" />
<Unit filename="test/testdangerousfunctions.cpp" />
<Unit filename="test/testdivision.cpp" />
<Unit filename="test/testerrorlogger.cpp" />
<Unit filename="test/testexceptionsafety.cpp" />
<Unit filename="test/testfilelister.cpp" />
<Unit filename="test/testfilelister_unix.cpp" />
<Unit filename="test/testincompletestatement.cpp" />
<Unit filename="test/testmathlib.cpp" />
<Unit filename="test/testmemleak.cpp" />
<Unit filename="test/testnullpointer.cpp" />
<Unit filename="test/testobsoletefunctions.cpp" />
<Unit filename="test/testoptions.cpp" />
<Unit filename="test/testother.cpp" />
<Unit filename="test/testpath.cpp" />
<Unit filename="test/testpathmatch.cpp" />
<Unit filename="test/testpostfixoperator.cpp" />
<Unit filename="test/testpreprocessor.cpp" />
<Unit filename="test/testredundantif.cpp" />
@ -170,12 +205,16 @@
<Unit filename="test/teststl.cpp" />
<Unit filename="test/testsuite.cpp" />
<Unit filename="test/testsuite.h" />
<Unit filename="test/testsuppressions.cpp" />
<Unit filename="test/testsymboldatabase.cpp" />
<Unit filename="test/testthreadexecutor.cpp" />
<Unit filename="test/testtoken.cpp" />
<Unit filename="test/testtokenize.cpp" />
<Unit filename="test/testuninitvar.cpp" />
<Unit filename="test/testunusedfunctions.cpp" />
<Unit filename="test/testunusedprivfunc.cpp" />
<Unit filename="test/testunusedvar.cpp" />
<Unit filename="test/testutils.h" />
<Unit filename="test/tinyxml/tinystr.cpp" />
<Unit filename="test/tinyxml/tinystr.h" />
<Unit filename="test/tinyxml/tinyxml.cpp" />

View File

@ -1455,7 +1455,7 @@ void Scope::getVariableList()
// skip return and delete
else if (Token::Match(tok, "return|delete"))
{
while (tok->next()->str() != ";")
while (tok->next() && tok->next()->str() != ";")
tok = tok->next();
continue;
}

View File

@ -1235,15 +1235,24 @@ void Tokenizer::simplifyTypedef()
// function: typedef ... ( .... type )( ... );
// typedef ... (( .... type )( ... ));
// typedef ... ( * ( .... type )( ... ));
else if ((tok->tokAt(offset)->str() == "(" &&
Token::Match(tok->tokAt(offset)->link()->previous(), "%type% ) (") &&
Token::Match(tok->tokAt(offset)->link()->next()->link(), ") const|volatile|;")) ||
(Token::simpleMatch(tok->tokAt(offset), "( (") &&
Token::Match(tok->tokAt(offset + 1)->link()->previous(), "%type% ) (") &&
Token::Match(tok->tokAt(offset + 1)->link()->next()->link(), ") const|volatile| )")))
Token::Match(tok->tokAt(offset + 1)->link()->next()->link(), ") const|volatile| ) ;|,")) ||
(Token::simpleMatch(tok->tokAt(offset), "( * (") &&
Token::Match(tok->tokAt(offset + 2)->link()->previous(), "%type% ) (") &&
Token::Match(tok->tokAt(offset + 2)->link()->next()->link(), ") const|volatile| ) ;|,")))
{
if (tok->strAt(offset + 1) == "(")
offset++;
else if (Token::simpleMatch(tok->tokAt(offset), "( * ("))
{
pointers.push_back("*");
offset += 2;
}
if (tok->tokAt(offset)->link()->strAt(-2) == "*")
functionPtr = true;
@ -1289,7 +1298,9 @@ void Tokenizer::simplifyTypedef()
}
// pointer to function returning pointer to function
else if (Token::Match(tok->tokAt(offset), "( * ( * %type% ) ("))
else if (Token::Match(tok->tokAt(offset), "( * ( * %type% ) (") &&
Token::Match(tok->tokAt(offset + 6)->link(), ") ) (") &&
Token::Match(tok->tokAt(offset + 6)->link()->tokAt(2)->link(), ") ;|,"))
{
functionPtrRetFuncPtr = true;
@ -1305,7 +1316,8 @@ void Tokenizer::simplifyTypedef()
// function returning pointer to function
else if (Token::Match(tok->tokAt(offset), "( * %type% (") &&
Token::simpleMatch(tok->tokAt(offset + 3)->link(), ") ) ("))
Token::simpleMatch(tok->tokAt(offset + 3)->link(), ") ) (") &&
Token::Match(tok->tokAt(offset + 3)->link()->tokAt(2)->link(), ") ;|,"))
{
functionRetFuncPtr = true;
@ -2911,6 +2923,7 @@ void Tokenizer::simplifyTemplatesInstantiate(const Token *tok,
if (Token::Match(tok, "%var% ,|>"))
type.push_back(tok);
}
// bail out if the end of the file was reached
if (!tok)
return;
@ -3006,6 +3019,12 @@ void Tokenizer::simplifyTemplatesInstantiate(const Token *tok,
std::string s1(name + " < ");
for (const Token *tok3 = tok2->tokAt(2); tok3 && tok3->str() != ">"; tok3 = tok3->next())
{
// #2648 - unhandled paranthesis => bail out
if (tok3->str() == "(")
{
s.clear();
break;
}
if (!tok3->next())
{
s.clear();
@ -3430,7 +3449,7 @@ void Tokenizer::setVarId()
{
again = false;
if (tok2->str() == "const")
if (tok2 && tok2->str() == "const")
tok2 = tok2->next();
while (Token::Match(tok2, "%var% ::"))
@ -3465,7 +3484,7 @@ void Tokenizer::setVarId()
{
while (tok2 && (tok2->isName() || tok2->isNumber() || tok2->str() == "*" || tok2->str() == "&" || tok2->str() == ","))
tok2 = tok2->next();
if (tok2->str() == "(")
if (tok2 && tok2->str() == "(")
{
tok2 = tok2->link()->next();
if (tok2->str() == "(")
@ -3561,11 +3580,41 @@ void Tokenizer::setVarId()
// Variable declaration found => Set variable ids
if (Token::Match(tok2, "[,();[=]") && !varname.empty())
{
// Are we in a class declaration?
// Then start at the start of the class declaration..
while (NULL != (tok2 = tok2->previous()))
{
if (tok2->str() == "}" || tok2->str() == ")")
tok2 = tok2->link();
else if (tok2->str() == "(")
break;
else if (tok2->str() == "{")
{
while (NULL != (tok2 = tok2->previous()))
{
if (Token::Match(tok2, "[,;{})]"))
break;
if (Token::Match(tok2, "class|struct"))
break;
}
break;
}
}
// Set start token
if (Token::Match(tok2, "class|struct"))
{
while (tok2->str() != "{")
tok2 = tok2->next();
}
else
tok2 = tok;
++_varId;
int indentlevel = 0;
int parlevel = 0;
bool funcDeclaration = false;
for (tok2 = tok->next(); tok2; tok2 = tok2->next())
while (NULL != (tok2 = tok2->next()))
{
const char c = tok2->str()[0];
if (c == varname[0])
@ -3602,29 +3651,6 @@ void Tokenizer::setVarId()
}
}
// Struct/Class members
for (Token *tok = _tokens; tok; tok = tok->next())
{
// str.clear is a variable
// str.clear() is a member function
if (tok->varId() != 0 &&
Token::Match(tok->next(), ". %var% !!(") &&
tok->tokAt(2)->varId() == 0)
{
++_varId;
const std::string pattern(std::string(". ") + tok->strAt(2));
for (Token *tok2 = tok; tok2; tok2 = tok2->next())
{
if (tok2->varId() == tok->varId())
{
if (Token::Match(tok2->next(), pattern.c_str()))
tok2->tokAt(2)->varId(_varId);
}
}
}
}
// Member functions and variables in this source
std::list<Token *> allMemberFunctions;
std::list<Token *> allMemberVars;
@ -3739,6 +3765,29 @@ void Tokenizer::setVarId()
}
}
// Struct/Class members
for (Token *tok = _tokens; tok; tok = tok->next())
{
// str.clear is a variable
// str.clear() is a member function
if (tok->varId() != 0 &&
Token::Match(tok->next(), ". %var% !!(") &&
tok->tokAt(2)->varId() == 0)
{
++_varId;
const std::string pattern(std::string(". ") + tok->strAt(2));
for (Token *tok2 = tok; tok2; tok2 = tok2->next())
{
if (tok2->varId() == tok->varId())
{
if (Token::Match(tok2->next(), pattern.c_str()))
tok2->tokAt(2)->varId(_varId);
}
}
}
}
}
bool Tokenizer::createLinks()

View File

@ -197,6 +197,7 @@ private:
TEST_CASE(symboldatabase14); // ticket #2589
TEST_CASE(symboldatabase15); // ticket #2591
TEST_CASE(symboldatabase16); // ticket #2637
TEST_CASE(symboldatabase17); // ticket #2657
}
// Check the operator Equal
@ -5805,6 +5806,14 @@ private:
ASSERT_EQUALS("", errout.str());
}
void symboldatabase17()
{
// ticket #2657 - segmentation fault
checkConst("return f(){}\n");
ASSERT_EQUALS("", errout.str());
}
};
REGISTER_TEST(TestClass)

View File

@ -127,13 +127,13 @@ public:
{ }
private:
void check(const char code[], bool showAll = false)
void check(const char code[], bool inconclusive = false)
{
// Clear the error buffer..
errout.str("");
Settings settings;
settings.inconclusive = showAll;
settings.inconclusive = inconclusive;
// Tokenize..
Tokenizer tokenizer(&settings, this);
@ -4235,8 +4235,7 @@ private:
"private:\n"
" char *s;\n"
"};\n");
TODO_ASSERT_EQUALS("publicAllocation",
"", errout.str());
ASSERT_EQUALS("[test.cpp:7]: (warning) Possible leak in public function. The pointer 's' is not deallocated before it is allocated.\n", errout.str());
}
void func2()

View File

@ -115,6 +115,7 @@ private:
TEST_CASE(template22);
TEST_CASE(template23);
TEST_CASE(template24); // #2648 - using sizeof in template parameter
TEST_CASE(template25); // #2648 - another test for sizeof template parameter
TEST_CASE(template_unhandled);
TEST_CASE(template_default_parameter);
TEST_CASE(template_default_type);
@ -249,6 +250,7 @@ private:
TEST_CASE(simplifyTypedef84); // ticket #2630
TEST_CASE(simplifyTypedef85); // ticket #2651
TEST_CASE(simplifyTypedef86); // ticket #2581
TEST_CASE(simplifyTypedef87); // ticket #2651
TEST_CASE(simplifyTypedefFunction1);
TEST_CASE(simplifyTypedefFunction2); // ticket #1685
@ -2060,6 +2062,30 @@ private:
ASSERT_EQUALS(expected, sizeof_(code));
}
void template25()
{
const char code[] = "template<int n> struct B\n"
"{\n"
" int a[n];\n"
"};\n"
"\n"
"template<int x> class bitset: B<((sizeof(int)) ? : 1)>\n"
"{};\n"
"\n"
"bitset<1> z;";
const char actual[] = "; bitset<1> z ; "
"class bitset<1> : B < ( ) > { }";
const char expected[] = "; "
"bitset<1> z ; "
"class bitset<1> : B<4> { } "
"struct B<4> { int a [ 4 ] ; }";
TODO_ASSERT_EQUALS(expected, actual, sizeof_(code));
}
void template_unhandled()
{
// An unhandled template usage should be simplified..
@ -5035,6 +5061,15 @@ private:
ASSERT_EQUALS("", errout.str());
}
void simplifyTypedef87() // ticket #2651
{
const char code[] = "typedef FOO (*(*BAR)(void, int, const int, int*));\n";
const char expected[] = ";";
checkSimplifyTypedef(code);
ASSERT_EQUALS(expected, sizeof_(code));
ASSERT_EQUALS("", errout.str());
}
void simplifyTypedefFunction1()
{
{

View File

@ -170,6 +170,7 @@ private:
TEST_CASE(varid25);
TEST_CASE(varid26); // ticket #1967 (list of function pointers)
TEST_CASE(varid27); // Ticket #2280 (same name for namespace and variable)
TEST_CASE(varid28); // ticket #2630
TEST_CASE(varidFunctionCall1);
TEST_CASE(varidFunctionCall2);
TEST_CASE(varidFunctionCall3);
@ -192,6 +193,8 @@ private:
TEST_CASE(varidclass7);
TEST_CASE(varidclass8);
TEST_CASE(varidclass9);
TEST_CASE(varidclass10); // variable declaration below usage
TEST_CASE(varidclass11); // variable declaration below usage
TEST_CASE(file1);
TEST_CASE(file2);
@ -2818,6 +2821,12 @@ private:
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
}
void varid28() // ticket #2630 (segmentation fault)
{
tokenizeDebugListing("template <typedef A>\n");
ASSERT_EQUALS("", errout.str());
}
void varidFunctionCall1()
{
const std::string code("void f() {\n"
@ -3083,7 +3092,7 @@ private:
"10:\n"
"11: void Bar :: f ( )\n"
"12: {\n"
"13: foo@2 . x = x@3 ;\n" // TODO: it would be even better if the ". x" was ". x@4" instead
"13: foo@2 . x@4 = x@3 ;\n"
"14: }\n");
ASSERT_EQUALS(expected, actual);
}
@ -3374,7 +3383,7 @@ private:
"1: class Fred {\n"
"2: public:\n"
"3: void foo ( int d@1 ) {\n"
"4: int i@2 ; i@2 = bar ( x * d@1 ) ;\n"
"4: int i@2 ; i@2 = bar ( x@3 * d@1 ) ;\n"
"5: }\n"
"6: int x@3 ;\n"
"7: }\n");
@ -3408,6 +3417,52 @@ private:
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
}
void varidclass10()
{
const std::string code("class A {\n"
" void f() {\n"
" a = 3;\n"
" }\n"
" int a;\n"
"};\n");
const std::string expected("\n\n##file 0\n"
"1: class A {\n"
"2: void f ( ) {\n"
"3: a@1 = 3 ;\n"
"4: }\n"
"5: int a@1 ;\n"
"6: } ;\n");
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
}
void varidclass11()
{
const std::string code("class Fred {\n"
" int a;\n"
" void f();\n"
"};\n"
"class Wilma {\n"
" int a;\n"
" void f();\n"
"};\n"
"void Fred::f() { a = 0; }\n"
"void Wilma::f() { a = 0; }\n");
const std::string expected("\n\n##file 0\n"
"1: class Fred {\n"
"2: int a@1 ;\n"
"3: void f ( ) ;\n"
"4: } ;\n"
"5: class Wilma {\n"
"6: int a@2 ;\n"
"7: void f ( ) ;\n"
"8: } ;\n"
"9: void Fred :: f ( ) { a@1 = 0 ; }\n"
"10: void Wilma :: f ( ) { a@2 = 0 ; }\n");
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
}
void file1()
{