code cleanup and add more tests to CheckClass::noMemset()

This commit is contained in:
Robert Reif 2011-02-24 19:59:50 -05:00
parent 51eee5f3a7
commit f596a6959e
3 changed files with 125 additions and 29 deletions

View File

@ -717,7 +717,7 @@ void CheckClass::noMemset()
unsigned int varid = tok->tokAt(3)->varId(); unsigned int varid = tok->tokAt(3)->varId();
for (const Token *lookback = tok->previous(); lookback; lookback = lookback->previous()) for (const Token *lookback = tok->previous(); lookback; lookback = lookback->previous())
{ {
if (Token::Match(lookback, "%type% %varid%",varid)) if (Token::Match(lookback, "%type% %varid%", varid))
{ {
type = lookback->str(); type = lookback->str();
break; break;
@ -731,7 +731,14 @@ void CheckClass::noMemset()
// Warn if type is a class or struct that contains any std::* variables // Warn if type is a class or struct that contains any std::* variables
const std::string pattern2(std::string("struct|class ") + type + " {"); const std::string pattern2(std::string("struct|class ") + type + " {");
for (const Token *tstruct = Token::findmatch(_tokenizer->tokens(), pattern2.c_str()); tstruct; tstruct = tstruct->next()) const Token *tstruct = Token::findmatch(_tokenizer->tokens(), pattern2.c_str());
if (!tstruct)
continue;
const std::string &typeName = tstruct->str();
for (; tstruct; tstruct = tstruct->next())
{ {
if (tstruct->str() == "}") if (tstruct->str() == "}")
break; break;
@ -751,7 +758,7 @@ void CheckClass::noMemset()
tstruct->str().find(":") != std::string::npos) tstruct->str().find(":") != std::string::npos)
{ {
if (Token::Match(tstruct->next(), "std :: %type% %var% ;")) if (Token::Match(tstruct->next(), "std :: %type% %var% ;"))
memsetStructError(tok, tok->str(), tstruct->strAt(3)); memsetError(tok, tok->str(), tstruct->strAt(3), typeName);
else if (Token::Match(tstruct->next(), "std :: %type% <")) else if (Token::Match(tstruct->next(), "std :: %type% <"))
{ {
@ -779,21 +786,16 @@ void CheckClass::noMemset()
// found error => report // found error => report
if (Token::Match(tstruct, "> %var% ;")) if (Token::Match(tstruct, "> %var% ;"))
memsetStructError(tok, tok->str(), typestr); memsetError(tok, tok->str(), typestr, typeName);
} }
} }
} }
} }
} }
void CheckClass::memsetClassError(const Token *tok, const std::string &memfunc) void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type)
{ {
reportError(tok, Severity::error, "memsetClass", "Using '" + memfunc + "' on class"); reportError(tok, Severity::error, "memsetClass", "Using '" + memfunc + "' on " + type + " that contains a 'std::" + classname + "'");
}
void CheckClass::memsetStructError(const Token *tok, const std::string &memfunc, const std::string &classname)
{
reportError(tok, Severity::error, "memsetStruct", "Using '" + memfunc + "' on struct that contains a 'std::" + classname + "'");
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -117,8 +117,7 @@ private:
void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname); void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname);
void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname); void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname);
void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname); void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname);
void memsetClassError(const Token *tok, const std::string &memfunc); void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type);
void memsetStructError(const Token *tok, const std::string &memfunc, const std::string &classname);
void operatorEqReturnError(const Token *tok); void operatorEqReturnError(const Token *tok);
void virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived); void virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived);
void thisSubtractionError(const Token *tok); void thisSubtractionError(const Token *tok);
@ -134,8 +133,7 @@ private:
c.uninitVarError(0, "classname", "varname"); c.uninitVarError(0, "classname", "varname");
c.operatorEqVarError(0, "classname", ""); c.operatorEqVarError(0, "classname", "");
c.unusedPrivateFunctionError(0, "classname", "funcname"); c.unusedPrivateFunctionError(0, "classname", "funcname");
c.memsetClassError(0, "memfunc"); c.memsetError(0, "memfunc", "classname", "class");
c.memsetStructError(0, "memfunc", "classname");
c.operatorEqReturnError(0); c.operatorEqReturnError(0);
//c.virtualDestructorError(0, "Base", "Derived"); //c.virtualDestructorError(0, "Base", "Derived");
c.thisSubtractionError(0); c.thisSubtractionError(0);

View File

@ -2908,7 +2908,52 @@ private:
void memsetOnClass() void memsetOnClass()
{ {
checkNoMemset("class A\n" checkNoMemset("class Fred\n"
"{\n"
"};\n"
"void f()\n"
"{\n"
" Fred fred;\n"
" memset(&fred, 0, sizeof(Fred));\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkNoMemset("class Fred\n"
"{\n"
" std::string b; \n"
"};\n"
"void f()\n"
"{\n"
" Fred fred;\n"
" memset(&fred, 0, sizeof(Fred));\n"
"}\n");
ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on class that contains a 'std::string'\n", errout.str());
checkNoMemset("class Fred\n"
"{\n"
"};\n"
"void f()\n"
"{\n"
" Fred fred;\n"
" memset(&fred, 0, sizeof(fred));\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkNoMemset("class Fred\n"
"{\n"
" std::string s;\n"
"};\n"
"void f()\n"
"{\n"
" Fred fred;\n"
" memset(&fred, 0, sizeof(fred));\n"
"}\n");
ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on class that contains a 'std::string'\n", errout.str());
}
void memsetOnStruct()
{
checkNoMemset("struct A\n"
"{\n" "{\n"
"};\n" "};\n"
"void f()\n" "void f()\n"
@ -2924,23 +2969,24 @@ private:
"void f()\n" "void f()\n"
"{\n" "{\n"
" struct A a;\n" " struct A a;\n"
" memset(&a, 0, sizeof(A));\n" " memset(&a, 0, sizeof(struct A));\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
}
void memsetOnStruct() checkNoMemset("struct A\n"
{
checkNoMemset("class A\n"
"{\n" "{\n"
" void g( struct sockaddr_in6& a);\n"
"private:\n"
" std::string b; \n"
"};\n" "};\n"
"void f()\n" "void f()\n"
"{\n" "{\n"
" struct sockaddr_in6 fail;\n" " struct A a;\n"
" memset(&fail, 0, sizeof(struct sockaddr_in6));\n" " memset(&a, 0, sizeof(A));\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkNoMemset("void f()\n"
"{\n"
" struct sockaddr_in6 fail;\n"
" memset(&fail, 0, sizeof(struct sockaddr_in6));\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
@ -2971,13 +3017,63 @@ private:
void memsetVector() void memsetVector()
{ {
checkNoMemset("class A\n"
"{ 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 class that contains a 'std::vector'\n", errout.str());
checkNoMemset("struct A\n" checkNoMemset("struct A\n"
"{ std::vector<int> ints; }\n" "{ std::vector<int> ints; }\n"
"\n" "\n"
"void f()\n" "void f()\n"
"{\n" "{\n"
" A a;\n" " A a;\n"
" memset(a, 0, sizeof(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"
"void f()\n"
"{\n"
" A a;\n"
" memset(&a, 0, sizeof(struct 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"
"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("class 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 class 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()); ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str());
@ -2987,7 +3083,7 @@ private:
"void f()\n" "void f()\n"
"{\n" "{\n"
" A a;\n" " A a;\n"
" memset(a, 0, sizeof(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()); ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str());
@ -2997,7 +3093,7 @@ private:
"void f()\n" "void f()\n"
"{\n" "{\n"
" A a;\n" " A a;\n"
" memset(a, 0, sizeof(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()); ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str());
} }