Fix #10852 FP unused struct member (inner struct in C code) (#3890)

* Fix #10852 FP unused struct member (inner struct in C code)

* Redundant findType() call, add test
This commit is contained in:
chrchr-github 2022-03-12 06:16:29 +01:00 committed by GitHub
parent ff902369e0
commit 4c85ac0d7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 3 deletions

View File

@ -5423,11 +5423,16 @@ const Scope *SymbolDatabase::findScopeByName(const std::string& name) const
//---------------------------------------------------------------------------
const Scope *Scope::findRecordInNestedList(const std::string & name) const
const Scope *Scope::findRecordInNestedList(const std::string & name, bool isC) const
{
for (const Scope* scope: nestedList) {
if (scope->className == name && scope->type != eFunction)
return scope;
if (isC) {
const Scope* nestedScope = scope->findRecordInNestedList(name, isC);
if (nestedScope)
return nestedScope;
}
}
const Type * nested_type = findType(name);
@ -5546,6 +5551,23 @@ const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startSc
if (startTok->str() == startScope->className && startScope->isClassOrStruct() && startTok->strAt(1) != "::")
return startScope->definedType;
if (mTokenizer->isC()) {
const Scope* scope = startScope;
while (scope) {
if (startTok->str() == scope->className && scope->isClassOrStruct())
return scope->definedType;
const Scope* typeScope = scope->findRecordInNestedList(startTok->str(), /*isC*/ true);
if (typeScope) {
if (startTok->str() == typeScope->className && typeScope->isClassOrStruct()) {
if (const Type* type = typeScope->definedType)
return type;
}
}
scope = scope->nestedIn;
}
return nullptr;
}
const Scope* start_scope = startScope;
// absolute path - directly start in global scope

View File

@ -1129,7 +1129,7 @@ public:
*/
const Function *findFunction(const Token *tok, bool requireConst=false) const;
const Scope *findRecordInNestedList(const std::string & name) const;
const Scope *findRecordInNestedList(const std::string & name, bool isC = false) const;
Scope *findRecordInNestedList(const std::string & name) {
return const_cast<Scope *>(const_cast<const Scope *>(this)->findRecordInNestedList(name));
}

View File

@ -66,7 +66,7 @@ private:
TEST_CASE(structmember16); // #10485
TEST_CASE(structmember17); // #10591
TEST_CASE(structmember18); // #10684
TEST_CASE(structmember19); // #10826, #10848
TEST_CASE(structmember19); // #10826, #10848, #10852
TEST_CASE(localvar1);
TEST_CASE(localvar2);
@ -1710,6 +1710,37 @@ private:
"}\n");
ASSERT_EQUALS("[test.cpp:1]: (style) struct member 'A::i' is never used.\n",
errout.str());
settings.enforcedLang = Settings::C;
checkStructMemberUsage("struct A {\n" // #10852
" struct B {\n"
" int x;\n"
" } b;\n"
"} a;\n"
"void f() {\n"
" struct B* pb = &a.b;\n"
" pb->x = 1;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkStructMemberUsage("union U {\n"
" struct A {\n"
" struct B {\n"
" int x;\n"
" } b;\n"
" } a;\n"
" struct C {\n"
" short s[2];\n"
" } c;\n"
"} u;\n"
"void f() {\n"
" struct B* pb = &u.a.b;\n"
" pb->x = 1;\n"
" struct C* pc = &u.c;\n"
" pc->s[0] = 1;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
settings.enforcedLang = Settings::None;
}
void functionVariableUsage_(const char* file, int line, const char code[], const char filename[] = "test.cpp") {