Fixed #8221 (ValueFlow: value for static variable that is not written)
This commit is contained in:
parent
d79762cfc3
commit
1dbcba4dd6
@ -931,6 +931,59 @@ static void valueFlowOppositeCondition(SymbolDatabase *symboldatabase, const Set
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void valueFlowGlobalStaticVar(TokenList *tokenList, const Settings *settings)
|
||||||
|
{
|
||||||
|
// Get variable values...
|
||||||
|
std::map<const Variable *, ValueFlow::Value> vars;
|
||||||
|
for (const Token *tok = tokenList->front(); tok; tok = tok->next()) {
|
||||||
|
if (!tok->variable())
|
||||||
|
continue;
|
||||||
|
// Initialization...
|
||||||
|
if (tok == tok->variable()->nameToken() &&
|
||||||
|
tok->variable()->isStatic() &&
|
||||||
|
!tok->variable()->isConst() &&
|
||||||
|
tok->valueType() &&
|
||||||
|
tok->valueType()->isIntegral() &&
|
||||||
|
tok->valueType()->pointer == 0 &&
|
||||||
|
tok->valueType()->constness == 0 &&
|
||||||
|
Token::Match(tok, "%name% =") &&
|
||||||
|
tok->next()->astOperand2() &&
|
||||||
|
tok->next()->astOperand2()->hasKnownIntValue()) {
|
||||||
|
vars[tok->variable()] = tok->next()->astOperand2()->values().front();
|
||||||
|
} else {
|
||||||
|
// If variable is written anywhere in TU then remove it from vars
|
||||||
|
if (!tok->astParent())
|
||||||
|
continue;
|
||||||
|
if (Token::Match(tok->astParent(), "++|--|&") && !tok->astParent()->astOperand2())
|
||||||
|
vars.erase(tok->variable());
|
||||||
|
else if (tok->astParent()->str() == "=") {
|
||||||
|
if (tok == tok->astParent()->astOperand1())
|
||||||
|
vars.erase(tok->variable());
|
||||||
|
else if (tokenList->isCPP() && Token::Match(tok->astParent()->tokAt(-2), "& %name% ="))
|
||||||
|
vars.erase(tok->variable());
|
||||||
|
} else if (tokenList->isCPP() && tok->astParent()->str() == ">>") {
|
||||||
|
const Token *lhs = tok->astParent();
|
||||||
|
while (Token::simpleMatch(lhs->astParent(), ">>"))
|
||||||
|
lhs = lhs->astParent();
|
||||||
|
lhs = lhs->astOperand1();
|
||||||
|
if (!lhs || !lhs->valueType() || !lhs->valueType()->isIntegral())
|
||||||
|
vars.erase(tok->variable());
|
||||||
|
} else if (Token::Match(tok->astParent(), "[(,]"))
|
||||||
|
vars.erase(tok->variable());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set values..
|
||||||
|
for (Token *tok = tokenList->front(); tok; tok = tok->next()) {
|
||||||
|
if (!tok->variable())
|
||||||
|
continue;
|
||||||
|
std::map<const Variable *, ValueFlow::Value>::const_iterator var = vars.find(tok->variable());
|
||||||
|
if (var == vars.end())
|
||||||
|
continue;
|
||||||
|
setTokenValue(tok, var->second, settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void valueFlowReverse(TokenList *tokenlist,
|
static void valueFlowReverse(TokenList *tokenlist,
|
||||||
Token *tok,
|
Token *tok,
|
||||||
const Token * const varToken,
|
const Token * const varToken,
|
||||||
@ -3169,6 +3222,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
|
|||||||
valueFlowNumber(tokenlist);
|
valueFlowNumber(tokenlist);
|
||||||
valueFlowString(tokenlist);
|
valueFlowString(tokenlist);
|
||||||
valueFlowArray(tokenlist);
|
valueFlowArray(tokenlist);
|
||||||
|
valueFlowGlobalStaticVar(tokenlist, settings);
|
||||||
valueFlowPointerAlias(tokenlist);
|
valueFlowPointerAlias(tokenlist);
|
||||||
valueFlowFunctionReturn(tokenlist, errorLogger);
|
valueFlowFunctionReturn(tokenlist, errorLogger);
|
||||||
valueFlowBitAnd(tokenlist);
|
valueFlowBitAnd(tokenlist);
|
||||||
|
@ -94,6 +94,8 @@ private:
|
|||||||
|
|
||||||
TEST_CASE(valueFlowGlobalVar);
|
TEST_CASE(valueFlowGlobalVar);
|
||||||
|
|
||||||
|
TEST_CASE(valueFlowGlobalStaticVar);
|
||||||
|
|
||||||
TEST_CASE(valueFlowInlineAssembly);
|
TEST_CASE(valueFlowInlineAssembly);
|
||||||
|
|
||||||
TEST_CASE(valueFlowUninit);
|
TEST_CASE(valueFlowUninit);
|
||||||
@ -2472,11 +2474,11 @@ private:
|
|||||||
|
|
||||||
code = "void f() {\n"
|
code = "void f() {\n"
|
||||||
" static int x = 0;\n"
|
" static int x = 0;\n"
|
||||||
" return x + 1;\n" // <- possible value
|
" return x + 1;\n" // <- known value
|
||||||
"}\n";
|
"}\n";
|
||||||
value = valueOfTok(code, "+");
|
value = valueOfTok(code, "+");
|
||||||
ASSERT_EQUALS(1, value.intvalue);
|
ASSERT_EQUALS(1, value.intvalue);
|
||||||
ASSERT(value.isPossible());
|
ASSERT(value.isKnown());
|
||||||
|
|
||||||
code = "void f() {\n"
|
code = "void f() {\n"
|
||||||
" int x = 0;\n"
|
" int x = 0;\n"
|
||||||
@ -2596,6 +2598,44 @@ private:
|
|||||||
ASSERT_EQUALS(false, testValueOfX(code, 5U, 42));
|
ASSERT_EQUALS(false, testValueOfX(code, 5U, 42));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void valueFlowGlobalStaticVar() {
|
||||||
|
const char *code;
|
||||||
|
|
||||||
|
code = "static int x = 321;\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" a = x;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 321));
|
||||||
|
|
||||||
|
code = "static int x = 321;\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" a = x;\n"
|
||||||
|
"}"
|
||||||
|
"void other() { x=a; }\n";
|
||||||
|
ASSERT_EQUALS(false, testValueOfX(code, 3U, 321));
|
||||||
|
|
||||||
|
code = "static int x = 321;\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" a = x;\n"
|
||||||
|
"}"
|
||||||
|
"void other() { p = &x; }\n";
|
||||||
|
ASSERT_EQUALS(false, testValueOfX(code, 3U, 321));
|
||||||
|
|
||||||
|
code = "static int x = 321;\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" a = x;\n"
|
||||||
|
"}"
|
||||||
|
"void other() { x++; }\n";
|
||||||
|
ASSERT_EQUALS(false, testValueOfX(code, 3U, 321));
|
||||||
|
|
||||||
|
code = "static int x = 321;\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" a = x;\n"
|
||||||
|
"}"
|
||||||
|
"void other() { foo(x); }\n";
|
||||||
|
ASSERT_EQUALS(false, testValueOfX(code, 3U, 321));
|
||||||
|
}
|
||||||
|
|
||||||
void valueFlowInlineAssembly() {
|
void valueFlowInlineAssembly() {
|
||||||
const char* code = "void f() {\n"
|
const char* code = "void f() {\n"
|
||||||
" int x = 42;\n"
|
" int x = 42;\n"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user