Skip to content

Commit 9191e6f

Browse files
committed
Fixed cppcheck-opensource#8246 (ValueFlow: known value, function pointer argument)
1 parent 5cfa13c commit 9191e6f

2 files changed

Lines changed: 62 additions & 24 deletions

File tree

lib/valueflow.cpp

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,34 @@ static void bailoutInternal(TokenList *tokenlist, ErrorLogger *errorLogger, cons
108108
#define bailout(tokenlist, errorLogger, tok, what) bailoutInternal(tokenlist, errorLogger, tok, what, __FILE__, __LINE__, "(valueFlow)")
109109
#endif
110110

111+
static void changeKnownToPossible(std::list<ValueFlow::Value> &values)
112+
{
113+
std::list<ValueFlow::Value>::iterator it;
114+
for (it = values.begin(); it != values.end(); ++it)
115+
it->changeKnownToPossible();
116+
}
117+
118+
static bool mightBeNonConstPointerFunctionArg(const Token *tok)
119+
{
120+
// TODO: check if argument might be non-const pointer
121+
const Token *parent = tok->astParent();
122+
while (parent && parent->str() == ",")
123+
parent = parent->astParent();
124+
return (parent && Token::Match(parent->previous(), "%name% ("));
125+
}
126+
127+
static const Token *findVariableInAST(const Token *tok, unsigned int varid)
128+
{
129+
if (!tok)
130+
return nullptr;
131+
if (tok->varId() == varid)
132+
return tok;
133+
const Token *ret1 = findVariableInAST(tok->astOperand1(), varid);
134+
if (ret1)
135+
return ret1;
136+
return findVariableInAST(tok->astOperand2(), varid);
137+
}
138+
111139
/**
112140
* Is condition always false when variable has given value?
113141
* \param condition top ast token in condition
@@ -1465,9 +1493,7 @@ static bool valueFlowForward(Token * const startToken,
14651493
Token::simpleMatch(tok2->link()->previous(), "else {") &&
14661494
!isReturnScope(tok2->link()->tokAt(-2)) &&
14671495
isVariableChanged(tok2->link(), tok2, varid, var->isGlobal(), settings)) {
1468-
std::list<ValueFlow::Value>::iterator it;
1469-
for (it = values.begin(); it != values.end(); ++it)
1470-
it->changeKnownToPossible();
1496+
changeKnownToPossible(values);
14711497
}
14721498
}
14731499

@@ -1482,8 +1508,7 @@ static bool valueFlowForward(Token * const startToken,
14821508
}
14831509

14841510
if (Token::Match(tok2, "[;{}] %name% :") || tok2->str() == "case") {
1485-
for (std::list<ValueFlow::Value>::iterator it = values.begin(); it != values.end(); ++it)
1486-
it->changeKnownToPossible();
1511+
changeKnownToPossible(values);
14871512
tok2 = tok2->tokAt(2);
14881513
continue;
14891514
}
@@ -1597,10 +1622,7 @@ static bool valueFlowForward(Token * const startToken,
15971622

15981623
if (!condAlwaysFalse && isVariableChanged(startToken1, startToken1->link(), varid, var->isGlobal(), settings)) {
15991624
removeValues(values, truevalues);
1600-
1601-
std::list<ValueFlow::Value>::iterator it;
1602-
for (it = values.begin(); it != values.end(); ++it)
1603-
it->changeKnownToPossible();
1625+
changeKnownToPossible(values);
16041626
}
16051627

16061628
// goto '}'
@@ -1628,10 +1650,7 @@ static bool valueFlowForward(Token * const startToken,
16281650

16291651
if (!condAlwaysTrue && isVariableChanged(startTokenElse, startTokenElse->link(), varid, var->isGlobal(), settings)) {
16301652
removeValues(values, falsevalues);
1631-
1632-
std::list<ValueFlow::Value>::iterator it;
1633-
for (it = values.begin(); it != values.end(); ++it)
1634-
it->changeKnownToPossible();
1653+
changeKnownToPossible(values);
16351654
}
16361655

16371656
// goto '}'
@@ -1811,9 +1830,7 @@ static bool valueFlowForward(Token * const startToken,
18111830
if (tok2 == endToken)
18121831
break;
18131832
--indentlevel;
1814-
for (std::list<ValueFlow::Value>::iterator it = values.begin(); it != values.end(); ++it) {
1815-
it->changeKnownToPossible();
1816-
}
1833+
changeKnownToPossible(values);
18171834
continue;
18181835
}
18191836
}
@@ -1841,6 +1858,8 @@ static bool valueFlowForward(Token * const startToken,
18411858
std::list<ValueFlow::Value>::const_iterator it;
18421859
for (it = values.begin(); it != values.end(); ++it)
18431860
valueFlowAST(const_cast<Token*>(expr), varid, *it, settings);
1861+
if ((expr->valueType() && expr->valueType()->pointer) && mightBeNonConstPointerFunctionArg(tok2) && findVariableInAST(expr,varid))
1862+
changeKnownToPossible(values);
18441863
} else {
18451864
std::list<ValueFlow::Value>::const_iterator it;
18461865
for (it = values.begin(); it != values.end(); ++it) {
@@ -1852,6 +1871,9 @@ static bool valueFlowForward(Token * const startToken,
18521871
else
18531872
valueFlowAST(const_cast<Token*>(op2), varid, *it, settings);
18541873
}
1874+
1875+
if (mightBeNonConstPointerFunctionArg(tok2) && findVariableInAST(op2,varid))
1876+
changeKnownToPossible(values);
18551877
}
18561878

18571879
// Skip conditional expressions..
@@ -2245,11 +2267,8 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat
22452267
}
22462268

22472269
// Static variable initialisation?
2248-
if (var->isStatic() && var->nameToken() == tok->astOperand1()) {
2249-
for (std::list<ValueFlow::Value>::iterator it = values.begin(); it != values.end(); ++it) {
2250-
it->changeKnownToPossible();
2251-
}
2252-
}
2270+
if (var->isStatic() && var->nameToken() == tok->astOperand1())
2271+
changeKnownToPossible(values);
22532272

22542273
// Skip RHS
22552274
const Token * nextExpression = nextAfterAstRightmostLeaf(tok);
@@ -3057,9 +3076,7 @@ static void valueFlowSubFunction(TokenList *tokenlist, ErrorLogger *errorLogger,
30573076
}
30583077

30593078
// passed values are not "known"..
3060-
for (std::list<ValueFlow::Value>::iterator it = argvalues.begin(); it != argvalues.end(); ++it) {
3061-
it->changeKnownToPossible();
3062-
}
3079+
changeKnownToPossible(argvalues);
30633080

30643081
valueFlowInjectParameter(tokenlist, errorLogger, settings, argvar, calledFunctionScope, argvalues);
30653082
}

test/testvalueflow.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2390,6 +2390,27 @@ class TestValueFlow : public TestFixture {
23902390
"}";
23912391
ASSERT(isNotKnownValues(code, "+"));
23922392

2393+
code = "void f() {\n"
2394+
" int x = 0;\n"
2395+
" dostuff(&x);\n"
2396+
" if (x < 0) {}\n"
2397+
"}\n";
2398+
ASSERT(isNotKnownValues(code, "<"));
2399+
2400+
code = "void f() {\n"
2401+
" int x = 0;\n"
2402+
" dostuff(0 ? ptr : &x);\n"
2403+
" if (x < 0) {}\n"
2404+
"}\n";
2405+
ASSERT(isNotKnownValues(code, "<"));
2406+
2407+
code = "void f() {\n"
2408+
" int x = 0;\n"
2409+
" dostuff(unknown ? ptr : &x);\n"
2410+
" if (x < 0) {}\n"
2411+
"}\n";
2412+
ASSERT(isNotKnownValues(code, "<"));
2413+
23932414
code = "void f() {\n"
23942415
" int x = 0;\n"
23952416
" fred.dostuff(x);\n"

0 commit comments

Comments
 (0)