From 6ac01b6d8f78eb4d46aaffbf49326ed0978b1a51 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:17:35 +0200 Subject: [PATCH 1/5] Update astutils.cpp --- lib/astutils.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 2a4de18b2c0..63652bdddbb 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -3101,8 +3101,7 @@ static const Token* findExpressionChangedImpl(const Token* expr, } bool global = false; if (tok->variable()) { - global = !tok->variable()->isLocal() && !tok->variable()->isArgument() && - !(tok->variable()->isMember() && !tok->variable()->isStatic()); + global = !tok->variable()->isLocal() && !tok->variable()->isArgument(); } else if (tok->isIncompleteVar() && !tok->isIncompleteConstant()) { global = true; } From d3495156e5afd40712e798bd822809206eb221c4 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:18:37 +0200 Subject: [PATCH 2/5] Update testcondition.cpp --- test/testcondition.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 58475896ebe..b6102bdcd4b 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -5094,6 +5094,21 @@ class TestCondition : public TestFixture { " if (i < 0) {}\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("struct A { int x; int y; };" + "void use(int);\n" + "void test(A a) {\n" + " int i = a.x;\n" + " int j = a.x;\n" + " use(j);\n" + " if (i == j) {}\n" + " if (i == a.x) {}\n" + " if (j == a.x) {}\n" + "}"); + ASSERT_EQUALS("[test.cpp:6:11]: (style) Condition 'i==j' is always true [knownConditionTrueFalse]\n" + "[test.cpp:7:11]: (style) Condition 'i==a.x' is always true [knownConditionTrueFalse]\n" + "[test.cpp:8:11]: (style) Condition 'j==a.x' is always true [knownConditionTrueFalse]\n", + errout_str()); } void alwaysTrueInfer() { From d5c85cd404b198549b10f65491b63de50297ae0a Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:27:23 +0200 Subject: [PATCH 3/5] Update testother.cpp --- test/testother.cpp | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/test/testother.cpp b/test/testother.cpp index bac5dfbdf7f..09f05108a4d 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -200,6 +200,7 @@ class TestOther : public TestFixture { TEST_CASE(duplicateExpression18); TEST_CASE(duplicateExpression19); TEST_CASE(duplicateExpression20); + TEST_CASE(duplicateExpression21); TEST_CASE(duplicateExpressionLoop); TEST_CASE(duplicateValueTernary); TEST_CASE(duplicateValueTernarySizeof); // #13773 @@ -8186,6 +8187,35 @@ class TestOther : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void duplicateExpression21() { + check("struct S { int i; };\n" // #12795 + "struct T {\n" + " std::map m;\n" + " S* get(const std::string& s) { return m[s]; }\n" + " void modify() { for (const auto& e : m) e.second->i = 0; }\n" + "};\n" + "void f(T& t) {\n" + " const S* p = t.get(\"abc\");\n" + " const int o = p->i;\n" + " t.modify();\n" + " if (p->i == o) {}\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("struct S { int i; };\n" + " struct T {\n" + " std::vector m;\n" + " void modify() { for (auto e : m) e->i = 0; }\n" + "};\n" + "void f(T& t) {\n" + " const S* p = t.m[0];\n" + " const int o = p->i;\n" + " t.modify();\n" + " if (p->i == o) {}\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + } + void duplicateExpressionLoop() { check("void f() {\n" " int a = 1;\n" @@ -8897,8 +8927,7 @@ class TestOther : public TestFixture { " if (i == j) {}\n" "}"); ASSERT_EQUALS( - "[test.cpp:4:9] -> [test.cpp:3:9]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'. [duplicateAssignExpression]\n" - "[test.cpp:3:14] -> [test.cpp:4:14] -> [test.cpp:6:11]: (style) The comparison 'i == j' is always true because 'i' and 'j' represent the same value. [knownConditionTrueFalse]\n", + "[test.cpp:4:9] -> [test.cpp:3:9]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'. [duplicateAssignExpression]\n", errout_str()); check("struct A { int x; int y; };" @@ -8910,8 +8939,7 @@ class TestOther : public TestFixture { " if (i == a.x) {}\n" "}"); ASSERT_EQUALS( - "[test.cpp:4:9] -> [test.cpp:3:9]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'. [duplicateAssignExpression]\n" - "[test.cpp:3:14] -> [test.cpp:6:11]: (style) The comparison 'i == a.x' is always true because 'i' and 'a.x' represent the same value. [knownConditionTrueFalse]\n", + "[test.cpp:4:9] -> [test.cpp:3:9]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'. [duplicateAssignExpression]\n", errout_str()); check("struct A { int x; int y; };" @@ -8923,8 +8951,7 @@ class TestOther : public TestFixture { " if (j == a.x) {}\n" "}"); ASSERT_EQUALS( - "[test.cpp:4:9] -> [test.cpp:3:9]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'. [duplicateAssignExpression]\n" - "[test.cpp:4:14] -> [test.cpp:6:11]: (style) The comparison 'j == a.x' is always true because 'j' and 'a.x' represent the same value. [knownConditionTrueFalse]\n", + "[test.cpp:4:9] -> [test.cpp:3:9]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'. [duplicateAssignExpression]\n", errout_str()); // Issue #8612 @@ -9992,9 +10019,7 @@ class TestOther : public TestFixture { " u.g();\n" " if (c == m->get()) {}\n" "}\n"); - TODO_ASSERT_EQUALS("", - "[test.cpp:16:33] -> [test.cpp:18:11]: (style) The comparison 'c == m->get()' is always true because 'c' and 'm->get()' represent the same value. [knownConditionTrueFalse]\n", - errout_str()); + ASSERT_EQUALS("", errout_str()); check("struct S {\n" // #12925 " const std::string & f() const { return str; }\n" From f3ec34420ca9857d7fdf349897ee9904431c35b8 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:40:51 +0200 Subject: [PATCH 4/5] Update testcondition.cpp [skip ci] --- test/testcondition.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/testcondition.cpp b/test/testcondition.cpp index b6102bdcd4b..a314c42437a 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -5109,6 +5109,22 @@ class TestCondition : public TestFixture { "[test.cpp:7:11]: (style) Condition 'i==a.x' is always true [knownConditionTrueFalse]\n" "[test.cpp:8:11]: (style) Condition 'j==a.x' is always true [knownConditionTrueFalse]\n", errout_str()); + + check("struct S { int i; };\n" // #12795 + "struct T {\n" + " std::map m;\n" + " S* get(const std::string& s) { return m[s]; }\n" + " void modify() { for (const auto& e : m) e.second->i = 0; }\n" + "};\n" + "void f(T& t) {\n" + " const S* p = t.get(\"abc\");\n" + " const int o = p->i;\n" + " t.modify();\n" + " if (p->i == o) {}\n" + "}\n"); + TODO_ASSERT_EQUALS("", + "[test.cpp:11:14]: (style) Condition 'p->i==o' is always true [knownConditionTrueFalse]\n", + errout_str()); } void alwaysTrueInfer() { From d7113f7ea4079268ce800b7e51b2a78ba19f81c1 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:42:43 +0200 Subject: [PATCH 5/5] Format --- test/testother.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testother.cpp b/test/testother.cpp index 09f05108a4d..a649e1e8da1 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -8187,7 +8187,7 @@ class TestOther : public TestFixture { ASSERT_EQUALS("", errout_str()); } - void duplicateExpression21() { + void duplicateExpression21() { check("struct S { int i; };\n" // #12795 "struct T {\n" " std::map m;\n"