Uninitialized member variables: Improvements
This commit is contained in:
parent
d87d54339d
commit
2c6b383822
|
@ -1082,7 +1082,7 @@ void CheckUninitVar::checkScope(const Scope* scope)
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
if (stdtype || i->isPointer())
|
if (stdtype || i->isPointer())
|
||||||
checkScopeForVariable(scope, tok, *i, NULL, NULL, NULL);
|
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 std::string structname(i->typeStartToken()->next()->str());
|
||||||
const SymbolDatabase * symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase * symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
for (std::size_t j = 0U; j < symbolDatabase->classAndStructScopes.size(); ++j) {
|
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..
|
// variable is seen..
|
||||||
if (tok->varId() == var.varId()) {
|
if (tok->varId() == var.varId()) {
|
||||||
if (membervar) {
|
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;
|
return true;
|
||||||
else if (Token::Match(tok, "%var% ="))
|
else if (tok->strAt(1) == "=")
|
||||||
|
return true;
|
||||||
|
else if (tok->strAt(-1) == "&")
|
||||||
return true;
|
return true;
|
||||||
else if (Token::Match(tok->previous(), "[(,] %var% [,)]") && isVariableUsage(scope, tok, var.isPointer()))
|
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 {
|
} else {
|
||||||
// Use variable
|
// Use variable
|
||||||
if (!suppressErrors && isVariableUsage(scope, tok, var.isPointer()))
|
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);
|
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.");
|
||||||
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ public:
|
||||||
void uninitstringError(const Token *tok, const std::string &varname, bool strncpy_);
|
void uninitstringError(const Token *tok, const std::string &varname, bool strncpy_);
|
||||||
void uninitdataError(const Token *tok, const std::string &varname);
|
void uninitdataError(const Token *tok, const std::string &varname);
|
||||||
void uninitvarError(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:
|
private:
|
||||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||||
|
@ -94,6 +95,7 @@ private:
|
||||||
c.uninitstringError(0, "varname", true);
|
c.uninitstringError(0, "varname", true);
|
||||||
c.uninitdataError(0, "varname");
|
c.uninitdataError(0, "varname");
|
||||||
c.uninitvarError(0, "varname");
|
c.uninitvarError(0, "varname");
|
||||||
|
c.uninitStructMemberError(0, "a.b");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string myName() {
|
static std::string myName() {
|
||||||
|
|
|
@ -1944,6 +1944,7 @@ private:
|
||||||
|
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings.experimental = experimental;
|
settings.experimental = experimental;
|
||||||
|
settings.addEnabled("style");
|
||||||
|
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
@ -2561,7 +2562,7 @@ private:
|
||||||
" ab.a = 0;\n"
|
" ab.a = 0;\n"
|
||||||
" do_something(ab);\n"
|
" do_something(ab);\n"
|
||||||
"}\n", "test.c", true);
|
"}\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"
|
checkUninitVar2("struct AB { int a; int b; };\n"
|
||||||
"void do_something(const struct AB ab);\n"
|
"void do_something(const struct AB ab);\n"
|
||||||
|
@ -2581,6 +2582,30 @@ private:
|
||||||
" do_something(ab);\n"
|
" do_something(ab);\n"
|
||||||
"}\n", "test.c", true);
|
"}\n", "test.c", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
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());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue