From 37deb7902327a5ffd69e3ff5245024c9464323aa Mon Sep 17 00:00:00 2001 From: Francois Berder Date: Wed, 1 Apr 2026 17:32:45 +0200 Subject: [PATCH 1/2] Report overlapping inner conditions as identicalInnerCondition Signed-off-by: Francois Berder --- lib/checkcondition.cpp | 4 +++- lib/checkcondition.h | 2 +- test/testcondition.cpp | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index cf54c882f34..07c671e7ada 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -602,7 +602,7 @@ void CheckCondition::oppositeElseIfConditionError(const Token *ifCond, const Tok //--------------------------------------------------------------------------- // - Opposite inner conditions => always false -// - (TODO) Same/Overlapping inner condition => always true +// - Same/Overlapping inner condition => always true // - same condition after early exit => always false //--------------------------------------------------------------------------- @@ -759,6 +759,8 @@ void CheckCondition::multiCondition2() oppositeInnerConditionError(firstCondition, cond2, errorPath); } else if (!isReturnVar && isSameExpression(true, firstCondition, cond2, *mSettings, true, true, &errorPath)) { identicalInnerConditionError(firstCondition, cond2, errorPath); + } else if (!isReturnVar && isOverlappingCond(cond2, firstCondition, true)) { + identicalInnerConditionError(firstCondition, cond2, errorPath); } } return ChildrenToVisit::none; diff --git a/lib/checkcondition.h b/lib/checkcondition.h index dac3ba8d0de..dd6784c2ce3 100644 --- a/lib/checkcondition.h +++ b/lib/checkcondition.h @@ -84,7 +84,7 @@ class CPPCHECKLIB CheckCondition : public Check { /** * multiconditions #2 * - Opposite inner conditions => always false - * - (TODO) Same/Overlapping inner condition => always true + * - Same/Overlapping inner condition => always true * - same condition after early exit => always false **/ void multiCondition2(); diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 421fa53e2bc..4b61b2e0fc0 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -2834,6 +2834,20 @@ class TestCondition : public TestFixture { " }\n" "}\n"); ASSERT_EQUALS("[test.cpp:2:12] -> [test.cpp:4:13]: (warning) Identical inner 'if' condition is always true. [identicalInnerCondition]\n", errout_str()); + + check("void f(int x) {\n" + " if (x == 1) {\n" + " if (x & 7) {}\n" + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:2:11] -> [test.cpp:3:15]: (warning) Identical inner 'if' condition is always true. [identicalInnerCondition]\n", errout_str()); + + check("void f(int x) {\n" + " if (x & 7) {\n" + " if (x == 1) {}\n" + " }\n" + "}"); + ASSERT_EQUALS("", errout_str()); } void identicalConditionAfterEarlyExit() { From 8dad4aa81c90102321e67bcc9b06d38cfef5310c Mon Sep 17 00:00:00 2001 From: Francois Berder Date: Fri, 17 Apr 2026 11:55:56 +0200 Subject: [PATCH 2/2] fixup! Report overlapping inner conditions as identicalInnerCondition --- lib/checkcondition.cpp | 18 +++++++++++++++++- lib/checkcondition.h | 1 + test/testcondition.cpp | 32 ++++++++++++++++++-------------- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 07c671e7ada..a56aea7a4b5 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -760,7 +760,7 @@ void CheckCondition::multiCondition2() } else if (!isReturnVar && isSameExpression(true, firstCondition, cond2, *mSettings, true, true, &errorPath)) { identicalInnerConditionError(firstCondition, cond2, errorPath); } else if (!isReturnVar && isOverlappingCond(cond2, firstCondition, true)) { - identicalInnerConditionError(firstCondition, cond2, errorPath); + overlappingInnerConditionError(firstCondition, cond2, errorPath); } } return ChildrenToVisit::none; @@ -881,6 +881,21 @@ void CheckCondition::oppositeInnerConditionError(const Token *tok1, const Token* reportError(std::move(errorPath), Severity::warning, "oppositeInnerCondition", msg, CWE398, Certainty::normal); } +void CheckCondition::overlappingInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath) +{ + if (diag(tok1, tok2)) + return; + const std::string s1(tok1 ? tok1->expressionString() : "x"); + const std::string s2(tok2 ? tok2->expressionString() : "x"); + const std::string innerSmt = innerSmtString(tok2); + errorPath.emplace_back(tok1, "outer condition: " + s1); + errorPath.emplace_back(tok2, "overlapping inner condition: " + s2); + + const std::string msg("Overlapping inner '" + innerSmt + "' condition is always true.\n" + "Overlapping inner '" + innerSmt + "' condition is always true (outer condition is '" + s1 + "' and inner condition is '" + s2 + "')."); + reportError(std::move(errorPath), Severity::warning, "overlappingInnerCondition", msg, CWE398, Certainty::normal); +} + void CheckCondition::identicalInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath) { if (diag(tok1, tok2)) @@ -2113,6 +2128,7 @@ void CheckCondition::getErrorMessages(ErrorLogger *errorLogger, const Settings * c.comparisonError(nullptr, "&", 6, "==", 1, false); c.duplicateConditionError(nullptr, nullptr, ErrorPath{}); c.overlappingElseIfConditionError(nullptr, 1); + c.overlappingInnerConditionError(nullptr, nullptr, ErrorPath()); c.mismatchingBitAndError(nullptr, 0xf0, nullptr, 1); c.oppositeInnerConditionError(nullptr, nullptr, ErrorPath{}); c.identicalInnerConditionError(nullptr, nullptr, ErrorPath{}); diff --git a/lib/checkcondition.h b/lib/checkcondition.h index dd6784c2ce3..2c010cd7c5a 100644 --- a/lib/checkcondition.h +++ b/lib/checkcondition.h @@ -130,6 +130,7 @@ class CPPCHECKLIB CheckCondition : public Check { bool result); void duplicateConditionError(const Token *tok1, const Token *tok2, ErrorPath errorPath); void overlappingElseIfConditionError(const Token *tok, nonneg int line1); + void overlappingInnerConditionError(const Token *tok1, const Token *tok2, ErrorPath errorPath); void oppositeElseIfConditionError(const Token *ifCond, const Token *elseIfCond, ErrorPath errorPath); void oppositeInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath); diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 4b61b2e0fc0..20e13b62f82 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -94,6 +94,8 @@ class TestCondition : public TestFixture { TEST_CASE(identicalConditionAfterEarlyExit); TEST_CASE(innerConditionModified); + TEST_CASE(overlappingInnerCondition); + TEST_CASE(clarifyCondition1); // if (a = b() < 0) TEST_CASE(clarifyCondition2); // if (a & b == c) TEST_CASE(clarifyCondition3); // if (! a & b) @@ -2834,20 +2836,6 @@ class TestCondition : public TestFixture { " }\n" "}\n"); ASSERT_EQUALS("[test.cpp:2:12] -> [test.cpp:4:13]: (warning) Identical inner 'if' condition is always true. [identicalInnerCondition]\n", errout_str()); - - check("void f(int x) {\n" - " if (x == 1) {\n" - " if (x & 7) {}\n" - " }\n" - "}"); - ASSERT_EQUALS("[test.cpp:2:11] -> [test.cpp:3:15]: (warning) Identical inner 'if' condition is always true. [identicalInnerCondition]\n", errout_str()); - - check("void f(int x) {\n" - " if (x & 7) {\n" - " if (x == 1) {}\n" - " }\n" - "}"); - ASSERT_EQUALS("", errout_str()); } void identicalConditionAfterEarlyExit() { @@ -3036,6 +3024,22 @@ class TestCondition : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void overlappingInnerCondition() { + check("void f(int x) {\n" + " if (x == 1) {\n" + " if (x & 7) {}\n" + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:2:11] -> [test.cpp:3:15]: (warning) Overlapping inner 'if' condition is always true. [overlappingInnerCondition]\n", errout_str()); + + check("void f(int x) {\n" + " if (x & 7) {\n" + " if (x == 1) {}\n" + " }\n" + "}"); + ASSERT_EQUALS("", errout_str()); + } + // clarify conditions with = and comparison void clarifyCondition1() { check("void f() {\n"