diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index fd98fd68c..bc051b5e6 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1443,6 +1443,9 @@ void CheckUnusedVar::checkStructMemberUsage() if (scope.bodyStart->fileIndex() != 0 || scope.className.empty()) continue; + if (scope.classDef->isExpandedMacro()) + continue; + // Packed struct => possibly used by lowlevel code. Struct members might be required by hardware. if (scope.bodyEnd->isAttributePacked()) continue; diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 0e616b01d..318865145 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -71,6 +71,7 @@ private: TEST_CASE(structmember21); // #4759 TEST_CASE(structmember22); // #11016 TEST_CASE(structmember23); + TEST_CASE(structmember_macro); TEST_CASE(classmember); TEST_CASE(localvar1); @@ -272,6 +273,31 @@ private: (checkUnusedVar.checkStructMemberUsage)(); } + void checkStructMemberUsageP(const char code[]) { + // Raw tokens.. + std::vector files(1, "test.cpp"); + std::istringstream istr(code); + const simplecpp::TokenList tokens1(istr, files, files[0]); + + // Preprocess.. + simplecpp::TokenList tokens2(files); + std::map filedata; + simplecpp::preprocess(tokens2, tokens1, files, filedata, simplecpp::DUI()); + + Preprocessor preprocessor(settings); + preprocessor.setDirectives(tokens1); + + // Tokenizer.. + Tokenizer tokenizer(&settings, this, &preprocessor); + tokenizer.createTokens(std::move(tokens2)); + tokenizer.simplifyTokens1(""); + + // Check for unused variables.. + CheckUnusedVar checkUnusedVar(&tokenizer, &settings, this); + (checkUnusedVar.checkStructMemberUsage)(); + } + + void checkFunctionVariableUsageP(const char code[], const char* filename = "test.cpp") { // Raw tokens.. std::vector files(1, filename); @@ -1878,6 +1904,12 @@ private: ASSERT_EQUALS("", errout.str()); } + void structmember_macro() { + checkStructMemberUsageP("#define S(n) struct n { int a, b, c; };\n" + "S(unused);\n"); + ASSERT_EQUALS("", errout.str()); + } + void classmember() { checkStructMemberUsage("class C {\n" " int i{};\n"