Skip to content

Commit 8b2249c

Browse files
authored
fix #14130: false positive: unusedStructMember with [[maybe_unused]] (danmar#7818)
1 parent 5131a05 commit 8b2249c

File tree

6 files changed

+80
-8
lines changed

6 files changed

+80
-8
lines changed

lib/checkclass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1338,7 +1338,7 @@ void CheckClass::privateFunctions()
13381338

13391339
while (!privateFuncs.empty()) {
13401340
const auto& pf = privateFuncs.front();
1341-
if (pf->retDef && pf->retDef->isAttributeMaybeUnused()) {
1341+
if (pf->token->isAttributeMaybeUnused()) {
13421342
privateFuncs.pop_front();
13431343
continue;
13441344
}

lib/checkunusedvar.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1606,7 +1606,7 @@ void CheckUnusedVar::checkStructMemberUsage()
16061606
if (isInherited && !var.isPrivate())
16071607
continue;
16081608

1609-
if (!var.nameToken() || var.nameToken()->isAttributeUnused() || var.nameToken()->isAnonymous())
1609+
if (!var.nameToken() || var.nameToken()->isAttributeUnused() || var.nameToken()->isAttributeMaybeUnused() || var.nameToken()->isAnonymous())
16101610
continue;
16111611

16121612
if (mTokenizer->isVarUsedInTemplate(var.declarationId()))

lib/symboldatabase.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2357,8 +2357,11 @@ void Variable::evaluate(const Settings& settings)
23572357
const Library & lib = settings.library;
23582358

23592359
bool isContainer = false;
2360-
if (mNameToken)
2360+
if (mNameToken) {
23612361
setFlag(fIsArray, arrayDimensions(settings, isContainer));
2362+
setFlag(fIsMaybeUnused, mNameToken->isAttributeMaybeUnused());
2363+
}
2364+
23622365

23632366
if (mTypeStartToken)
23642367
setValueType(ValueType::parseDecl(mTypeStartToken,settings));
@@ -2395,10 +2398,6 @@ void Variable::evaluate(const Settings& settings)
23952398
setFlag(fIsReference, true); // Set also fIsReference
23962399
}
23972400

2398-
if (tok->isAttributeMaybeUnused()) {
2399-
setFlag(fIsMaybeUnused, true);
2400-
}
2401-
24022401
if (tok->str() == "<" && tok->link())
24032402
tok = tok->link();
24042403
else

lib/tokenize.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9550,9 +9550,27 @@ void Tokenizer::simplifyCPPAttribute()
95509550
Token* head = skipCPPOrAlignAttribute(tok)->next();
95519551
while (isCPPAttribute(head) || isAlignAttribute(head))
95529552
head = skipCPPOrAlignAttribute(head)->next();
9553+
95539554
if (!head)
95549555
syntaxError(tok);
9555-
head->isAttributeMaybeUnused(true);
9556+
9557+
while (Token::Match(head->next(), "%name%|*|&|&&|const|static|inline|volatile"))
9558+
head = head->next();
9559+
if (Token::Match(head, "%name%") && !Token::Match(head, "auto ["))
9560+
head->isAttributeMaybeUnused(true);
9561+
else if (Token::Match(tok->previous(), "%name%") && Token::Match(tok->link(), "] [;={]")) {
9562+
tok->previous()->isAttributeMaybeUnused(true);
9563+
} else {
9564+
if (Token::simpleMatch(head->next(), "[")) {
9565+
head = head->next();
9566+
const Token *end = head->link();
9567+
for (head = head->next(); end && head != end; head = head->next()) {
9568+
if (Token::Match(head, "%name%")) {
9569+
head->isAttributeMaybeUnused(true);
9570+
}
9571+
}
9572+
}
9573+
}
95569574
} else if (Token::findsimplematch(tok->tokAt(2), "unused", tok->link())) {
95579575
Token* head = skipCPPOrAlignAttribute(tok)->next();
95589576
while (isCPPAttribute(head) || isAlignAttribute(head))

test/testtokenize.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ class TestTokenizer : public TestFixture {
273273
TEST_CASE(functionAttributeListBefore);
274274
TEST_CASE(functionAttributeListAfter);
275275

276+
TEST_CASE(cppMaybeUnusedBefore);
277+
TEST_CASE(cppMaybeUnusedAfter);
278+
TEST_CASE(cppMaybeUnusedStructuredBinding);
279+
276280
TEST_CASE(splitTemplateRightAngleBrackets);
277281

278282
TEST_CASE(cpp03template1);
@@ -4193,6 +4197,47 @@ class TestTokenizer : public TestFixture {
41934197
ASSERT(func8 && func8->isAttributeNoreturn() && func8->isAttributePure() && func8->isAttributeNothrow() && func8->isAttributeConst());
41944198
}
41954199

4200+
void cppMaybeUnusedBefore() {
4201+
const char code[] = "[[maybe_unused]] int var {};";
4202+
const char expected[] = "int var { } ;";
4203+
4204+
SimpleTokenizer tokenizer(settings0, *this);
4205+
ASSERT(tokenizer.tokenize(code));
4206+
4207+
ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(nullptr, false));
4208+
4209+
const Token *var = Token::findsimplematch(tokenizer.tokens(), "var");
4210+
ASSERT(var && var->isAttributeMaybeUnused());
4211+
}
4212+
4213+
void cppMaybeUnusedAfter() {
4214+
const char code[] = "int var [[maybe_unused]] {};";
4215+
const char expected[] = "int var { } ;";
4216+
4217+
SimpleTokenizer tokenizer(settings0, *this);
4218+
ASSERT(tokenizer.tokenize(code));
4219+
4220+
ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(nullptr, false));
4221+
4222+
const Token *var = Token::findsimplematch(tokenizer.tokens(), "var");
4223+
ASSERT(var && var->isAttributeMaybeUnused());
4224+
}
4225+
4226+
void cppMaybeUnusedStructuredBinding() {
4227+
const char code[] = "[[maybe_unused]] auto [var1, var2] = f();";
4228+
const char expected[] = "auto [ var1 , var2 ] = f ( ) ;";
4229+
4230+
SimpleTokenizer tokenizer(settings0, *this);
4231+
ASSERT(tokenizer.tokenize(code));
4232+
4233+
ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(nullptr, false));
4234+
4235+
const Token *var1 = Token::findsimplematch(tokenizer.tokens(), "var1");
4236+
ASSERT(var1 && var1->isAttributeMaybeUnused());
4237+
const Token *var2 = Token::findsimplematch(tokenizer.tokens(), "var2");
4238+
ASSERT(var2 && var2->isAttributeMaybeUnused());
4239+
}
4240+
41964241

41974242
void splitTemplateRightAngleBrackets() {
41984243
{

test/testunusedvar.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class TestUnusedVar : public TestFixture {
7373
TEST_CASE(structmember28);
7474
TEST_CASE(structmember29); // #14075
7575
TEST_CASE(structmember30); // #14131
76+
TEST_CASE(structmember31); // #14130
7677
TEST_CASE(structmember_macro);
7778
TEST_CASE(structmember_template_argument); // #13887 - do not report that member used in template argument is unused
7879
TEST_CASE(classmember);
@@ -2035,6 +2036,15 @@ class TestUnusedVar : public TestFixture {
20352036
ASSERT_EQUALS("", errout_str());
20362037
}
20372038

2039+
void structmember31() { // #14130
2040+
checkStructMemberUsage("struct S\n"
2041+
"{\n"
2042+
" [[maybe_unused]] int i1{};\n"
2043+
" int i2 [[maybe_unused]] {};\n"
2044+
"};\n");
2045+
ASSERT_EQUALS("", errout_str());
2046+
}
2047+
20382048
void structmember_macro() {
20392049
checkStructMemberUsageP("#define S(n) struct n { int a, b, c; };\n"
20402050
"S(unused);\n");

0 commit comments

Comments
 (0)