Tweaks in uninitvar, small steps to make it possible to remove the ExecutionPath
This commit is contained in:
parent
75f922e799
commit
42ed436e9d
|
@ -1200,6 +1200,17 @@ static void conditionAlwaysTrueOrFalse(const Token *tok, const std::map<unsigned
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isVariableUsed(const Token *tok, const Variable& var)
|
||||||
|
{
|
||||||
|
if (!tok)
|
||||||
|
return false;
|
||||||
|
if (tok->str() == "&" && !tok->astOperand2())
|
||||||
|
return false;
|
||||||
|
if (Token::Match(tok, "%cop%|:"))
|
||||||
|
return isVariableUsed(tok->astOperand1(),var) || isVariableUsed(tok->astOperand2(),var);
|
||||||
|
return (tok->varId() == var.declarationId());
|
||||||
|
}
|
||||||
|
|
||||||
bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var, bool * const possibleInit, bool * const noreturn, Alloc* const alloc, const std::string &membervar)
|
bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var, bool * const possibleInit, bool * const noreturn, Alloc* const alloc, const std::string &membervar)
|
||||||
{
|
{
|
||||||
const bool suppressErrors(possibleInit && *possibleInit);
|
const bool suppressErrors(possibleInit && *possibleInit);
|
||||||
|
@ -1446,8 +1457,18 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bailout on ternary operator. TODO: This can be solved much better. For example, if the variable is not accessed in the branches of the ternary operator, we could just continue.
|
|
||||||
if (tok->str() == "?") {
|
if (tok->str() == "?") {
|
||||||
|
const bool used1 = isVariableUsed(tok->astOperand2()->astOperand1(), var);
|
||||||
|
const bool used0 = isVariableUsed(tok->astOperand2()->astOperand2(), var);
|
||||||
|
const bool err = (number_of_if == 0) ? (used1 || used0) : (used1 && used0);
|
||||||
|
if (err) {
|
||||||
|
if (*alloc != NO_ALLOC)
|
||||||
|
uninitdataError(tok, var.nameToken()->str());
|
||||||
|
else
|
||||||
|
uninitvarError(tok, var.nameToken()->str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Todo: skip expression if there is no error
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1481,11 +1502,18 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
|
||||||
else if (Token::Match(tok, "sizeof|typeof|offsetof|decltype ("))
|
else if (Token::Match(tok, "sizeof|typeof|offsetof|decltype ("))
|
||||||
tok = tok->linkAt(1);
|
tok = tok->linkAt(1);
|
||||||
|
|
||||||
else if (tok->str() == "?")
|
else if (tok->str() == "?") {
|
||||||
// TODO: False negatives when "?:" is used.
|
const bool used1 = isVariableUsed(tok->astOperand2()->astOperand1(), var);
|
||||||
// Fix the tokenizer and then remove this bailout.
|
const bool used0 = isVariableUsed(tok->astOperand2()->astOperand2(), var);
|
||||||
// The tokenizer should replace "return x?y:z;" with "if(x)return y;return z;"
|
const bool err = (number_of_if == 0) ? (used1 || used0) : (used1 && used0);
|
||||||
|
if (err) {
|
||||||
|
if (*alloc != NO_ALLOC)
|
||||||
|
uninitdataError(tok, var.nameToken()->str());
|
||||||
|
else
|
||||||
|
uninitvarError(tok, var.nameToken()->str());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
}
|
}
|
||||||
|
@ -1888,6 +1916,8 @@ int CheckUninitVar::isFunctionParUsage(const Token *vartok, bool pointer, Alloc
|
||||||
return alloc == NO_ALLOC;
|
return alloc == NO_ALLOC;
|
||||||
} else {
|
} else {
|
||||||
const bool isnullbad = _settings->library.isnullargbad(start->previous(), argumentNumber + 1);
|
const bool isnullbad = _settings->library.isnullargbad(start->previous(), argumentNumber + 1);
|
||||||
|
if (!address && isnullbad && alloc == NO_ALLOC)
|
||||||
|
return true;
|
||||||
const bool isuninitbad = _settings->library.isuninitargbad(start->previous(), argumentNumber + 1);
|
const bool isuninitbad = _settings->library.isuninitargbad(start->previous(), argumentNumber + 1);
|
||||||
if (alloc != NO_ALLOC)
|
if (alloc != NO_ALLOC)
|
||||||
return isnullbad && isuninitbad;
|
return isnullbad && isuninitbad;
|
||||||
|
|
|
@ -1004,7 +1004,7 @@ private:
|
||||||
" char *c1;\n"
|
" char *c1;\n"
|
||||||
" c1=strcpy(c1,\"test\");\n"
|
" c1=strcpy(c1,\"test\");\n"
|
||||||
"}");
|
"}");
|
||||||
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: c1\n","", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: c1\n", errout.str());
|
||||||
|
|
||||||
checkUninitVarB("void f(char *c1)\n"
|
checkUninitVarB("void f(char *c1)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -2357,12 +2357,6 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
checkUninitVarB("int f(int a) {\n"
|
|
||||||
" int result;\n"
|
|
||||||
" foo() ? result = 1 : result = 0;\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
// = { .. }
|
// = { .. }
|
||||||
checkUninitVarB("int f() {\n"
|
checkUninitVarB("int f() {\n"
|
||||||
" int a;\n"
|
" int a;\n"
|
||||||
|
@ -3120,16 +3114,13 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// TODO: False negative when "?:" is used
|
|
||||||
// This should probably be fixed in the tokenizer by changing
|
|
||||||
// "return x?y:z;" to "if(x)return y;return z;"
|
|
||||||
checkUninitVar2("int f(int x) {\n"
|
checkUninitVar2("int f(int x) {\n"
|
||||||
" int a;\n"
|
" int a;\n"
|
||||||
" if (x)\n"
|
" if (x)\n"
|
||||||
" a = p;\n"
|
" a = p;\n"
|
||||||
" return y ? 2*a : 3*a;\n"
|
" return y ? 2*a : 3*a;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
TODO_ASSERT_EQUALS("error", "", errout.str());
|
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: a\n", errout.str());
|
||||||
|
|
||||||
// Unknown => bail out..
|
// Unknown => bail out..
|
||||||
checkUninitVarB("void f(int x) {\n"
|
checkUninitVarB("void f(int x) {\n"
|
||||||
|
|
Loading…
Reference in New Issue