From 605f042d9ee7353d6c3d282d6a223dbeb708ef99 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 11 May 2026 14:45:25 +0200 Subject: [PATCH 1/3] Update astutils.cpp --- lib/astutils.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 94dc6fc5afa..56a9489d00e 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -3114,6 +3114,8 @@ static const Token* findExpressionChangedImpl(const Token* expr, if (vt->type == ValueType::ITERATOR) ++indirect; } + if (indirect == 0 && tok2->astParent() && tok2->astParent()->isUnaryOp("*")) + ++indirect; for (int i = 0; i <= indirect; ++i) { if (isExpressionChangedAt(tok, tok2, i, global, settings, depth)) return true; From 26e25476059f8a135298599fb72666524668ded0 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 11 May 2026 14:47:00 +0200 Subject: [PATCH 2/3] Update testother.cpp --- test/testother.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/testother.cpp b/test/testother.cpp index c23e8c64155..727a3c4ac61 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -4120,6 +4120,11 @@ class TestOther : public TestFixture { " std::string _s;\n" "};\n"); ASSERT_EQUALS("", errout_str()); + + check("void f(std::optional& o) {\n" + " *o = 1;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void constParameterCallback() { From 4bebfdea27e20f2e10a1fd71ab0dcf0aea8fc9c8 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Mon, 11 May 2026 21:12:05 +0200 Subject: [PATCH 3/3] Fix --- lib/checkother.cpp | 10 +++++++--- test/testother.cpp | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index fd23e113509..7a1e1fea774 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1769,9 +1769,13 @@ void CheckOther::checkConstVariable() //Is it the right side of an initialization of a non-const reference bool usedInAssignment = false; for (const Token* tok = var->nameToken(); tok != scope->bodyEnd && tok != nullptr; tok = tok->next()) { - if (Token::Match(tok, "& %var% = %varid%", var->declarationId())) { - const Variable* refvar = tok->next()->variable(); - if (refvar && !refvar->isConst() && refvar->nameToken() == tok->next()) { + if (Token::Match(tok, "%name% = %varid%", var->declarationId())) { + const Variable* refvar = tok->variable(); + if (tok->strAt(-1) == "&" && refvar && !refvar->isConst() && refvar->nameToken() == tok) { + usedInAssignment = true; + break; + } + if (!tok->valueType() || tok->valueType()->type == ValueType::Type::RECORD) { usedInAssignment = true; break; } diff --git a/test/testother.cpp b/test/testother.cpp index 727a3c4ac61..a768abb647e 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -4121,6 +4121,22 @@ class TestOther : public TestFixture { "};\n"); ASSERT_EQUALS("", errout_str()); + check("void f(int& r) {\n" // #9761 + " o1 = r;\n" + "}\n" + "boost::optional o2;\n" + "void g(int& r) {\n" + " o2 = r;\n" + "}\n" + "struct T {\n" + " int* p;\n" + " T& operator=(int& rhs) { p = &rhs; return *this; }\n" + "};\n" + "void h(T& t, int& r) {\n" + " t = r;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + check("void f(std::optional& o) {\n" " *o = 1;\n" "}\n");