-
Notifications
You must be signed in to change notification settings - Fork 1.5k
fix #5591: Add check for meaningless comma operator in if statement, misplaced ')' #7406
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
base: main
Are you sure you want to change the base?
Conversation
53083da
to
1687100
Compare
Thanks for your contribution. Note that these issues seem to be diagnosed already by current compilers. |
Hi CHR, many thanks for your comments, and I have updated the commit. But there is a failed case tested on the github for the commit, that seems not the problem of the committed code. Seems the network traffic caused a overtime. But I am not sure. Do you know how to trigger the checks to run again? Thanks a lot! |
The macos runners can be very slow sometimes. I have restarted the failing run. |
Makefile
Outdated
@@ -204,6 +204,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ | |||
$(libcppdir)/checkleakautovar.o \ | |||
$(libcppdir)/checkmemoryleak.o \ | |||
$(libcppdir)/checknullpointer.o \ | |||
$(libcppdir)/checkoperatorcomma.o \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want that we have files with just 1 checker. With this filename it's hard to see that more checkers would be added later. I suggest that your checker is added in checkother instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or make the name more generic so more checkers can be added in it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Danmar, yes, it is not a common check, so it is better to add the checker to checkother.cpp.
lib/checkoperatorcomma.cpp
Outdated
const Token * parent = tok->astParent(); | ||
if (parent && (Token::simpleMatch(parent->previous(), "if (") || | ||
Token::simpleMatch(parent->previous(), "while ("))) { | ||
assertWithSuspiciousCommaError(tok); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it looks strange to me that assertWithSuspiciousComma
is reported when there is no assert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Danmar, I will use the word warn instead of using assert.
lib/checkoperatorcomma.cpp
Outdated
parent = parent->astParent(); | ||
if (Token::simpleMatch(parent->previous(), "for (")) { | ||
if (tok->index() < tok->astParent()->index()) { | ||
assertWithSuspiciousCommaError(tok); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have the feeling this could be noisy. Maybe you want to increment two variables in the third expression and then a comma seems natural.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Danmar, this is to check the condition judgment part of the 'for' statement, and I can make it more straightforward. But if we make the checker focusing on a very specific case, maybe it is not needed for a 'for' statement.
the PR description says that you want to detect:
well yes that looks like a possible bug. there seems to be misplaced parenthesis but I fear your checker is much more verbose. you warn whenever there is a comma in a if/while. no matter if there are function calls. If the condition says:
I agree the code looks weird.. but it's not a likely misplaced parenthesis and I am not convinced that the comma is a bug. It looks intentional. |
I also want to point out that misra has a rule that forbids comma operators. But I still feel sympathy for this checker if we make it more specific and it can detect actual bugs and not just warn about random comma operators. |
Hi Danmer, according to the description of the bug 5591, seems the user just want the cppcheck to help to give some warning to avoid unintended spelling mistakes which are grammatically correct. But it is a logical error during running. So maybe it is a little difficult to completely decide if the code is intended or not by a static analysis. Maybe we can find out the most likely possibility and provide a warning. The case described on the bug usually happened when using a function with default arguments, as the default arguments might be ignored and misplaced outside the parentheses. So is it ok that we just focus on the functions with default args called in an if or while condition statement? |
7219b70
to
74a9515
Compare
yeah.. and when you say "a little difficult" you probably mean "impossible" right ? :-) our approach is to make the checker "passive" then and warn only about the most obvious bugs. and I think your suggestion resonate well with that.
Yes that sounds much better to me. If such function appear immediately before the comma operator then I would think it seems fair to write a warning. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- please add some tests also in the testother.cpp
- update CheckOther::getErrorMessages
- update classInfo in checkother.h
lib/checkother.cpp
Outdated
if (parent && (Token::simpleMatch(parent->previous(), "if (") || | ||
Token::simpleMatch(parent->previous(), "while ("))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can write Token::Match(parent->previous(), "if|while (")
instead
lib/checkother.cpp
Outdated
const Token * parent = tok->astParent(); | ||
if (parent && (Token::simpleMatch(parent->previous(), "if (") || | ||
Token::simpleMatch(parent->previous(), "while ("))) { | ||
if (tok->previous()->str() == ")" && tok->previous()->link()->str() == "(") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like overall to be over-explicit. but this && tok->previous()->link()->str() == "("
is too redundant please remove that.
lib/checkother.cpp
Outdated
const Function * func = tok->previous()->link()->previous()->function(); | ||
if (func && func->initArgCount > 0) { | ||
const Token * r_op = tok->astOperand2(); | ||
if (r_op && r_op->hasKnownValue()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
explain why there must be a known value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Danmar, sorry, that code is thoughtless. I will update the commit. I make a sample to explain my thinking.
int func(int a, int b = 100) {
return 1;
}
int main() {
int x = 200;
int y = 100;
if (func(100), x) {} //case 1, report warning
if (func(100), true) {} //case 2, report warning
if (func(100), 100) {} //case 3, report warning
if (func(100), func(100)) {} //case 4, not report warning
if (func(100), x + y) {} //case 5, not report warning
return 100;
}
For case 4 and case 5, seems the programmer is more likely intended to do that. But I am not quite sure about that.
you don't have to do it in this PR but I think this warning could be more generic and written for other statements also. Example:
It should check that the comma is inside parentheses. |
Use |
Hi CHR, thanks a lot for your help! With the latest submit, the github report test failures. It is caused by running the testrunner. But all the tests can be passed when I run the testrunner locally on my pc.
Local:
Do you know what's the reason? Thanks! |
Maybe you need to rebase onto main? I think there were some recent changes involving the column number. |
68c021b
to
35ed502
Compare
should be |
https://trac.cppcheck.net/ticket/5591
Description:
int f2(int, int = 0) {....}
void f()
{
if(f2(0), 0) //actually mean f2(0, 0)
{
....
}
}