Merge branch 'master' of http://github.com/danmar/cppcheck
This commit is contained in:
commit
fb345e7a2c
|
@ -376,8 +376,12 @@ void CheckMemoryLeak::mismatchAllocDealloc(const std::list<const Token *> &calls
|
||||||
|
|
||||||
CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok) const
|
CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok) const
|
||||||
{
|
{
|
||||||
// Locate the start of the function..
|
if (!tok)
|
||||||
unsigned int parlevel = 0;
|
return No;
|
||||||
|
|
||||||
|
const std::string functionName = tok->str();
|
||||||
|
|
||||||
|
// Locate start of function
|
||||||
while (tok)
|
while (tok)
|
||||||
{
|
{
|
||||||
if (tok->str() == "{" || tok->str() == "}")
|
if (tok->str() == "{" || tok->str() == "}")
|
||||||
|
@ -385,15 +389,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok)
|
||||||
|
|
||||||
if (tok->str() == "(")
|
if (tok->str() == "(")
|
||||||
{
|
{
|
||||||
if (parlevel != 0)
|
tok = tok->link();
|
||||||
return No;
|
|
||||||
++parlevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (tok->str() == ")")
|
|
||||||
{
|
|
||||||
if (parlevel != 1)
|
|
||||||
return No;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,6 +425,10 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok)
|
||||||
}
|
}
|
||||||
else if (tok2->str() == "return")
|
else if (tok2->str() == "return")
|
||||||
{
|
{
|
||||||
|
// recursion => bail out
|
||||||
|
if (tok2->strAt(1) == functionName)
|
||||||
|
return No;
|
||||||
|
|
||||||
AllocType allocType = getAllocationType(tok2->next(), 0);
|
AllocType allocType = getAllocationType(tok2->next(), 0);
|
||||||
if (allocType != No)
|
if (allocType != No)
|
||||||
return allocType;
|
return allocType;
|
||||||
|
@ -445,11 +445,11 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok)
|
||||||
{
|
{
|
||||||
if (Token::Match(tok, "%varid% =", varid))
|
if (Token::Match(tok, "%varid% =", varid))
|
||||||
{
|
{
|
||||||
|
// recursion => bail out
|
||||||
|
if (tok->strAt(2) == functionName)
|
||||||
|
return No;
|
||||||
|
|
||||||
allocType = getAllocationType(tok->tokAt(2), varid);
|
allocType = getAllocationType(tok->tokAt(2), varid);
|
||||||
if (allocType == No)
|
|
||||||
{
|
|
||||||
allocType = getReallocationType(tok->tokAt(2), varid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (Token::Match(tok, "= %varid% ;", varid))
|
if (Token::Match(tok, "= %varid% ;", varid))
|
||||||
{
|
{
|
||||||
|
|
|
@ -2951,11 +2951,18 @@ static bool isFunction(const std::string &name, const Token *startToken)
|
||||||
for (const Token *tok = startToken; tok; tok = tok->next())
|
for (const Token *tok = startToken; tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
// skip executable scopes etc
|
// skip executable scopes etc
|
||||||
if (tok->str() == "(" || tok->str() == "{")
|
if (tok->str() == "(")
|
||||||
|
{
|
||||||
tok = tok->link();
|
tok = tok->link();
|
||||||
|
if (Token::simpleMatch(tok, ") {"))
|
||||||
|
tok = tok->next()->link();
|
||||||
|
else if (Token::simpleMatch(tok, ") const {"))
|
||||||
|
tok = tok->tokAt(2)->link();
|
||||||
|
}
|
||||||
|
|
||||||
// function declaration/implementation found
|
// function declaration/implementation found
|
||||||
if (Token::simpleMatch(tok, pattern1.c_str()))
|
if ((tok->str() == "*" || (tok->isName() && tok->str().find(":") ==std::string::npos))
|
||||||
|
&& Token::simpleMatch(tok->next(), pattern1.c_str()))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -5563,7 +5563,7 @@ void Tokenizer:: simplifyFunctionPointers()
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
// check that the declaration ends
|
// check that the declaration ends
|
||||||
if (!Token::Match(tok->tokAt(5)->link(), ") ;|,|)|="))
|
if (!Token::Match(tok->tokAt(5)->link(), ") ;|,|)|=|["))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// ok simplify this function pointer to an ordinary pointer
|
// ok simplify this function pointer to an ordinary pointer
|
||||||
|
@ -9315,15 +9315,22 @@ void Tokenizer::simplifyBitfields()
|
||||||
{
|
{
|
||||||
Token *last = 0;
|
Token *last = 0;
|
||||||
|
|
||||||
if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% %var% : %any% ;|,") &&
|
if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% %var% :") &&
|
||||||
tok->next()->str() != "case")
|
!Token::Match(tok->next(), "case|public|protected|private"))
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (tok->next()->str() == "const")
|
if (tok->next()->str() == "const")
|
||||||
offset = 1;
|
offset = 1;
|
||||||
|
|
||||||
last = tok->tokAt(5 + offset);
|
Token *tok1 = tok->tokAt(2 + offset);
|
||||||
Token::eraseTokens(tok->tokAt(2 + offset), tok->tokAt(5 + offset));
|
if (tok1->tokAt(2)->isBoolean() || Token::Match(tok1->tokAt(2), "%num%") ||
|
||||||
|
!Token::Match(tok1->tokAt(2), "public|protected|private| %type% ::|<|,|{|;"))
|
||||||
|
{
|
||||||
|
while (tok1->next() && !Token::Match(tok1->next(), ";|,"))
|
||||||
|
tok1->deleteNext();
|
||||||
|
|
||||||
|
last = tok1->next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% : %any% ;") &&
|
else if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% : %any% ;") &&
|
||||||
tok->next()->str() != "default")
|
tok->next()->str() != "default")
|
||||||
|
|
|
@ -333,6 +333,10 @@ private:
|
||||||
TEST_CASE(jmp);
|
TEST_CASE(jmp);
|
||||||
|
|
||||||
TEST_CASE(trac1949);
|
TEST_CASE(trac1949);
|
||||||
|
|
||||||
|
// #2662: segfault because of endless recursion (call_func -> getAllocationType -> functionReturnType -> call_func ..)
|
||||||
|
TEST_CASE(trac2662);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3157,6 +3161,31 @@ private:
|
||||||
);
|
);
|
||||||
ASSERT_EQUALS("[test.cpp:10]: (error) Memory leak: buff\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:10]: (error) Memory leak: buff\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void trac2662()
|
||||||
|
{
|
||||||
|
// segfault because of endless recursion
|
||||||
|
// call_func -> getAllocationType -> functionReturnType -> call_func ..
|
||||||
|
|
||||||
|
check("char *foo() {\n"
|
||||||
|
" return foo();\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"void bar() {\n"
|
||||||
|
" char *s = foo();\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("char *foo() {\n"
|
||||||
|
" char *s = foo();\n"
|
||||||
|
" return s;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"void bar() {\n"
|
||||||
|
" char *s = foo();\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static TestMemleakInFunction testMemleakInFunction;
|
static TestMemleakInFunction testMemleakInFunction;
|
||||||
|
|
|
@ -82,7 +82,8 @@ private:
|
||||||
TEST_CASE(testScanf2);
|
TEST_CASE(testScanf2);
|
||||||
|
|
||||||
TEST_CASE(trac1132);
|
TEST_CASE(trac1132);
|
||||||
TEST_CASE(testMisusedScopeObjectDoesNotPickFunction);
|
TEST_CASE(testMisusedScopeObjectDoesNotPickFunction1);
|
||||||
|
TEST_CASE(testMisusedScopeObjectDoesNotPickFunction2);
|
||||||
TEST_CASE(testMisusedScopeObjectPicksClass);
|
TEST_CASE(testMisusedScopeObjectPicksClass);
|
||||||
TEST_CASE(testMisusedScopeObjectPicksStruct);
|
TEST_CASE(testMisusedScopeObjectPicksStruct);
|
||||||
TEST_CASE(testMisusedScopeObjectDoesNotPickIf);
|
TEST_CASE(testMisusedScopeObjectDoesNotPickIf);
|
||||||
|
@ -1647,7 +1648,7 @@ private:
|
||||||
ASSERT_EQUALS("[trac1132.cpp:16]: (error) instance of \"Lock\" object destroyed immediately\n", errout.str());
|
ASSERT_EQUALS("[trac1132.cpp:16]: (error) instance of \"Lock\" object destroyed immediately\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void testMisusedScopeObjectDoesNotPickFunction()
|
void testMisusedScopeObjectDoesNotPickFunction1()
|
||||||
{
|
{
|
||||||
check("int main ( )\n"
|
check("int main ( )\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -1658,6 +1659,24 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testMisusedScopeObjectDoesNotPickFunction2()
|
||||||
|
{
|
||||||
|
check("struct error {\n"
|
||||||
|
" error() {}\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"class parser {\n"
|
||||||
|
"public:\n"
|
||||||
|
" void error() const {}\n"
|
||||||
|
"\n"
|
||||||
|
" void foo() const {\n"
|
||||||
|
" error();\n"
|
||||||
|
" }\n"
|
||||||
|
"};\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void testMisusedScopeObjectPicksClass()
|
void testMisusedScopeObjectPicksClass()
|
||||||
{
|
{
|
||||||
check("class NotAFunction ;\n"
|
check("class NotAFunction ;\n"
|
||||||
|
@ -1803,7 +1822,7 @@ private:
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
check(code, "test.cpp");
|
check(code, "test.cpp");
|
||||||
TODO_ASSERT_EQUALS("", "[test.cpp:13]: (error) instance of \"Init\" object destroyed immediately\n", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void trac2084()
|
void trac2084()
|
||||||
|
|
|
@ -267,7 +267,8 @@ private:
|
||||||
TEST_CASE(simplifyConst);
|
TEST_CASE(simplifyConst);
|
||||||
TEST_CASE(switchCase);
|
TEST_CASE(switchCase);
|
||||||
|
|
||||||
TEST_CASE(functionpointer);
|
TEST_CASE(functionpointer1);
|
||||||
|
TEST_CASE(functionpointer2);
|
||||||
|
|
||||||
TEST_CASE(removeRedundantAssignment);
|
TEST_CASE(removeRedundantAssignment);
|
||||||
|
|
||||||
|
@ -289,6 +290,7 @@ private:
|
||||||
TEST_CASE(bitfields4); // ticket #1956
|
TEST_CASE(bitfields4); // ticket #1956
|
||||||
TEST_CASE(bitfields5); // ticket #1956
|
TEST_CASE(bitfields5); // ticket #1956
|
||||||
TEST_CASE(bitfields6); // ticket #2595
|
TEST_CASE(bitfields6); // ticket #2595
|
||||||
|
TEST_CASE(bitfields7); // ticket #1987
|
||||||
|
|
||||||
TEST_CASE(microsoftMFC);
|
TEST_CASE(microsoftMFC);
|
||||||
|
|
||||||
|
@ -4737,7 +4739,7 @@ private:
|
||||||
return ostr.str();
|
return ostr.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void functionpointer()
|
void functionpointer1()
|
||||||
{
|
{
|
||||||
ASSERT_EQUALS(" void* f;", simplifyFunctionPointers("void (*f)();"));
|
ASSERT_EQUALS(" void* f;", simplifyFunctionPointers("void (*f)();"));
|
||||||
ASSERT_EQUALS(" void** f;", simplifyFunctionPointers("void *(*f)();"));
|
ASSERT_EQUALS(" void** f;", simplifyFunctionPointers("void *(*f)();"));
|
||||||
|
@ -4745,6 +4747,19 @@ private:
|
||||||
ASSERT_EQUALS(" unsigned int** f;", simplifyFunctionPointers("unsigned int * (*f)();"));
|
ASSERT_EQUALS(" unsigned int** f;", simplifyFunctionPointers("unsigned int * (*f)();"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void functionpointer2()
|
||||||
|
{
|
||||||
|
const char code[] = "typedef void (* PF)();"
|
||||||
|
"void f1 ( ) { }"
|
||||||
|
"PF pf = &f1;"
|
||||||
|
"PF pfs[] = { &f1, &f1 };";
|
||||||
|
const char expected[] = "; "
|
||||||
|
"void f1(){} "
|
||||||
|
"void* pf; pf=& f1; "
|
||||||
|
"void* pfs[]={& f1,& f1};";
|
||||||
|
ASSERT_EQUALS(expected, simplifyFunctionPointers(code));
|
||||||
|
}
|
||||||
|
|
||||||
void removeRedundantAssignment()
|
void removeRedundantAssignment()
|
||||||
{
|
{
|
||||||
ASSERT_EQUALS("void f ( ) { ; int * q ; }", tokenizeAndStringify("void f() { int *p, *q; p = q; }", true));
|
ASSERT_EQUALS("void f ( ) { ; int * q ; }", tokenizeAndStringify("void f() { int *p, *q; p = q; }", true));
|
||||||
|
@ -5273,6 +5288,18 @@ private:
|
||||||
ASSERT_EQUALS("void f ( int a ) { switch ( a ) { default : ; break ; } }", tokenizeAndStringify(code5,true));
|
ASSERT_EQUALS("void f ( int a ) { switch ( a ) { default : ; break ; } }", tokenizeAndStringify(code5,true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bitfields7() // ticket #1987
|
||||||
|
{
|
||||||
|
const char code[] = "typedef struct Descriptor {"
|
||||||
|
" unsigned element_size: 8* sizeof( unsigned );"
|
||||||
|
"} Descriptor;";
|
||||||
|
const char expected[] = "struct Descriptor { "
|
||||||
|
"unsigned int element_size ; "
|
||||||
|
"} ;";
|
||||||
|
ASSERT_EQUALS(expected, tokenizeAndStringify(code,false));
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void microsoftMFC()
|
void microsoftMFC()
|
||||||
{
|
{
|
||||||
const char code1[] = "class MyDialog : public CDialog { DECLARE_MESSAGE_MAP() private: CString text; };";
|
const char code1[] = "class MyDialog : public CDialog { DECLARE_MESSAGE_MAP() private: CString text; };";
|
||||||
|
|
Loading…
Reference in New Issue