* Preliminary * Fix member search, add tests
This commit is contained in:
parent
850ad0fed9
commit
557263acde
|
@ -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();
|
||||
|
|
|
@ -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") {
|
||||
|
|
Loading…
Reference in New Issue