diff --git a/lib/vf_settokenvalue.cpp b/lib/vf_settokenvalue.cpp index c4d32691422..e7b715ab36b 100644 --- a/lib/vf_settokenvalue.cpp +++ b/lib/vf_settokenvalue.cpp @@ -216,6 +216,25 @@ namespace ValueFlow return false; } + static bool isFunctionCall(const Token* tok, const Settings& settings) + { + if (!tok) + return false; + if (tok->str() == "{") + return true; + if (tok->str() == "(") { + if (tok->astOperand1() && tok->astOperand1()->isControlFlowKeyword()) + return false; + if (Token::Match(tok->next(), "%name%") && !settings.library.isNotLibraryFunction(tok->next())) + return true; + if (Token::Match(tok->previous(), "%name%|>")) + return true; + if (Token::Match(tok->astOperand1(), "%name%|(|[|*|.")) + return true; + } + return false; + } + /** set ValueFlow value and perform calculations if possible */ void setTokenValue(Token* tok, Value value, @@ -254,9 +273,7 @@ namespace ValueFlow return !Token::simpleMatch(p, ","); }); // Ensure that the comma isn't a function call - if (!callParent || (!Token::Match(callParent->previous(), "%name%|> (") && !Token::simpleMatch(callParent, "{") && - (!Token::Match(callParent, "( %name%") || settings.library.isNotLibraryFunction(callParent->next())) && - !(callParent->str() == "(" && Token::Match(callParent->astOperand1(), "%name%|(|[|*|.")))) { + if (!isFunctionCall(callParent, settings)) { setTokenValue(parent, std::move(value), settings); return; } diff --git a/test/testcondition.cpp b/test/testcondition.cpp index abef2d95614..37efa4f8091 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -5011,6 +5011,14 @@ class TestCondition : public TestFixture { "[test.cpp:9:9]: (style) Condition '0b101010' is always true [knownConditionTrueFalse]\n" "[test.cpp:10:9]: (style) Condition '!42' is always false [knownConditionTrueFalse]\n", errout_str()); + + check("bool g(int = 1) __attribute__((pure));\n" + "void f() {\n" + " int n = 0;\n" + " if (g(), n) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4:12]: (style) Condition 'g(),n' is always false [knownConditionTrueFalse]\n", + errout_str()); } void alwaysTrueSymbolic() diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 3609bf2aee2..b8496c863d5 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -1887,6 +1887,16 @@ class TestValueFlow : public TestFixture { "}\n"; values = tokenValues(code, ","); ASSERT_EQUALS(0U, values.size()); + + code = "void f() {\n" + " int a = 4;\n" + " if (g(), a) {}\n" + "}\n"; + values = tokenValues(code, ","); + ASSERT_EQUALS(1U, values.size()); + ASSERT(values.front().isKnown()); + ASSERT(values.front().isIntValue()); + ASSERT_EQUALS(4, values.front().intvalue); } void valueFlowErrorPath() {