Skip to content

Commit ac1a869

Browse files
committed
unused struct members: don't warn about packed structs (danmar#3088)
1 parent 4d22ada commit ac1a869

File tree

4 files changed

+26
-3
lines changed

4 files changed

+26
-3
lines changed

lib/checkunusedvar.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,10 @@ void CheckUnusedVar::checkStructMemberUsage()
12401240
if (scope->classStart->fileIndex() != 0 || scope->className.empty())
12411241
continue;
12421242

1243+
// Packed struct => possibly used by lowlevel code. Struct members might be required by hardware.
1244+
if (scope->classEnd->isAttributePacked())
1245+
continue;
1246+
12431247
// Bail out if struct/union contains any functions
12441248
if (!scope->functionList.empty())
12451249
continue;

lib/token.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,12 @@ class CPPCHECKLIB Token {
386386
void isAttributeNothrow(bool value) {
387387
setFlag(fIsAttributeNothrow, value);
388388
}
389+
bool isAttributePacked() const {
390+
return getFlag(fIsAttributePacked);
391+
}
392+
void isAttributePacked(bool value) {
393+
setFlag(fIsAttributePacked, value);
394+
}
389395
bool isOperatorKeyword() const {
390396
return getFlag(fIsOperatorKeyword);
391397
}
@@ -838,9 +844,10 @@ class CPPCHECKLIB Token {
838844
fIsAttributeNoreturn = (1 << 12), // __attribute__((noreturn)), __declspec(noreturn)
839845
fIsAttributeNothrow = (1 << 13), // __attribute__((nothrow)), __declspec(nothrow)
840846
fIsAttributeUsed = (1 << 14), // __attribute__((used))
841-
fIsOperatorKeyword = (1 << 15), // operator=, etc
842-
fIsComplex = (1 << 16), // complex/_Complex type
843-
fIsEnumType = (1 << 17) // enumeration type
847+
fIsAttributePacked = (1 << 15), // __attribute__((packed))
848+
fIsOperatorKeyword = (1 << 16), // operator=, etc
849+
fIsComplex = (1 << 17), // complex/_Complex type
850+
fIsEnumType = (1 << 18) // enumeration type
844851
};
845852

846853
unsigned int _flags;

lib/tokenize.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8585,6 +8585,10 @@ void Tokenizer::simplifyAttribute()
85858585
}
85868586
}
85878587

8588+
else if (Token::simpleMatch(tok->previous(), "} __attribute__ ( ( packed )")) {
8589+
tok->previous()->isAttributePacked(true);
8590+
}
8591+
85888592
Token::eraseTokens(tok, tok->next()->link()->next());
85898593
tok->deleteThis();
85908594
}

test/testunusedvar.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class TestUnusedVar : public TestFixture {
4848
TEST_CASE(structmember10);
4949
TEST_CASE(structmember11); // #4168 - initialization with {} / passed by address to unknown function
5050
TEST_CASE(structmember12); // #7179 - FP unused structmember
51+
TEST_CASE(structmember13); // #3088 - __attribute__((packed))
5152
TEST_CASE(structmember_sizeof);
5253

5354
TEST_CASE(localvar1);
@@ -422,6 +423,13 @@ class TestUnusedVar : public TestFixture {
422423
ASSERT_EQUALS("", errout.str());
423424
}
424425

426+
void structmember13() { // #3088 - struct members required by hardware
427+
checkStructMemberUsage("struct S {\n"
428+
" int x;\n"
429+
"} __attribute__((packed));");
430+
ASSERT_EQUALS("", errout.str());
431+
}
432+
425433
void structmember_extern() {
426434
// extern struct => no false positive
427435
checkStructMemberUsage("extern struct AB\n"

0 commit comments

Comments
 (0)