Fix 9760: False positive: constParameter on parameter used to take non-const pointer via array decaying (#3660)
This commit is contained in:
parent
71a44395c8
commit
01a8890d6d
|
@ -2326,28 +2326,40 @@ static bool isExpressionChangedAt(const F& getExprTok,
|
||||||
bool cpp,
|
bool cpp,
|
||||||
int depth)
|
int depth)
|
||||||
{
|
{
|
||||||
|
if (depth < 0)
|
||||||
|
return true;
|
||||||
if (tok->exprId() != exprid) {
|
if (tok->exprId() != exprid) {
|
||||||
if (globalvar && Token::Match(tok, "%name% ("))
|
if (globalvar && Token::Match(tok, "%name% ("))
|
||||||
// TODO: Is global variable really changed by function call?
|
// TODO: Is global variable really changed by function call?
|
||||||
return true;
|
return true;
|
||||||
// Is aliased function call or alias passed to function
|
const bool pointer = astIsPointer(tok);
|
||||||
if ((Token::Match(tok, "%var% (") || isVariableChangedByFunctionCall(tok, 1, settings)) &&
|
bool aliased = false;
|
||||||
std::any_of(tok->values().begin(), tok->values().end(), std::mem_fn(&ValueFlow::Value::isLifetimeValue))) {
|
// If we can't find the expression then assume it is an alias
|
||||||
bool aliased = false;
|
if (!getExprTok())
|
||||||
// If we can't find the expression then assume it was modified
|
aliased = true;
|
||||||
if (!getExprTok())
|
if (!aliased) {
|
||||||
return true;
|
aliased = findAstNode(getExprTok(), [&](const Token* childTok) {
|
||||||
visitAstNodes(getExprTok(), [&](const Token* childTok) {
|
for (const ValueFlow::Value& val : tok->values()) {
|
||||||
if (childTok->varId() > 0 && isAliasOf(tok, childTok->varId())) {
|
if (val.isImpossible())
|
||||||
aliased = true;
|
continue;
|
||||||
return ChildrenToVisit::done;
|
if (val.isLocalLifetimeValue() || (pointer && val.isSymbolicValue() && val.intvalue == 0)) {
|
||||||
|
if (findAstNode(val.tokvalue,
|
||||||
|
[&](const Token* aliasTok) {
|
||||||
|
return aliasTok->exprId() == childTok->exprId();
|
||||||
|
}))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ChildrenToVisit::op1_and_op2;
|
return false;
|
||||||
});
|
});
|
||||||
// TODO: Try to traverse the lambda function
|
|
||||||
if (aliased)
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (!aliased)
|
||||||
|
return false;
|
||||||
|
if (isVariableChanged(tok, 1, settings, cpp, depth))
|
||||||
|
return true;
|
||||||
|
// TODO: Try to traverse the lambda function
|
||||||
|
if (Token::Match(tok, "%var% ("))
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (isVariableChanged(tok, indirect, settings, cpp, depth));
|
return (isVariableChanged(tok, indirect, settings, cpp, depth));
|
||||||
|
@ -2398,7 +2410,7 @@ bool isVariableChanged(const Variable * var, const Settings *settings, bool cpp,
|
||||||
return false;
|
return false;
|
||||||
if (Token::Match(start, "; %varid% =", var->declarationId()))
|
if (Token::Match(start, "; %varid% =", var->declarationId()))
|
||||||
start = start->tokAt(2);
|
start = start->tokAt(2);
|
||||||
return isVariableChanged(start->next(), var->scope()->bodyEnd, var->declarationId(), var->isGlobal(), settings, cpp, depth);
|
return isExpressionChanged(var->nameToken(), start->next(), var->scope()->bodyEnd, settings, cpp, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isVariablesChanged(const Token* start,
|
bool isVariablesChanged(const Token* start,
|
||||||
|
@ -2458,6 +2470,8 @@ bool isThisChanged(const Token* start, const Token* end, int indirect, const Set
|
||||||
|
|
||||||
bool isExpressionChanged(const Token* expr, const Token* start, const Token* end, const Settings* settings, bool cpp, int depth)
|
bool isExpressionChanged(const Token* expr, const Token* start, const Token* end, const Settings* settings, bool cpp, int depth)
|
||||||
{
|
{
|
||||||
|
if (depth < 0)
|
||||||
|
return true;
|
||||||
if (!precedes(start, end))
|
if (!precedes(start, end))
|
||||||
return false;
|
return false;
|
||||||
const Token* result = findAstNode(expr, [&](const Token* tok) {
|
const Token* result = findAstNode(expr, [&](const Token* tok) {
|
||||||
|
|
|
@ -2623,6 +2623,10 @@ private:
|
||||||
check("struct S { void f(); int i; };\n"
|
check("struct S { void f(); int i; };\n"
|
||||||
"void call_f(S& s) { (s.*(&S::f))(); }\n");
|
"void call_f(S& s) { (s.*(&S::f))(); }\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("struct S { int a[1]; };\n"
|
||||||
|
"void f(S& s) { int* p = s.a; *p = 0; }\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void constParameterCallback() {
|
void constParameterCallback() {
|
||||||
|
|
Loading…
Reference in New Issue