Partial fix for #10848 FP: unusedStructMember (II) (#3881)

* Preliminary

* Fix member search, add tests
This commit is contained in:
chrchr-github 2022-03-09 18:22:30 +01:00 committed by GitHub
parent 850ad0fed9
commit 557263acde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 16 deletions

View File

@ -1210,20 +1210,36 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers()
// Set Token::variable pointer for array member variable
// Since it doesn't point at a fixed location it doesn't have varid
if (tok->variable() != nullptr &&
(tok->variable()->typeScope() || tok->variable()->isSmartPointer() || (tok->valueType() && tok->valueType()->type == ValueType::CONTAINER)) &&
Token::Match(tok, "%name% [|.")) {
Token *tok2 = tok->next();
// Locate "]"
while (tok2 && tok2->str() == "[")
tok2 = tok2->link()->next();
Token *membertok = nullptr;
if (Token::Match(tok2, ". %name%"))
membertok = tok2->next();
else if (Token::Match(tok2, ") . %name%") && tok->strAt(-1) == "(")
membertok = tok2->tokAt(2);
const bool isVar = tok->variable() && (tok->variable()->typeScope() || tok->variable()->isSmartPointer() || (tok->valueType() && tok->valueType()->type == ValueType::CONTAINER));
const bool isArrayAccess = isVar && Token::simpleMatch(tok->astParent(), "[");
const bool isDirectAccess = isVar && !isArrayAccess && Token::simpleMatch(tok->astParent(), ".");
const bool isDerefAccess = isVar && !isDirectAccess && Token::simpleMatch(tok->astParent(), "*") && Token::simpleMatch(tok->astParent()->astParent(), ".");
if (isVar && (isArrayAccess || isDirectAccess || isDerefAccess)) {
Token* membertok{};
if (isArrayAccess) {
membertok = const_cast<Token*>(tok->astParent());
while (Token::simpleMatch(membertok, "["))
membertok = membertok->astParent();
if (membertok)
membertok = membertok->astOperand2();
}
else if (isDirectAccess) {
membertok = const_cast<Token*>(tok->astParent()->astOperand2());
if (membertok == tok) {
Token* gptok = const_cast<Token*>(tok->astParent()->astParent());
if (Token::simpleMatch(gptok, ".")) // chained access
membertok = gptok->astOperand2();
else if (Token::simpleMatch(gptok, "[") && Token::simpleMatch(gptok->astParent(), "."))
membertok = gptok->astParent()->astOperand2();
}
}
else { // isDerefAccess
membertok = const_cast<Token*>(tok->astParent());
while (Token::simpleMatch(membertok, "*"))
membertok = membertok->astParent();
if (membertok)
membertok = membertok->astOperand2();
}
if (membertok) {
const Variable *var = tok->variable();

View File

@ -1629,8 +1629,8 @@ private:
ASSERT_EQUALS("", errout.str());
}
void structmember19() { // #10826
checkStructMemberUsage("class C {};\n"
void structmember19() {
checkStructMemberUsage("class C {};\n" // #10826
"struct S {\n"
" char* p;\n"
" std::string str;\n"
@ -1653,6 +1653,54 @@ private:
"[test.cpp:4]: (style) struct member 'S::str' is never used.\n"
"[test.cpp:5]: (style) struct member 'S::c' is never used.\n",
errout.str());
checkStructMemberUsage("struct S {\n"
" struct T {\n"
" int i;\n"
" } t[2];\n"
"};\n"
"S s[1];\n"
"int f() {\n"
" return s[0].t[1].i;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkStructMemberUsage("struct S { int a; };\n"
"struct T { S s; };\n"
"int f(const T** tp) {\n"
" return tp[0]->s.a;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkStructMemberUsage("struct S { int a; };\n"
"int f(const S* sp) {\n"
" return (*sp).a; \n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkStructMemberUsage("struct S { int a; };\n"
"int f(const S** spp) {\n"
" return spp[0]->a;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkStructMemberUsage("struct S { int a; };\n"
"int f(const S** spp) {\n"
" return spp[0][0].a;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkStructMemberUsage("struct S { int a; };\n"
"int f(const S* sp) {\n"
" return sp[0].a;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkStructMemberUsage("struct S { int a; };\n"
"int f(const S* sp) {\n"
" return sp->a;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void functionVariableUsage_(const char* file, int line, const char code[], const char filename[] = "test.cpp") {