CheckClass::noMemset: Refactoring so it handles more complex std template types

This commit is contained in:
Daniel Marjamäki 2010-02-04 21:49:58 +01:00
parent da7e75f69e
commit 9e6ea07c14
2 changed files with 51 additions and 6 deletions

View File

@ -752,16 +752,51 @@ void CheckClass::noMemset()
if (tstruct->str() == "}")
break;
if (Token::Match(tstruct, "std :: %type% %var% ;"))
// struct with function? skip function body..
if (Token::simpleMatch(tstruct, ") {"))
{
memsetStructError(tok, tok->str(), tstruct->strAt(2));
tstruct = tstruct->next()->link();
if (!tstruct)
break;
}
if (Token::Match(tstruct, "std :: %type% < %type% *| > %var% ;"))
// before a statement there must be either:
// * private:|protected:|public:
// * { } ;
if (Token::Match(tstruct, "[;{}]") ||
tstruct->str().find(":") != std::string::npos)
{
memsetStructError(tok, tok->str(), tstruct->strAt(2));
if (Token::Match(tstruct->next(), "std :: %type% %var% ;"))
memsetStructError(tok, tok->str(), tstruct->strAt(3));
else if (Token::Match(tstruct->next(), "std :: %type% < "))
{
// backup the type
const std::string typestr(tstruct->strAt(3));
// check if it's a pointer variable..
unsigned int level = 0;
while (0 != (tstruct = tstruct->next()))
{
if (tstruct->str() == "<")
++level;
else if (tstruct->str() == ">")
{
if (level <= 1)
break;
--level;
}
else if (tstruct->str() == "(")
tstruct = tstruct->link();
}
if (!tstruct)
break;
// found error => report
if (Token::Match(tstruct, "> %var% ;"))
memsetStructError(tok, tok->str(), typestr);
}
}
}
}

View File

@ -1493,6 +1493,16 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str());
checkNoMemset("struct A\n"
"{ std::vector< std::vector<int> > ints; }\n"
"\n"
"void f()\n"
"{\n"
" A a;\n"
" memset(a, 0, sizeof(A));\n"
"}");
ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str());
checkNoMemset("struct A\n"
"{ std::vector<int *> ints; }\n"
"\n"