Suppress unused struct members from types expanded from macros (#5087)
This commit is contained in:
parent
10b55cc0cf
commit
96c6276ce7
|
@ -1443,6 +1443,9 @@ void CheckUnusedVar::checkStructMemberUsage()
|
||||||
if (scope.bodyStart->fileIndex() != 0 || scope.className.empty())
|
if (scope.bodyStart->fileIndex() != 0 || scope.className.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (scope.classDef->isExpandedMacro())
|
||||||
|
continue;
|
||||||
|
|
||||||
// Packed struct => possibly used by lowlevel code. Struct members might be required by hardware.
|
// Packed struct => possibly used by lowlevel code. Struct members might be required by hardware.
|
||||||
if (scope.bodyEnd->isAttributePacked())
|
if (scope.bodyEnd->isAttributePacked())
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -71,6 +71,7 @@ private:
|
||||||
TEST_CASE(structmember21); // #4759
|
TEST_CASE(structmember21); // #4759
|
||||||
TEST_CASE(structmember22); // #11016
|
TEST_CASE(structmember22); // #11016
|
||||||
TEST_CASE(structmember23);
|
TEST_CASE(structmember23);
|
||||||
|
TEST_CASE(structmember_macro);
|
||||||
TEST_CASE(classmember);
|
TEST_CASE(classmember);
|
||||||
|
|
||||||
TEST_CASE(localvar1);
|
TEST_CASE(localvar1);
|
||||||
|
@ -272,6 +273,31 @@ private:
|
||||||
(checkUnusedVar.checkStructMemberUsage)();
|
(checkUnusedVar.checkStructMemberUsage)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void checkStructMemberUsageP(const char code[]) {
|
||||||
|
// Raw tokens..
|
||||||
|
std::vector<std::string> files(1, "test.cpp");
|
||||||
|
std::istringstream istr(code);
|
||||||
|
const simplecpp::TokenList tokens1(istr, files, files[0]);
|
||||||
|
|
||||||
|
// Preprocess..
|
||||||
|
simplecpp::TokenList tokens2(files);
|
||||||
|
std::map<std::string, simplecpp::TokenList*> 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") {
|
void checkFunctionVariableUsageP(const char code[], const char* filename = "test.cpp") {
|
||||||
// Raw tokens..
|
// Raw tokens..
|
||||||
std::vector<std::string> files(1, filename);
|
std::vector<std::string> files(1, filename);
|
||||||
|
@ -1878,6 +1904,12 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void classmember() {
|
||||||
checkStructMemberUsage("class C {\n"
|
checkStructMemberUsage("class C {\n"
|
||||||
" int i{};\n"
|
" int i{};\n"
|
||||||
|
|
Loading…
Reference in New Issue