Uninitialized member variables: Improvements

This commit is contained in:
Daniel Marjamäki 2013-01-17 21:04:22 +01:00
parent d87d54339d
commit 2c6b383822
3 changed files with 45 additions and 5 deletions

View File

@ -1082,7 +1082,7 @@ void CheckUninitVar::checkScope(const Scope* scope)
tok = tok->next();
if (stdtype || i->isPointer())
checkScopeForVariable(scope, tok, *i, NULL, NULL, NULL);
if (_settings->experimental && Token::Match(i->typeStartToken(), "struct %type% %var% ;")) {
if (_settings->experimental && _settings->isEnabled("style") && Token::Match(i->typeStartToken(), "struct %type% %var% ;")) {
const std::string structname(i->typeStartToken()->next()->str());
const SymbolDatabase * symbolDatabase = _tokenizer->getSymbolDatabase();
for (std::size_t j = 0U; j < symbolDatabase->classAndStructScopes.size(); ++j) {
@ -1343,12 +1343,14 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
// variable is seen..
if (tok->varId() == var.varId()) {
if (membervar) {
if (Token::Match(tok, "%var% . %var% =") && tok->strAt(2) == membervar->name())
if (Token::Match(tok, "%var% . %var% [=.[]") && tok->strAt(2) == membervar->name())
return true;
else if (Token::Match(tok, "%var% ="))
else if (tok->strAt(1) == "=")
return true;
else if (tok->strAt(-1) == "&")
return true;
else if (Token::Match(tok->previous(), "[(,] %var% [,)]") && isVariableUsage(scope, tok, var.isPointer()))
uninitvarError(tok, tok->str() + "." + membervar->name());
uninitStructMemberError(tok, tok->str() + "." + membervar->name());
} else {
// Use variable
if (!suppressErrors && isVariableUsage(scope, tok, var.isPointer()))
@ -1512,3 +1514,14 @@ void CheckUninitVar::uninitvarError(const Token *tok, const std::string &varname
{
reportError(tok, Severity::error, "uninitvar", "Uninitialized variable: " + varname);
}
void CheckUninitVar::uninitStructMemberError(const Token *tok, const std::string &membername)
{
reportError(tok,
Severity::warning,
"uninitStructMember",
"Perhaps '" + membername + "' should be initialized before calling function.\n"
"The struct is not fully initialized, '" + membername + "' hasn't been initialized. "
"Using the struct in function call might be dangerous, unless you know for sure that the member "
"will not be used by the function.");
}

View File

@ -85,6 +85,7 @@ public:
void uninitstringError(const Token *tok, const std::string &varname, bool strncpy_);
void uninitdataError(const Token *tok, const std::string &varname);
void uninitvarError(const Token *tok, const std::string &varname);
void uninitStructMemberError(const Token *tok, const std::string &membername);
private:
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
@ -94,6 +95,7 @@ private:
c.uninitstringError(0, "varname", true);
c.uninitdataError(0, "varname");
c.uninitvarError(0, "varname");
c.uninitStructMemberError(0, "a.b");
}
static std::string myName() {

View File

@ -1944,6 +1944,7 @@ private:
Settings settings;
settings.experimental = experimental;
settings.addEnabled("style");
// Tokenize..
Tokenizer tokenizer(&settings, this);
@ -2561,7 +2562,7 @@ private:
" ab.a = 0;\n"
" do_something(ab);\n"
"}\n", "test.c", true);
ASSERT_EQUALS("[test.c:6]: (error) Uninitialized variable: ab.b\n", errout.str());
ASSERT_EQUALS("[test.c:6]: (warning) Perhaps 'ab.b' should be initialized before calling function.\n", errout.str());
checkUninitVar2("struct AB { int a; int b; };\n"
"void do_something(const struct AB ab);\n"
@ -2581,6 +2582,30 @@ private:
" do_something(ab);\n"
"}\n", "test.c", true);
ASSERT_EQUALS("", errout.str());
checkUninitVar2("struct AB { int a; struct { int b; int c; } s; };\n"
"void do_something(const struct AB ab);\n"
"void f(void) {\n"
" struct AB ab;\n"
" ab.a = 1;\n"
" ab.s.b = 2;\n"
" ab.s.c = 3;\n"
" do_something(ab);\n"
"}\n", "test.c", true);
ASSERT_EQUALS("", errout.str());
checkUninitVar2("struct conf {\n"
" char x;\n"
"};\n"
"\n"
"void do_something(struct conf ant_conf);\n"
"\n"
"void f(void) {\n"
" struct conf c;\n"
" initdata(&c);\n"
" do_something(c);\n"
"}\n", "test.c", true);
ASSERT_EQUALS("", errout.str());
}
};