diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 5eb69a48c..43b72488e 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1002,24 +1002,24 @@ void SymbolDatabase::createSymbolDatabaseVariableSymbolTable() } // fill in missing variables if possible - const std::size_t functions = functionScopes.size(); - for (std::size_t i = 0; i < functions; ++i) { - const Scope *func = functionScopes[i]; + for (const Scope *func: functionScopes) { for (const Token *tok = func->bodyStart->next(); tok && tok != func->bodyEnd; tok = tok->next()) { // check for member variable - if (tok->varId() && tok->next() && - (tok->next()->str() == "." || - (tok->next()->str() == "[" && tok->linkAt(1)->strAt(1) == "."))) { - const Token *tok1 = tok->next()->str() == "." ? tok->tokAt(2) : tok->linkAt(1)->tokAt(2); - if (tok1 && tok1->varId() && mVariableList[tok1->varId()] == nullptr) { - const Variable *var = mVariableList[tok->varId()]; - if (var && var->typeScope()) { - // find the member variable of this variable - const Variable *var1 = var->typeScope()->getVariable(tok1->str()); - if (var1) { - // add this variable to the look up table - mVariableList[tok1->varId()] = var1; - } + if (!Token::Match(tok, "%var% .|[")) + continue; + const Token* tokDot = tok->next(); + while (Token::simpleMatch(tokDot, "[")) + tokDot = tokDot->link()->next(); + if (!Token::Match(tokDot, ". %var%")) + continue; + const Token *member = tokDot->next(); + if (mVariableList[member->varId()] == nullptr) { + const Variable *var1 = mVariableList[tok->varId()]; + if (var1 && var1->typeScope()) { + const Variable* memberVar = var1->typeScope()->getVariable(member->str()); + if (memberVar) { + // add this variable to the look up table + mVariableList[member->varId()] = memberVar; } } } @@ -4442,7 +4442,6 @@ void Scope::getVariableList(const Settings* settings, const Token* start, const // Is it a function? else if (tok->str() == "{") { - tok = tok->link(); continue; } @@ -4614,13 +4613,18 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess, con const Variable *Scope::getVariable(const std::string &varname) const { - std::list::const_iterator iter; - - for (iter = varlist.begin(); iter != varlist.end(); ++iter) { - if (iter->name() == varname) - return &*iter; + for (const Variable& var: varlist) { + if (var.name() == varname) + return &var; + } + if (definedType) { + for (const Type::BaseInfo& baseInfo: definedType->derivedFrom) { + if (baseInfo.type && baseInfo.type->classScope) { + if (const Variable* var = baseInfo.type->classScope->getVariable(varname)) + return var; + } + } } - return nullptr; } diff --git a/test/testimportproject.cpp b/test/testimportproject.cpp index 1d7bb8039..2d39345e5 100644 --- a/test/testimportproject.cpp +++ b/test/testimportproject.cpp @@ -352,7 +352,7 @@ private: ASSERT_EQUALS("lib/", s.includePaths.front()); } - void ignorePaths() { + void ignorePaths() const { ImportProject::FileSettings fs1, fs2; fs1.filename = "foo/bar"; fs2.filename = "qwe/rty"; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 2b2b6d866..50d72a4c9 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -184,6 +184,7 @@ private: TEST_CASE(rangeBasedFor); + TEST_CASE(memberVar1); TEST_CASE(arrayMemberVar1); TEST_CASE(arrayMemberVar2); TEST_CASE(arrayMemberVar3); @@ -1417,6 +1418,22 @@ private: ASSERT_EQUALS("signed int *", c->valueType()->str()); } + void memberVar1() { + GET_SYMBOL_DB("struct Foo {\n" + " int x;\n" + "};\n" + "struct Bar : public Foo {};\n" + "void f() {\n" + " struct Bar bar;\n" + " bar.x = 123;\n" // <- x should get a variable() pointer + "}"); + + ASSERT(db != nullptr); + const Token *tok = Token::findsimplematch(tokenizer.tokens(), "x ="); + ASSERT(tok->variable()); + ASSERT(Token::simpleMatch(tok->variable()->typeStartToken(), "int x ;")); + } + void arrayMemberVar1() { GET_SYMBOL_DB("struct Foo {\n" " int x;\n"