Fix FP with unreadVariable (#1859)

This commit is contained in:
Paul Fultz II 2019-05-31 01:06:36 -05:00 committed by Daniel Marjamäki
parent 33130bdff6
commit 108cdaa485
4 changed files with 42 additions and 1 deletions

View File

@ -1457,6 +1457,8 @@ const Token *FwdAnalysis::reassign(const Token *expr, const Token *startToken, c
bool FwdAnalysis::unusedValue(const Token *expr, const Token *startToken, const Token *endToken)
{
if (isEscapedAlias(expr))
return false;
mWhat = What::UnusedValue;
Result result = check(expr, startToken, endToken);
return (result.type == FwdAnalysis::Result::Type::NONE || result.type == FwdAnalysis::Result::Type::RETURN) && !possiblyAliased(expr, startToken);
@ -1516,6 +1518,25 @@ bool FwdAnalysis::possiblyAliased(const Token *expr, const Token *startToken) co
return false;
}
bool FwdAnalysis::isEscapedAlias(const Token* expr)
{
for (const Token *subexpr = expr; subexpr; subexpr = subexpr->astOperand1()) {
for (const ValueFlow::Value &val : subexpr->values()) {
if (!val.isLocalLifetimeValue())
continue;
const Variable* var = val.tokvalue->variable();
if (!var)
continue;
if (!var->isLocal())
return true;
if (var->isArgument())
return true;
}
}
return false;
}
bool FwdAnalysis::isNullOperand(const Token *expr)
{
if (!expr)

View File

@ -206,6 +206,8 @@ public:
/** Is there some possible alias for given expression */
bool possiblyAliased(const Token *expr, const Token *startToken) const;
bool isEscapedAlias(const Token* expr);
static bool isNullOperand(const Token *expr);
private:
/** Result of forward analysis */

View File

@ -3342,7 +3342,7 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase*, ErrorLogger
valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
}
// container lifetimes
else if (tok->variable() && Token::Match(tok, "%var% . begin|cbegin|rbegin|crbegin|end|cend|rend|crend|data|c_str (")) {
else if (tok->variable() && Token::Match(tok, "%var% . begin|cbegin|rbegin|crbegin|end|cend|rend|crend|data|c_str|find (")) {
ErrorPath errorPath;
const Library::Container * container = settings->library.detectContainer(tok->variable()->typeStartToken());
if (!container)

View File

@ -33,6 +33,7 @@ private:
void run() OVERRIDE {
settings.addEnabled("style");
LOAD_LIB_2(settings.library, "std.cfg");
TEST_CASE(emptyclass); // #5355 - False positive: Variable is not assigned a value.
TEST_CASE(emptystruct); // #5355 - False positive: Variable is not assigned a value.
@ -197,6 +198,7 @@ private:
TEST_CASE(bracesInitCpp11);// #7895 - "int var{123}" initialization
TEST_CASE(argument);
TEST_CASE(escapeAlias); // #9150
}
void checkStructMemberUsage(const char code[]) {
@ -4538,6 +4540,22 @@ private:
);
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'foo.x' is assigned a value that is never used.\n", errout.str());
}
void escapeAlias() {
functionVariableUsage(
"struct A {\n"
" std::map<int, int> m;\n"
" void f(int key, int number) {\n"
" auto pos = m.find(key);\n"
" if (pos == m.end())\n"
" m.insert(std::map<int, int>::value_type(key, number));\n"
" else\n"
" (*pos).second = number;\n"
" }\n"
"};\n"
);
ASSERT_EQUALS("", errout.str());
}
};
REGISTER_TEST(TestUnusedVar)