From ac1a869d608989f1e92e8c909fe2158028f9ccbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 5 Sep 2016 17:27:12 +0200 Subject: [PATCH] unused struct members: don't warn about packed structs (#3088) --- lib/checkunusedvar.cpp | 4 ++++ lib/token.h | 13 ++++++++++--- lib/tokenize.cpp | 4 ++++ test/testunusedvar.cpp | 8 ++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index edae3154f..fce780187 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1240,6 +1240,10 @@ void CheckUnusedVar::checkStructMemberUsage() if (scope->classStart->fileIndex() != 0 || scope->className.empty()) 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 if (!scope->functionList.empty()) continue; diff --git a/lib/token.h b/lib/token.h index 0707ec9d0..ae950b634 100644 --- a/lib/token.h +++ b/lib/token.h @@ -386,6 +386,12 @@ public: void isAttributeNothrow(bool value) { setFlag(fIsAttributeNothrow, value); } + bool isAttributePacked() const { + return getFlag(fIsAttributePacked); + } + void isAttributePacked(bool value) { + setFlag(fIsAttributePacked, value); + } bool isOperatorKeyword() const { return getFlag(fIsOperatorKeyword); } @@ -838,9 +844,10 @@ private: fIsAttributeNoreturn = (1 << 12), // __attribute__((noreturn)), __declspec(noreturn) fIsAttributeNothrow = (1 << 13), // __attribute__((nothrow)), __declspec(nothrow) fIsAttributeUsed = (1 << 14), // __attribute__((used)) - fIsOperatorKeyword = (1 << 15), // operator=, etc - fIsComplex = (1 << 16), // complex/_Complex type - fIsEnumType = (1 << 17) // enumeration type + fIsAttributePacked = (1 << 15), // __attribute__((packed)) + fIsOperatorKeyword = (1 << 16), // operator=, etc + fIsComplex = (1 << 17), // complex/_Complex type + fIsEnumType = (1 << 18) // enumeration type }; unsigned int _flags; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 90f81842d..6b7fc6653 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -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()); tok->deleteThis(); } diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 22d5d39a7..306190f78 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -48,6 +48,7 @@ private: TEST_CASE(structmember10); TEST_CASE(structmember11); // #4168 - initialization with {} / passed by address to unknown function TEST_CASE(structmember12); // #7179 - FP unused structmember + TEST_CASE(structmember13); // #3088 - __attribute__((packed)) TEST_CASE(structmember_sizeof); TEST_CASE(localvar1); @@ -422,6 +423,13 @@ private: 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() { // extern struct => no false positive checkStructMemberUsage("extern struct AB\n"