From 5dac7e9a4f641a419ee523168a0db34f205136c8 Mon Sep 17 00:00:00 2001 From: Anton Lindqvist Date: Wed, 28 Oct 2026 20:27:18 +0100 Subject: [PATCH 1/2] Fix #15153 FP constParameterPointer with unused attribute Unused parameters annotated with the unused attribute were reported as they could be declared as pointer to const, while [[maybe_unused]] parameters were not. --- lib/symboldatabase.cpp | 2 +- lib/tokenize.cpp | 4 ++-- test/testother.cpp | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 78fd044cc7b..26801640e99 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2560,7 +2560,7 @@ void Variable::evaluate(const Settings& settings) bool isContainer = false; if (mNameToken) { setFlag(fIsArray, arrayDimensions(settings, isContainer)); - setFlag(fIsMaybeUnused, mNameToken->isAttributeMaybeUnused()); + setFlag(fIsMaybeUnused, mNameToken->isAttributeMaybeUnused() || mNameToken->isAttributeUnused()); } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 436a6655284..bbcd1bd6b89 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -9718,8 +9718,8 @@ static Token* getVariableTokenAfterAttributes(Token* tok) { Token *vartok = nullptr; Token *after = getTokenAfterAttributes(tok, true); - // check if after variable name - if (Token::Match(after, "[;={]")) { + // check if after variable or parameter name + if (Token::Match(after, "[;={,)]")) { Token *prev = tok->previous(); while (Token::simpleMatch(prev, "]")) prev = prev->link()->previous(); diff --git a/test/testother.cpp b/test/testother.cpp index a194c297a8b..61ff7b2dae5 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -5039,6 +5039,11 @@ class TestOther : public TestFixture { "};\n"); ASSERT_EQUALS("[test.cpp:2:17]: (style) Either there is a missing override/final keyword, or the parameter 'p' can be declared as pointer to const [constParameterPointer]\n", errout_str()); + + check("void f(int *p __attribute__((unused))) {}\n" + "void g(__attribute__((unused)) int *p) {}\n" + "void h(int *p) {}\n"); + ASSERT_EQUALS("[test.cpp:3:13]: (style) Parameter 'p' can be declared as pointer to const [constParameterPointer]\n", errout_str()); } void constArray() { From ee2268767af4228b961e2fb9617c1d7f17683b85 Mon Sep 17 00:00:00 2001 From: Anton Lindqvist Date: Sat, 7 Nov 2026 19:58:38 +0100 Subject: [PATCH 2/2] Add tests for unused attribute in multi-name declarations The unused attribute in declarations with several names now marks the correct variable or struct member. --- test/testunusedvar.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 78ecd45ccef..42077399411 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -2068,6 +2068,11 @@ class TestUnusedVar : public TestFixture { " int i3 __attribute__((unused)) {};\n" "};\n"); ASSERT_EQUALS("", errout_str()); + + checkStructMemberUsage("struct S {\n" + " int a __attribute__((unused)), b;\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:2:36]: (style) struct member 'S::b' is never used. [unusedStructMember]\n", errout_str()); } void structmember31() { // #14130 @@ -6015,6 +6020,12 @@ class TestUnusedVar : public TestFixture { " char b[1][2] __attribute__((unused));\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + functionVariableUsage("int foo()\n" + "{\n" + " int x __attribute__((unused)), y;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:36]: (style) Unused variable: y [unusedVariable]\n", errout_str()); } void localvarFunction() {