diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 5f35f443cbf..ccc87d9364a 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -1782,15 +1782,39 @@ void CheckCondition::checkPointerAdditionResultNotNull() if (tok->isExpandedMacro()) continue; - const Token *calcToken, *exprToken; + const Token *calcToken = nullptr, *exprToken = nullptr; if (tok->astOperand1()->str() == "+") { calcToken = tok->astOperand1(); exprToken = tok->astOperand2(); } else if (tok->astOperand2()->str() == "+") { calcToken = tok->astOperand2(); exprToken = tok->astOperand1(); - } else - continue; + } else { + const Token *pointerToken = nullptr; + if (tok->astOperand1()->variable() && tok->astOperand1()->variable()->isPointer()) + pointerToken = tok->astOperand1(); + else if (tok->astOperand2()->variable() && tok->astOperand2()->variable()->isPointer()) + pointerToken = tok->astOperand2(); + + if (!pointerToken) + continue; + + const std::list &tokenValues = pointerToken->values(); + for (const ValueFlow::Value &val : tokenValues) { + if (val.isSymbolicValue()) { + if (val.tokvalue->str() == "+") { + calcToken = val.tokvalue; + if (pointerToken == tok->astOperand1()) + exprToken = tok->astOperand2(); + else + exprToken = tok->astOperand1(); + break; + } + } + } + if (!calcToken || !exprToken) + continue; + } // pointer comparison against NULL (ptr+12==0) if (calcToken->hasKnownIntValue()) diff --git a/test/testcondition.cpp b/test/testcondition.cpp index ffeca5c5be7..aa169c01c55 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -6026,6 +6026,18 @@ class TestCondition : public TestFixture { " if (ptr + 1 != 0);\n" "}"); ASSERT_EQUALS("[test.cpp:2:15]: (warning) Comparison is wrong. Result of 'ptr+1' can't be 0 unless there is pointer overflow, and pointer overflow is undefined behaviour. [pointerAdditionResultNotNull]\n", errout_str()); + + // #8260 + check("void f(int *p) {\n" + " int * q = p + 1;\n" + " if (q != 0);\n" + "}"); + ASSERT_EQUALS("[test.cpp:3:9]: (warning) Comparison is wrong. Result of 'p+1' can't be 0 unless there is pointer overflow, and pointer overflow is undefined behaviour. [pointerAdditionResultNotNull]\n", errout_str()); + check("void f(int *p) {\n" + " int * q = p + 1;\n" + " if (0 != q);\n" + "}"); + ASSERT_EQUALS("[test.cpp:3:9]: (warning) Comparison is wrong. Result of 'p+1' can't be 0 unless there is pointer overflow, and pointer overflow is undefined behaviour. [pointerAdditionResultNotNull]\n", errout_str()); } void duplicateConditionalAssign() {