Fixed #5116 (false positive: memset on class (nested struct))

This commit is contained in:
Daniel Marjamäki 2013-11-18 16:56:00 +01:00
parent 033cb19656
commit ff5f223a1d
3 changed files with 28 additions and 5 deletions

View File

@ -898,7 +898,7 @@ static const Scope* findFunctionOf(const Scope* scope)
return 0; return 0;
} }
void CheckClass::noMemset() void CheckClass::checkMemset()
{ {
const std::size_t functions = symbolDatabase->functionScopes.size(); const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) { for (std::size_t i = 0; i < functions; ++i) {
@ -949,6 +949,20 @@ void CheckClass::noMemset()
if (derefs == 0) if (derefs == 0)
type = var->typeScope(); type = var->typeScope();
// TODO: The SymbolDatabase mix up variables in nested structs.
// So we must bailout right now if there are nested structs.
bool bailout = false;
for (const Token *typetok2 = var->typeStartToken(); typetok2 && typetok2 != var->typeEndToken(); typetok2 = typetok2->next()) {
if (typetok2->str() == "::")
bailout = true;
if (typetok2->str() == "{") {
bailout = false;
break;
}
}
if (bailout)
continue;
} }
} }

View File

@ -50,7 +50,7 @@ public:
CheckClass checkClass(tokenizer, settings, errorLogger); CheckClass checkClass(tokenizer, settings, errorLogger);
// can't be a simplified check .. the 'sizeof' is used. // can't be a simplified check .. the 'sizeof' is used.
checkClass.noMemset(); checkClass.checkMemset();
} }
/** @brief Run checks on the simplified token list */ /** @brief Run checks on the simplified token list */
@ -93,7 +93,7 @@ public:
* It can also overwrite the virtual table. * It can also overwrite the virtual table.
* Important: The checking doesn't work on simplified tokens list. * Important: The checking doesn't work on simplified tokens list.
*/ */
void noMemset(); void checkMemset();
void checkMemsetType(const Scope *start, const Token *tok, const Scope *type, bool allocation); void checkMemsetType(const Scope *start, const Token *tok, const Scope *type, bool allocation);
/** @brief 'operator=' should return something and it should not be const. */ /** @brief 'operator=' should return something and it should not be const. */

View File

@ -2042,7 +2042,7 @@ private:
// Check.. // Check..
CheckClass checkClass(&tokenizer, &settings, this); CheckClass checkClass(&tokenizer, &settings, this);
checkClass.noMemset(); checkClass.checkMemset();
} }
void memsetOnClass() { void memsetOnClass() {
@ -2219,7 +2219,7 @@ private:
" n1::Fred fred;\n" " n1::Fred fred;\n"
" memset(&fred, 0, sizeof(fred));\n" " memset(&fred, 0, sizeof(fred));\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:10]: (error) Using 'memset' on class that contains a 'std::string'.\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:10]: (error) Using 'memset' on class that contains a 'std::string'.\n", "", errout.str());
checkNoMemset("class A {\n" checkNoMemset("class A {\n"
" virtual ~A() { }\n" " virtual ~A() { }\n"
@ -2231,6 +2231,15 @@ private:
" memset(arr, 0, N * sizeof(A*));\n" " memset(arr, 0, N * sizeof(A*));\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkNoMemset("class A {\n" // #5116 - nested class data is mixed in the SymbolDatabase
" std::string s;\n"
" struct B { int x; };\n"
"};\n"
"void f(A::B *b) {\n"
" memset(b,0,4);\n"
"}");
ASSERT_EQUALS("", errout.str());
} }
void memsetOnStruct() { void memsetOnStruct() {