Skip to content

Fix #8266 identicalConditionAfterEarlyExit variable modified in if-clause #3610

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 18, 2021

Conversation

chrchr-github
Copy link
Collaborator

For discussion.
This reinstates some warnings associated with #9914, which were specifically suppressed at one point. However, it sounds like the warnings are now OK again?

lib/astutils.cpp Outdated
ftok = ftok->astParent();
if (ftok && ftok->tokType() == Token::eLogicalOp)
ptok = ftok->astOperand1(); // check lhs
Copy link
Contributor

@pfultz2 pfultz2 Dec 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we moving to the lhs side of logical ops? Wont this miss the parent function call? This seems like it would jump to g in the expression f(g(x) || y) instead of f

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example looks something like if (g(b) || b), and g(b) was not considered so far.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yea but you need to check isVariableChanged on the first b and not the second b. The first b should return true and the second b should return false.

lib/astutils.cpp Outdated
if ((ftok && Token::Match(ftok->link(), ")|} !!{")) || (ptok && Token::Match(ptok->link(), ")|} !!{"))) {
bool isChanged = false, inconclusive = false;
if (ptok) {
isChanged |= isVariableChangedByFunctionCall(ptok->next(), indirect, settings, &inconclusive); // lhs can be a function
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats the reason to pass ptok->next()?

@@ -707,7 +707,8 @@ void CheckCondition::multiCondition2()
return ChildrenToVisit::op1_and_op2;

if ((!cond1->hasKnownIntValue() || !secondCondition->hasKnownIntValue()) &&
isSameExpression(mTokenizer->isCPP(), true, cond1, secondCondition, mSettings->library, true, true, &errorPath)) {
isSameExpression(mTokenizer->isCPP(), true, cond1, secondCondition, mSettings->library, true, true, &errorPath) &&
!isExpressionChangedAt(cond1, secondCondition, 0, false, mSettings, mTokenizer->isCPP())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont you need to check if the expression is changed before the secondCondtion not at the secondCondition?

Above at line 663, we check if the variables are changed in the second condition. It should probably just be changed to just use isExpressionChanged(cond1, condStartToken, condEndToken, 0, false, mSettings, mTokenizer->isCPP()).

@chrchr-github
Copy link
Collaborator Author

isVariableChanged seems to make some unstated assumptions about the code that it's operating on, which are not true for the example in #8266. I just made the minimal changes necessary to get rid of the FP (and not crash on other code). Are ftok and ptok supposed to point to function and parameters, respectively?
I'll probably look at it again next week.

@pfultz2
Copy link
Contributor

pfultz2 commented Dec 11, 2021

isVariableChanged seems to make some unstated assumptions about the code that it's operating on, which are not true for the example in #8266.

What assumptions are you talking about? isVariableChanged should return true for b in g(&b).

Are ftok and ptok supposed to point to function and parameters, respectively?

Yes, mostly. Although, it seems like we should remove this ptok adjustment and move the logic into isVariableChangedByFunctionCall. For better context, this was added in bb52a63c4e0481f5693d83770d29088cef70ea2a when const variable check was added.

@chrchr-github
Copy link
Collaborator Author

Back to the unmodified code, with the test case

void f(bool b) {
    if (b)
        return;
    if (g(&b) || b)
        return;
}

Under which circumstances is isExpressionChangedAt(tok, tok2, tok->valueType() ? tok->valueType()->pointer : 0, global, settings, cpp, depth) supposed to return true, assuming that tok points to b in if (b)? E.g. for tok2 = g, (, &, or b?

@pfultz2
Copy link
Contributor

pfultz2 commented Dec 14, 2021

Under which circumstances is isExpressionChangedAt(tok, tok2, tok->valueType() ? tok->valueType()->pointer : 0, global, settings, cpp, depth) supposed to return true

Are you referring to line 657? That is only checking for changes before the if of the second condition.

At line 663, it checks if the second condition modifies the variable or expression. Of course, its quite in adequate and should just use isExpressionChanged(cond1, condStartToken, condEndToken, 0, false, mSettings, mTokenizer->isCPP()).

assuming that tok points to b in if (b)? E.g. for tok2 = g, (, &, or b?

It should return true when tok2 is equal to b in g(&b), but the visitAstNodes will not traverse that deep. It only checks the children of || or &&.

@chrchr-github chrchr-github reopened this Dec 15, 2021
@chrchr-github
Copy link
Collaborator Author

chrchr-github commented Dec 15, 2021

Using isExpressionChanged() seems to be the right fix, thanks for the suggestion. The problem was not were I thought it was.
Edit: unrelated issue removed

@chrchr-github
Copy link
Collaborator Author

Is this OK now?

@danmar
Copy link
Owner

danmar commented Dec 18, 2021

It looks good to me. If @pfultz2 has no complaint I think we should merge it.

@pfultz2
Copy link
Contributor

pfultz2 commented Dec 18, 2021

LGTM

@danmar danmar merged commit 8df25ec into danmar:main Dec 18, 2021
@chrchr-github chrchr-github deleted the chr_Fix8266 branch April 10, 2022 21:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants