Fixed #2018 (Postfix Operators)

This commit is contained in:
Debrard Sebastien 2010-10-14 19:08:31 +02:00
commit fb928b6778
11 changed files with 138 additions and 39 deletions

View File

@ -1012,7 +1012,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo
if (Token::Match(tok, "strcpy|strcat ( %varid% , %str% )", arrayInfo.varid)) if (Token::Match(tok, "strcpy|strcat ( %varid% , %str% )", arrayInfo.varid))
{ {
const unsigned long len = Token::getStrLength(tok->tokAt(4)); const unsigned long len = Token::getStrLength(tok->tokAt(4));
if (len >= total_size) if (total_size > 0 && len >= total_size)
{ {
bufferOverrun(tok, arrayInfo.varname); bufferOverrun(tok, arrayInfo.varname);
continue; continue;
@ -1794,7 +1794,9 @@ bool CheckBufferOverrun::ArrayInfo::declare(const Token *tok, const Tokenizer &t
if (!tok->isName()) if (!tok->isName())
return false; return false;
while (tok && (tok->str() == "static" || tok->str() == "const")) while (tok && (tok->str() == "static" ||
tok->str() == "const" ||
tok->str() == "extern"))
tok = tok->next(); tok = tok->next();
int ivar = 0; int ivar = 0;

View File

@ -2139,6 +2139,37 @@ bool CheckClass::isMemberVar(const SpaceInfo *info, const Token *tok)
return false; return false;
} }
bool CheckClass::isConstMemberFunc(const SpaceInfo *info, const Token *tok)
{
std::list<Func>::const_iterator func;
for (func = info->functionList.begin(); func != info->functionList.end(); ++func)
{
if (func->tokenDef->str() == tok->str() && func->isConst)
return true;
}
// not found in this class
if (!info->derivedFrom.empty())
{
// check each base class
for (unsigned int i = 0; i < info->derivedFrom.size(); ++i)
{
// find the base class
const SpaceInfo *spaceInfo = info->derivedFrom[i].spaceInfo;
// find the function in the base class
if (spaceInfo)
{
if (isConstMemberFunc(spaceInfo, tok))
return true;
}
}
}
return false;
}
bool CheckClass::checkConstFunc(const SpaceInfo *info, const Token *tok) bool CheckClass::checkConstFunc(const SpaceInfo *info, const Token *tok)
{ {
// if the function doesn't have any assignment nor function call, // if the function doesn't have any assignment nor function call,
@ -2200,9 +2231,16 @@ bool CheckClass::checkConstFunc(const SpaceInfo *info, const Token *tok)
} }
// function call.. // function call..
else if ((Token::Match(tok1, "%var% (") && else if (Token::Match(tok1, "%var% (") &&
!(Token::Match(tok1, "return|c_str|if|string") || tok1->isStandardType())) || !(Token::Match(tok1, "return|c_str|if|string") || tok1->isStandardType()))
Token::Match(tok1, "%var% < %any% > (")) {
if (!isConstMemberFunc(info, tok1))
{
isconst = false;
break;
}
}
else if (Token::Match(tok1, "%var% < %any% > ("))
{ {
isconst = false; isconst = false;
break; break;

View File

@ -305,6 +305,7 @@ private:
bool argsMatch(const Token *first, const Token *second, const std::string &path, unsigned int depth) const; bool argsMatch(const Token *first, const Token *second, const std::string &path, unsigned int depth) const;
bool isMemberVar(const SpaceInfo *info, const Token *tok); bool isMemberVar(const SpaceInfo *info, const Token *tok);
bool isConstMemberFunc(const SpaceInfo *info, const Token *tok);
bool checkConstFunc(const SpaceInfo *info, const Token *tok); bool checkConstFunc(const SpaceInfo *info, const Token *tok);
const Token *initBaseInfo(SpaceInfo *info, const Token *tok); const Token *initBaseInfo(SpaceInfo *info, const Token *tok);

View File

@ -3884,8 +3884,8 @@ bool CheckOther::isIdentifierObjectType(const Token * const tok)
return found->second; return found->second;
} }
const std::string classDef = std::string("class|struct ") + identifier; const std::string classDefnOrDecl = std::string("class|struct ") + identifier + " [{:;]";
const bool result = Token::findmatch(_tokenizer->tokens(), classDef.c_str()); const bool result = Token::findmatch(_tokenizer->tokens(), classDefnOrDecl.c_str()) != NULL;
isClassResults.insert(std::make_pair(identifier, result)); isClassResults.insert(std::make_pair(identifier, result));
return result; return result;
} }
@ -3895,7 +3895,6 @@ void CheckOther::checkMisusedScopedObject()
{ {
bool withinFunction = false; bool withinFunction = false;
unsigned int depth = 0; unsigned int depth = 0;
std::string className = "";
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{ {
@ -3910,17 +3909,6 @@ void CheckOther::checkMisusedScopedObject()
{ {
--depth; --depth;
withinFunction &= depth > 0; withinFunction &= depth > 0;
if (tok->strAt(1) == ";" && !className.empty())
{
isClassResults[className] = true;
className.clear();
}
}
else if (Token::Match(tok, "class|struct"))
{
className = tok->strAt(1);
isClassResults.insert(std::make_pair(className, false));
} }
if (withinFunction if (withinFunction

View File

@ -1594,28 +1594,33 @@ void Tokenizer::simplifyTypedef()
if (arrayStart && arrayEnd) if (arrayStart && arrayEnd)
{ {
tok2 = tok2->next(); do
Token * nextArrTok;
std::stack<Token *> arrLinks;
for (nextArrTok = arrayStart; nextArrTok != arrayEnd->next(); nextArrTok = nextArrTok->next())
{ {
tok2->insertToken(nextArrTok->strAt(0));
tok2 = tok2->next(); tok2 = tok2->next();
Token * nextArrTok;
// Check for links and fix them up std::stack<Token *> arrLinks;
if (tok2->str() == "(" || tok2->str() == "[") for (nextArrTok = arrayStart; nextArrTok != arrayEnd->next(); nextArrTok = nextArrTok->next())
arrLinks.push(tok2);
if (tok2->str() == ")" || tok2->str() == "]")
{ {
Token * link = arrLinks.top(); tok2->insertToken(nextArrTok->strAt(0));
tok2 = tok2->next();
tok2->link(link); // Check for links and fix them up
link->link(tok2); if (tok2->str() == "(" || tok2->str() == "[")
arrLinks.push(tok2);
if (tok2->str() == ")" || tok2->str() == "]")
{
Token * link = arrLinks.top();
arrLinks.pop(); tok2->link(link);
link->link(tok2);
arrLinks.pop();
}
} }
tok2 = tok2->next();
} }
tok2 = tok2->next(); while (Token::Match(tok2, ", %var% ;|'"));
} }
simplifyType = false; simplifyType = false;
@ -2095,6 +2100,12 @@ void Tokenizer::arraySize()
{ {
for (Token *tok = _tokens; tok; tok = tok->next()) for (Token *tok = _tokens; tok; tok = tok->next())
{ {
if (Token::Match(tok, "%var% [ ] = { %str% }"))
{
tok->tokAt(4)->deleteThis();
tok->tokAt(5)->deleteThis();
}
if (Token::Match(tok, "%var% [ ] = {")) if (Token::Match(tok, "%var% [ ] = {"))
{ {
unsigned int sz = 1; unsigned int sz = 1;

View File

@ -1688,11 +1688,25 @@ private:
void buffer_overrun_16() void buffer_overrun_16()
{ {
// unknown types
check("void f() {\n" check("void f() {\n"
" struct Foo foo[5];\n" " struct Foo foo[5];\n"
" memset(foo, 0, sizeof(foo));\n" " memset(foo, 0, sizeof(foo));\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void f() {\n" // ticket #2093
" gchar x[3];\n"
" strcpy(x, \"12\");\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("extern char a[10];\n"
"void f() {\n"
" char b[25] = {0};\n"
" std::memcpy(b, a, sizeof(a));\n"
"}\n");
ASSERT_EQUALS("", errout.str());
} }
void sprintf1() void sprintf1()

View File

@ -4130,7 +4130,7 @@ private:
" void f() const { };\n" " void f() const { };\n"
" void a() { f(); };\n" " void a() { f(); };\n"
"};\n"); "};\n");
TODO_ASSERT_EQUALS("[test.cpp:3]: (style) The function 'Fred::a' can be const\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (style) The function 'Fred::a' can be const\n", errout.str());
// ticket #1593 // ticket #1593
checkConst("#include <vector>\n" checkConst("#include <vector>\n"

View File

@ -112,6 +112,7 @@ private:
TEST_CASE(testMisusedScopeObjectDoesNotPickLocalClassConstructors); TEST_CASE(testMisusedScopeObjectDoesNotPickLocalClassConstructors);
TEST_CASE(testMisusedScopeObjectDoesNotPickUsedObject); TEST_CASE(testMisusedScopeObjectDoesNotPickUsedObject);
TEST_CASE(trac2071); TEST_CASE(trac2071);
TEST_CASE(trac2084);
TEST_CASE(assignmentInAssert); TEST_CASE(assignmentInAssert);
} }
@ -3060,6 +3061,21 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void trac2084()
{
check("#include <signal.h>\n"
"\n"
"void f()\n"
"{\n"
" struct sigaction sa;\n"
"\n"
" { sigaction(SIGHUP, &sa, 0); };\n"
" { sigaction(SIGINT, &sa, 0); };\n"
"}\n"
);
ASSERT_EQUALS("", errout.str());
}
void trac2071() void trac2071()
{ {
check("void f() {\n" check("void f() {\n"

View File

@ -217,6 +217,7 @@ private:
TEST_CASE(simplifyTypedef59); // ticket #2011 TEST_CASE(simplifyTypedef59); // ticket #2011
TEST_CASE(simplifyTypedef60); // ticket #2035 TEST_CASE(simplifyTypedef60); // ticket #2035
TEST_CASE(simplifyTypedef61); // ticket #2074 and 2075 TEST_CASE(simplifyTypedef61); // ticket #2074 and 2075
TEST_CASE(simplifyTypedef62); // ticket #2082
TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction1);
TEST_CASE(simplifyTypedefFunction2); // ticket #1685 TEST_CASE(simplifyTypedefFunction2); // ticket #1685
@ -934,6 +935,12 @@ private:
ASSERT_EQUALS("; const char str [ 1 ] = { '1' } ; 1 ;", sizeof_(code)); ASSERT_EQUALS("; const char str [ 1 ] = { '1' } ; 1 ;", sizeof_(code));
} }
{
// Ticket #2087
const char code[] = "; const char str[] = {\"abc\"}; sizeof(str);";
ASSERT_EQUALS("; const char str [ 4 ] = \"abc\" ; 4 ;", sizeof_(code));
}
// ticket #716 - sizeof string // ticket #716 - sizeof string
{ {
std::ostringstream expected; std::ostringstream expected;
@ -4469,6 +4476,23 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void simplifyTypedef62() // ticket #2082
{
const char code[] = "typedef char TString[256];\n"
"void f()\n"
"{\n"
" TString a, b;\n"
"}";
// The expected tokens..
const std::string expected("; void f ( ) { char a [ 256 ] ; char b [ 256 ] ; }");
ASSERT_EQUALS(expected, sizeof_(code, false));
// Check for output..
checkSimplifyTypedef(code);
ASSERT_EQUALS("", errout.str());
}
void simplifyTypedefFunction1() void simplifyTypedefFunction1()
{ {
{ {

View File

@ -49,11 +49,13 @@
<Component Id='GuiHelp' Guid='*'> <Component Id='GuiHelp' Guid='*'>
<File Id='onlinehelp.qhc' Name='online-help.qhc' DiskId='1' Source='$(var.HelpDir)\online-help.qhc' KeyPath='yes' /> <File Id='onlinehelp.qhc' Name='online-help.qhc' DiskId='1' Source='$(var.HelpDir)\online-help.qhc' KeyPath='yes' />
</Component> </Component>
<!-- Cleanup runtime files installed by previous InnoSetup installer --> <!-- Cleanup runtime files installed by previous InnoSetup installer
Also remove old gui.exe which is now cppcheck-gui.exe -->
<Component Id='InnoSetupCleanup' Guid='4A3F299D-1EE1-468b-814B-D6577F0698CA'> <Component Id='InnoSetupCleanup' Guid='4A3F299D-1EE1-468b-814B-D6577F0698CA'>
<RemoveFile Id="msvcp90.dll" On="install" Name="msvcp90.dll" /> <RemoveFile Id="msvcp90.dll" On="install" Name="msvcp90.dll" />
<RemoveFile Id="msvcr90.dll" On="install" Name="msvcr90.dll" /> <RemoveFile Id="msvcr90.dll" On="install" Name="msvcr90.dll" />
<RemoveFile Id="Microsoft.VC90.CRT.manifest" On="install" Name="Microsoft.VC90.CRT.manifest" /> <RemoveFile Id="Microsoft.VC90.CRT.manifest" On="install" Name="Microsoft.VC90.CRT.manifest" />
<RemoveFile Id="gui.exe" On="install" Name="gui.exe" />
</Component> </Component>
</Directory> </Directory>
<Merge Id="CRT" Language="0" SourceFile="$(var.CrtMergeModule)" DiskId="1" /> <Merge Id="CRT" Language="0" SourceFile="$(var.CrtMergeModule)" DiskId="1" />

View File

@ -25,11 +25,14 @@ Building installer
Before building the installer make sure all the components are build: Before building the installer make sure all the components are build:
- CLI executable (cppcheck.exe) - CLI executable (cppcheck.exe)
- GUI executable (gui.exe) - GUI executable (cppcheck-gui.exe)
- Manual (manual.pdf) - GUI translations (*.qm)
- Manual (onlinehelp.qhc)
And that runtime files are available: And that runtime files are available:
- Qt runtimes (qtcore4.dll, qtgui4.dll and qtxml4.dll) - Qt runtimes:
QtCLucene4.dll, QtCore4.dll, QtGui4.dll, QtHelp4.dll, QtNetwork4.dll,
QtSql4.dll and QtXml4.dll
- MS CRT merge module (Microsoft_VC90_CRT_x86.msm) - MS CRT merge module (Microsoft_VC90_CRT_x86.msm)
Build installer by giving this command line in VS command prompt (or run Build installer by giving this command line in VS command prompt (or run