From 4c9eae097e6fad7841bcc051d8ea6a14525b4dce Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:32:43 +0100 Subject: [PATCH 1/2] Update testautovariables.cpp --- test/testautovariables.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 1091a03e9ff..8729f915411 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -711,8 +711,7 @@ class TestAutoVariables : public TestFixture { " g(&s);\n" "}"); ASSERT_EQUALS( - "[test.cpp:4:5]: (error) Address of local auto-variable assigned to a function parameter. [autoVariables]\n" - "[test.cpp:4:5]: (error) Address of local auto-variable assigned to a function parameter. [autoVariables]\n", // duplicate + "[test.cpp:4:5]: (error) Address of local auto-variable assigned to a function parameter. [autoVariables]\n", errout_str()); } @@ -4693,6 +4692,21 @@ class TestAutoVariables : public TestFixture { "}\n"); ASSERT_EQUALS("", errout_str()); + check("struct S {\n" + " int* a[1];\n" + " int* b[1][1];\n" + "};\n" + "void f(S* s) {\n" + " int i = 0;\n" + " s->a[0] = &i;\n" + "}\n" + "void g(S* s) {\n" + " int i = 0;\n" + " s->b[0][0] = &i;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:7:5]: (error) Address of local auto-variable assigned to a function parameter. [autoVariables]\n" + "[test.cpp:11:5]: (error) Address of local auto-variable assigned to a function parameter. [autoVariables]\n", + errout_str()); } void deadPointer() { From 9290b3834e7213a598a826a1ddff2524740dceb6 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:34:31 +0100 Subject: [PATCH 2/2] Update checkautovariables.cpp --- lib/checkautovariables.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index bc18c3dc477..4f845c2314f 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -263,6 +263,23 @@ static bool hasOverloadedAssignment(const Token* tok, bool& inconclusive) return true; } +static bool isMemberAssignment(const Token* tok, const Token*& rhs, const Settings& settings) +{ + if (!Token::Match(tok, "[;{}] %var% . %var%")) + return false; + if (!isPtrArg(tok->next())) + return false; + const Token* assign = tok->tokAt(2)->astParent(); + while (Token::simpleMatch(assign, "[")) + assign = assign->astParent(); + if (!Token::simpleMatch(assign, "=")) + return false; + if (!isAutoVariableRHS(assign->astOperand2(), settings)) + return false; + rhs = assign->astOperand2(); + return true; +} + void CheckAutoVariables::autoVariables() { logChecker("CheckAutoVariables::autoVariables"); @@ -277,6 +294,7 @@ void CheckAutoVariables::autoVariables() continue; } // Critical assignment + const Token* rhs{}; if (Token::Match(tok, "[;{}] %var% =") && isRefPtrArg(tok->next()) && isAutoVariableRHS(tok->tokAt(2)->astOperand2(), *mSettings)) { checkAutoVariableAssignment(tok->next(), false); } else if (Token::Match(tok, "[;{}] * %var% =") && isPtrArg(tok->tokAt(2)) && isAutoVariableRHS(tok->tokAt(3)->astOperand2(), *mSettings)) { @@ -285,12 +303,12 @@ void CheckAutoVariables::autoVariables() if (!hasOverloadedAssignment(lhs, inconclusive) || (printInconclusive && inconclusive)) checkAutoVariableAssignment(tok->next(), inconclusive); tok = tok->tokAt(4); - } else if (Token::Match(tok, "[;{}] %var% . %var% =") && isPtrArg(tok->next()) && isAutoVariableRHS(tok->tokAt(4)->astOperand2(), *mSettings)) { + } else if (isMemberAssignment(tok, rhs, *mSettings)) { const Token* lhs = tok->tokAt(3); bool inconclusive = false; if (!hasOverloadedAssignment(lhs, inconclusive) || (printInconclusive && inconclusive)) checkAutoVariableAssignment(tok->next(), inconclusive); - tok = tok->tokAt(5); + tok = rhs; } else if (Token::Match(tok, "[;{}] %var% [") && Token::simpleMatch(tok->linkAt(2), "] =") && (isPtrArg(tok->next()) || isArrayArg(tok->next(), *mSettings)) && isAutoVariableRHS(tok->linkAt(2)->next()->astOperand2(), *mSettings)) { @@ -330,8 +348,10 @@ bool CheckAutoVariables::checkAutoVariableAssignment(const Token *expr, bool inc if (!startToken) startToken = Token::findsimplematch(expr, "=")->next(); for (const Token *tok = startToken; tok; tok = tok->next()) { - if (tok->str() == "}" && tok->scope()->type == ScopeType::eFunction) + if (tok->str() == "}" && tok->scope()->type == ScopeType::eFunction) { errorAutoVariableAssignment(expr, inconclusive); + return true; + } if (Token::Match(tok, "return|throw|break|continue")) { errorAutoVariableAssignment(expr, inconclusive);