unused struct members: don't warn about packed structs (#3088)

This commit is contained in:
Daniel Marjamäki 2016-09-05 17:27:12 +02:00
parent 4d22ada078
commit ac1a869d60
4 changed files with 26 additions and 3 deletions

View File

@ -1240,6 +1240,10 @@ void CheckUnusedVar::checkStructMemberUsage()
if (scope->classStart->fileIndex() != 0 || scope->className.empty()) if (scope->classStart->fileIndex() != 0 || scope->className.empty())
continue; continue;
// Packed struct => possibly used by lowlevel code. Struct members might be required by hardware.
if (scope->classEnd->isAttributePacked())
continue;
// Bail out if struct/union contains any functions // Bail out if struct/union contains any functions
if (!scope->functionList.empty()) if (!scope->functionList.empty())
continue; continue;

View File

@ -386,6 +386,12 @@ public:
void isAttributeNothrow(bool value) { void isAttributeNothrow(bool value) {
setFlag(fIsAttributeNothrow, value); setFlag(fIsAttributeNothrow, value);
} }
bool isAttributePacked() const {
return getFlag(fIsAttributePacked);
}
void isAttributePacked(bool value) {
setFlag(fIsAttributePacked, value);
}
bool isOperatorKeyword() const { bool isOperatorKeyword() const {
return getFlag(fIsOperatorKeyword); return getFlag(fIsOperatorKeyword);
} }
@ -838,9 +844,10 @@ private:
fIsAttributeNoreturn = (1 << 12), // __attribute__((noreturn)), __declspec(noreturn) fIsAttributeNoreturn = (1 << 12), // __attribute__((noreturn)), __declspec(noreturn)
fIsAttributeNothrow = (1 << 13), // __attribute__((nothrow)), __declspec(nothrow) fIsAttributeNothrow = (1 << 13), // __attribute__((nothrow)), __declspec(nothrow)
fIsAttributeUsed = (1 << 14), // __attribute__((used)) fIsAttributeUsed = (1 << 14), // __attribute__((used))
fIsOperatorKeyword = (1 << 15), // operator=, etc fIsAttributePacked = (1 << 15), // __attribute__((packed))
fIsComplex = (1 << 16), // complex/_Complex type fIsOperatorKeyword = (1 << 16), // operator=, etc
fIsEnumType = (1 << 17) // enumeration type fIsComplex = (1 << 17), // complex/_Complex type
fIsEnumType = (1 << 18) // enumeration type
}; };
unsigned int _flags; unsigned int _flags;

View File

@ -8585,6 +8585,10 @@ void Tokenizer::simplifyAttribute()
} }
} }
else if (Token::simpleMatch(tok->previous(), "} __attribute__ ( ( packed )")) {
tok->previous()->isAttributePacked(true);
}
Token::eraseTokens(tok, tok->next()->link()->next()); Token::eraseTokens(tok, tok->next()->link()->next());
tok->deleteThis(); tok->deleteThis();
} }

View File

@ -48,6 +48,7 @@ private:
TEST_CASE(structmember10); TEST_CASE(structmember10);
TEST_CASE(structmember11); // #4168 - initialization with {} / passed by address to unknown function TEST_CASE(structmember11); // #4168 - initialization with {} / passed by address to unknown function
TEST_CASE(structmember12); // #7179 - FP unused structmember TEST_CASE(structmember12); // #7179 - FP unused structmember
TEST_CASE(structmember13); // #3088 - __attribute__((packed))
TEST_CASE(structmember_sizeof); TEST_CASE(structmember_sizeof);
TEST_CASE(localvar1); TEST_CASE(localvar1);
@ -422,6 +423,13 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void structmember13() { // #3088 - struct members required by hardware
checkStructMemberUsage("struct S {\n"
" int x;\n"
"} __attribute__((packed));");
ASSERT_EQUALS("", errout.str());
}
void structmember_extern() { void structmember_extern() {
// extern struct => no false positive // extern struct => no false positive
checkStructMemberUsage("extern struct AB\n" checkStructMemberUsage("extern struct AB\n"