From cd3044c808e7c8e7279d286adcdfe1e484e5917f Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Mon, 12 Aug 2013 06:21:03 +0200 Subject: [PATCH] Fixed #4952 (SymbolDatabase: unknown types in log file) --- lib/symboldatabase.cpp | 30 +++++++++++++++++++++++++----- lib/symboldatabase.h | 11 +++++++++++ test/testsymboldatabase.cpp | 29 +++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 707c1f12a..8f469358f 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -830,23 +830,35 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti scope = &(*it); // add all variables - std::list::const_iterator var; + std::list::iterator var; for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var) { unsigned int varId = var->declarationId(); if (varId) _variableList[varId] = &(*var); + // fix up variables without type + if (var->isClass() && !var->type()) { + const Type *type = findType(var->typeStartToken(), scope); + if (type) + var->type(type); + } } // add all function parameters - std::list::const_iterator func; + std::list::iterator func; for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { - std::list::const_iterator arg; + std::list::iterator arg; for (arg = func->argumentList.begin(); arg != func->argumentList.end(); ++arg) { // check for named parameters if (arg->nameToken() && arg->declarationId()) { const unsigned int declarationId = arg->declarationId(); if (declarationId > 0U) _variableList[declarationId] = &(*arg); + // fix up parameters without type + if (!arg->type()) { + const Type *type = findType(arg->typeStartToken(), scope); + if (type) + arg->type(type); + } } } } @@ -2655,13 +2667,22 @@ const Scope *SymbolDatabase::findScope(const Token *tok, const Scope *startScope return scope->findRecordInNestedList(tok->str()); } - // not a valid path return 0; } +//--------------------------------------------------------------------------- + const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startScope) const { + // skip over struct or union + if (Token::Match(startTok, "struct|union")) + startTok = startTok->next(); + + // type same as scope + if (startTok->str() == startScope->className && startScope->isClassOrStruct()) + return startScope->definedType; + // absolute path - directly start in global scope if (startTok->str() == "::") { startTok = startTok->next(); @@ -2687,7 +2708,6 @@ const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startSc return scope->findType(tok->str()); } - // not a valid path return 0; } diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index ead2c1e38..1db9f3ab5 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -399,6 +399,17 @@ public: } private: + // only symbol database can change the type + friend class SymbolDatabase; + + /** + * Set Type pointer to known type. + * @param t type + */ + void type(const Type * t) { + _type = t; + } + /** @brief variable name token */ const Token *_name; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index fd1408530..4f4c7184c 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -197,6 +197,7 @@ private: TEST_CASE(symboldatabase34); // ticket #4694 (segmentation fault) TEST_CASE(symboldatabase35); // ticket #4806 (segmentation fault) TEST_CASE(symboldatabase36); // ticket #4892 (segmentation fault) + TEST_CASE(symboldatabase37); TEST_CASE(isImplicitlyVirtual); @@ -1582,6 +1583,34 @@ private: ASSERT_EQUALS("", errout.str()); } + void symboldatabase37() { + GET_SYMBOL_DB("class Fred {\n" + "public:\n" + " struct Barney {\n" + " bool operator == (const struct Barney & b) const { return true; }\n" + " };\n" + " Fred(const struct Barney & b) { barney = b; }\n" + "private:\n" + " struct Barney barney;\n" + "};\n"); + ASSERT(db && db->typeList.size() == 2); + ASSERT(db && db->isClassOrStruct("Fred")); + ASSERT(db && db->isClassOrStruct("Barney")); + if (!db || db->typeList.size() == 2) + return; + std::list::const_iterator i = db->typeList.begin(); + const Type* Fred = &(*i++); + const Type* Barney = &(*i++); + ASSERT(Fred && Fred->classDef && Fred->classScope && Fred->enclosingScope && Fred->name() == "Fred"); + ASSERT(Barney && Barney->classDef && Barney->classScope && Barney->enclosingScope && Barney->name() == "Barney"); + + ASSERT(db && db->getVariableListSize() == 4); + if (!db || db->getVariableListSize() == 4) + return; + ASSERT(db && db->getVariableFromVarId(1) && db->getVariableFromVarId(1)->type() && db->getVariableFromVarId(1)->type()->name() == "Barney"); + ASSERT(db && db->getVariableFromVarId(2) && db->getVariableFromVarId(2)->type() && db->getVariableFromVarId(2)->type()->name() == "Barney"); + } + void isImplicitlyVirtual() { { GET_SYMBOL_DB("class Base {\n"