Fix FP with unreadVariable (#1859)
This commit is contained in:
parent
33130bdff6
commit
108cdaa485
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue