diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 8a50d52d6..c7f129cff 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -232,7 +232,7 @@ void CheckClass::copyconstructors() } } if (!copyCtor) { - if (!allocatedVars.empty() && scope->derivedFrom.empty()) // TODO: Check if base class is non-copyable + if (!allocatedVars.empty() && scope->definedType->derivedFrom.empty()) // TODO: Check if base class is non-copyable noCopyConstructorError(scope->classDef, scope->className, scope->type == Scope::eStruct); } else { if (!copiedVars.empty()) { @@ -335,14 +335,14 @@ void CheckClass::clearAllVar(std::vector &usage) bool CheckClass::isBaseClassFunc(const Token *tok, const Scope *scope) { // Iterate through each base class... - for (std::size_t i = 0; i < scope->derivedFrom.size(); ++i) { - const Scope *derivedFrom = scope->derivedFrom[i].scope; + for (std::size_t i = 0; i < scope->definedType->derivedFrom.size(); ++i) { + const Type *derivedFrom = scope->definedType->derivedFrom[i].type; // Check if base class exists in database - if (derivedFrom) { + if (derivedFrom && derivedFrom->classScope) { std::list::const_iterator func; - for (func = derivedFrom->functionList.begin(); func != derivedFrom->functionList.end(); ++func) { + for (func = derivedFrom->classScope->functionList.begin(); func != derivedFrom->classScope->functionList.end(); ++func) { if (func->tokenDef->str() == tok->str()) return true; } @@ -586,7 +586,7 @@ void CheckClass::initializeVarList(const Function &func, std::listfriendList.empty()) + if (!scope->definedType->friendList.empty()) assignAllVar(usage); // the function is external and it's neither friend nor inherited virtual function. @@ -766,7 +766,7 @@ void CheckClass::privateFunctions() } // Bailout for overridden virtual functions of base classes - if (!scope->derivedFrom.empty()) { + if (!scope->definedType->derivedFrom.empty()) { // Check virtual functions for (std::list::iterator it = FuncList.begin(); it != FuncList.end();) { if ((*it)->isImplicitlyVirtual(true)) // Give true as default value to be returned if we don't see all base classes @@ -781,8 +781,11 @@ void CheckClass::privateFunctions() // Check that all private functions are used bool used = checkFunctionUsage(funcName, &*scope); // Usage in this class // Check in friend classes - for (std::list::const_iterator it = scope->friendList.begin(); !used && it != scope->friendList.end(); ++it) - used = checkFunctionUsage(funcName, it->scope); + for (std::list::const_iterator it = scope->definedType->friendList.begin(); !used && it != scope->definedType->friendList.end(); ++it) + if (it->type) + used = checkFunctionUsage(funcName, it->type->classScope); + else + used = true; // Assume, it is used if we do not see friend class if (!used) unusedPrivateFunctionError(FuncList.front()->tokenDef, scope->className, funcName); @@ -885,9 +888,9 @@ void CheckClass::noMemset() void CheckClass::checkMemsetType(const Scope *start, const Token *tok, const Scope *type, bool allocation) { // recursively check all parent classes - for (std::size_t i = 0; i < type->derivedFrom.size(); i++) { - if (type->derivedFrom[i].scope) - checkMemsetType(start, tok, type->derivedFrom[i].scope, allocation); + for (std::size_t i = 0; i < type->definedType->derivedFrom.size(); i++) { + if (type->definedType->derivedFrom[i].type && type->definedType->derivedFrom[i].type->classScope) + checkMemsetType(start, tok, type->definedType->derivedFrom[i].type->classScope, allocation); } // Warn if type is a class that contains any virtual functions @@ -1101,7 +1104,7 @@ void CheckClass::operatorEqToSelf() std::list::const_iterator func; // skip classes with multiple inheritance - if (scope->derivedFrom.size() > 1) + if (scope->definedType->derivedFrom.size() > 1) continue; for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { @@ -1215,7 +1218,7 @@ void CheckClass::virtualDestructor() const Scope * scope = symbolDatabase->classAndStructScopes[i]; // Skip base classes - if (scope->derivedFrom.empty()) + if (scope->definedType->derivedFrom.empty()) continue; // Find the destructor @@ -1233,13 +1236,13 @@ void CheckClass::virtualDestructor() const Token *derivedClass = derived->next(); // Iterate through each base class... - for (unsigned int j = 0; j < scope->derivedFrom.size(); ++j) { + for (unsigned int j = 0; j < scope->definedType->derivedFrom.size(); ++j) { // Check if base class is public and exists in database - if (scope->derivedFrom[j].access != Private && scope->derivedFrom[j].scope) { - const Scope *derivedFrom = scope->derivedFrom[j].scope; - - // Name of base class.. - const std::string& baseName = derivedFrom->className; + if (scope->definedType->derivedFrom[j].access != Private && scope->definedType->derivedFrom[j].type) { + const Type *derivedFrom = scope->definedType->derivedFrom[j].type; + const Scope *derivedFromScope = derivedFrom->classScope; + if (!derivedFromScope) + continue; // Check for this pattern: // 1. Base class pointer is given the address of derived class instance @@ -1250,6 +1253,12 @@ void CheckClass::virtualDestructor() // pointer variables of type 'Base *' std::set basepointer; + for (std::size_t i = 0; i < symbolDatabase->getVariableListSize(); i++) { + const Variable* var = symbolDatabase->getVariableFromVarId(i); + if (var && var->isPointer() && var->type() == derivedFrom) + basepointer.insert(var->varId()); + } + // pointer variables of type 'Base *' that should not be deleted std::set dontDelete; @@ -1257,16 +1266,9 @@ void CheckClass::virtualDestructor() bool ok = true; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { - // Declaring base class pointer - if (Token::simpleMatch(tok, baseName.c_str())) { - if (Token::Match(tok->previous(), ("[;{}] " + baseName + " * %var% ;").c_str())) - basepointer.insert(tok->tokAt(2)->varId()); - } - - // Assign base class pointer with pointer to derived class instance - else if (Token::Match(tok, "[;{}] %var% =") && - tok->next()->varId() > 0 && - basepointer.find(tok->next()->varId()) != basepointer.end()) { + if (Token::Match(tok, "[;{}] %var% =") && + tok->next()->varId() > 0 && + basepointer.find(tok->next()->varId()) != basepointer.end()) { // new derived class.. if (Token::simpleMatch(tok->tokAt(3), ("new " + derivedClass->str()).c_str())) { dontDelete.insert(tok->next()->varId()); @@ -1288,7 +1290,7 @@ void CheckClass::virtualDestructor() } // Find the destructor declaration for the base class. - const Function *base_destructor = derivedFrom->getDestructor(); + const Function *base_destructor = derivedFromScope->getDestructor(); const Token *base = 0; if (base_destructor) base = base_destructor->token; @@ -1296,7 +1298,7 @@ void CheckClass::virtualDestructor() // Check that there is a destructor.. if (!base_destructor) { if (derivedFrom->derivedFrom.empty()) - virtualDestructorError(derivedFrom->classDef, baseName, derivedClass->str()); + virtualDestructorError(derivedFrom->classDef, derivedFrom->name(), derivedClass->str()); } else if (!base_destructor->isVirtual) { // TODO: This is just a temporary fix, better solution is needed. // Skip situations where base class has base classes of its own, because @@ -1309,7 +1311,7 @@ void CheckClass::virtualDestructor() // would not compile if inheritance is used in a way that would // cause the bug we are trying to find here.) if (base_destructor->access == Public) - virtualDestructorError(base, baseName, derivedClass->str()); + virtualDestructorError(base, derivedFrom->name(), derivedClass->str()); } } } @@ -1409,7 +1411,7 @@ void CheckClass::checkConst() } // check if base class function is virtual - if (!scope->derivedFrom.empty()) { + if (!scope->definedType->derivedFrom.empty()) { if (func->isImplicitlyVirtual(true)) continue; } @@ -1479,15 +1481,15 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) } // not found in this class - if (!scope->derivedFrom.empty()) { + if (!scope->definedType->derivedFrom.empty()) { // check each base class - for (unsigned int i = 0; i < scope->derivedFrom.size(); ++i) { + for (unsigned int i = 0; i < scope->definedType->derivedFrom.size(); ++i) { // find the base class - const Scope *derivedFrom = scope->derivedFrom[i].scope; + const Type *derivedFrom = scope->definedType->derivedFrom[i].type; // find the function in the base class - if (derivedFrom) { - if (isMemberVar(derivedFrom, tok)) + if (derivedFrom && derivedFrom->classScope) { + if (isMemberVar(derivedFrom->classScope, tok)) return true; } } @@ -1545,15 +1547,15 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) } // not found in this class - if (!scope->derivedFrom.empty()) { + if (!scope->definedType->derivedFrom.empty()) { // check each base class - for (unsigned int i = 0; i < scope->derivedFrom.size(); ++i) { + for (unsigned int i = 0; i < scope->definedType->derivedFrom.size(); ++i) { // find the base class - const Scope *derivedFrom = scope->derivedFrom[i].scope; + const Type *derivedFrom = scope->definedType->derivedFrom[i].type; // find the function in the base class - if (derivedFrom) { - if (isMemberFunc(derivedFrom, tok)) + if (derivedFrom && derivedFrom->classScope) { + if (isMemberFunc(derivedFrom->classScope, tok)) return true; } } @@ -1585,15 +1587,15 @@ bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) return true; // not found in this class - if (!scope->derivedFrom.empty()) { + if (!scope->definedType->derivedFrom.empty()) { // check each base class - for (unsigned int i = 0; i < scope->derivedFrom.size(); ++i) { + for (unsigned int i = 0; i < scope->definedType->derivedFrom.size(); ++i) { // find the base class - const Scope *derivedFrom = scope->derivedFrom[i].scope; + const Type *derivedFrom = scope->definedType->derivedFrom[i].type; // find the function in the base class - if (derivedFrom) { - if (isConstMemberFunc(derivedFrom, tok)) + if (derivedFrom && derivedFrom->classScope) { + if (isConstMemberFunc(derivedFrom->classScope, tok)) return true; } } diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 4c95bd24d..39d19d336 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -117,7 +117,7 @@ bool CheckMemoryLeak::isclass(const Token *tok, unsigned int varid) const /** @todo false negative: check constructors for side effects */ if (var && var->typeScope() && var->typeScope()->numConstructors == 0 && (var->typeScope()->varlist.empty() || var->type()->needInitialization == Type::True) && - var->typeScope()->derivedFrom.empty()) + var->type()->derivedFrom.empty()) return false; return true; @@ -2349,9 +2349,9 @@ void CheckMemoryLeakInClass::check() } // known class? - else if (var->typeScope()) { + else if (var->type()) { // not derived? - if (var->typeScope()->derivedFrom.empty()) { + if (var->type()->derivedFrom.empty()) { if (var->isPrivate()) checkPublicFunctions(&(*scope), var->nameToken()); diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 36e86d46c..f0b62d940 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -608,15 +608,15 @@ static const Token* doAssignment(Variables &variables, const Token *tok, bool de return tok; } -static bool isRecordTypeWithoutSideEffects(const Scope* type) +static bool isRecordTypeWithoutSideEffects(const Type* type) { // a type that has no side effects (no constructors and no members with constructors) /** @todo false negative: check constructors for side effects */ - if (type && type->numConstructors == 0 && - (type->varlist.empty() || type->definedType->needInitialization == Type::True)) { + if (type && type->classScope && type->classScope->numConstructors == 0 && + (type->classScope->varlist.empty() || type->needInitialization == Type::True)) { bool yes = true; - for (std::vector::const_iterator i = type->derivedFrom.begin(); yes && i != type->derivedFrom.end(); ++i) - yes = isRecordTypeWithoutSideEffects(i->scope); + for (std::vector::const_iterator i = type->derivedFrom.begin(); yes && i != type->derivedFrom.end(); ++i) + yes = isRecordTypeWithoutSideEffects(i->type); return yes; } return false; @@ -688,7 +688,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const type = Variables::pointer; else if (_tokenizer->isC() || i->typeEndToken()->isStandardType() || - isRecordTypeWithoutSideEffects(i->typeScope()) || + isRecordTypeWithoutSideEffects(i->type()) || (Token::simpleMatch(i->typeStartToken(), "std ::") && i->typeStartToken()->strAt(2) != "lock_guard" && i->typeStartToken()->strAt(2) != "unique_lock")) @@ -893,7 +893,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const // is it a user defined type? if (!type->isStandardType()) { const Variable *variable = start->variable(); - if (!variable || !isRecordTypeWithoutSideEffects(variable->typeScope())) + if (!variable || !isRecordTypeWithoutSideEffects(variable->type())) allocate = false; } } diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 55bdd8f3b..94761d9c8 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -81,7 +81,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // only create base list for classes and structures if (new_scope->isClassOrStruct()) { // goto initial '{' - tok2 = new_scope->initBaseInfo(tok, tok2); + tok2 = new_scope->definedType->initBaseInfo(tok, tok2); // make sure we have valid code if (!tok2) { @@ -113,10 +113,22 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti else if (tok->str() == "struct") access[new_scope] = Public; + // fill typeList... + if (new_scope->isClassOrStruct() || new_scope->type == Scope::eUnion) { + Type* new_type = findType(tok->next(), scope); + if (!new_type) { + typeList.push_back(Type(new_scope->classDef, new_scope, scope)); + new_type = &typeList.back(); + scope->definedTypes.push_back(new_type); + } else + new_type->classScope = new_scope; + new_scope->definedType = new_type; + } + // only create base list for classes and structures if (new_scope->isClassOrStruct()) { // goto initial '{' - tok2 = new_scope->initBaseInfo(tok, tok2); + tok2 = new_scope->definedType->initBaseInfo(tok, tok2); // make sure we have valid code if (!tok2) { @@ -134,18 +146,6 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti break; } - // fill typeList... - if (new_scope->isClassOrStruct() || new_scope->type == Scope::eUnion) { - Type* new_type = findType(tok->next(), scope); - if (!new_type) { - typeList.push_back(Type(new_scope->classDef, new_scope, scope)); - new_type = &typeList.back(); - scope->definedTypes.push_back(new_type); - } else - new_type->classScope = new_scope; - new_scope->definedType = new_type; - } - // make the new scope the current scope scope = new_scope; scope->nestedIn->nestedList.push_back(scope); @@ -503,7 +503,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // friend class declaration? else if (Token::Match(tok, "friend class| ::| %any% ;|::")) { - Scope::FriendInfo friendInfo; + Type::FriendInfo friendInfo; // save the name start friendInfo.nameStart = tok->strAt(1) == "class" ? tok->tokAt(2) : tok->tokAt(1); @@ -522,9 +522,9 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti friendInfo.name = friendInfo.nameEnd->str(); // fill this in after parsing is complete - friendInfo.scope = 0; + friendInfo.type = 0; - scope->friendList.push_back(friendInfo); + scope->definedType->friendList.push_back(friendInfo); } } else if (scope->type == Scope::eNamespace || scope->type == Scope::eGlobal) { const Token *funcStart = 0; @@ -695,54 +695,22 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti } } - std::list::iterator it; - // fill in base class info - for (it = scopeList.begin(); it != scopeList.end(); ++it) { - scope = &(*it); - - // skip namespaces and functions - if (!scope->isClassOrStruct()) - continue; - + for (std::list::iterator it = typeList.begin(); it != typeList.end(); ++it) { // finish filling in base class info - for (unsigned int i = 0; i < scope->derivedFrom.size(); ++i) { - std::list::const_iterator it1; - - // check all scopes for match - for (it1 = scopeList.begin(); it1 != scopeList.end(); ++it1) { - // check scope for match - const Scope *scope1 = it1->findQualifiedScope(scope->derivedFrom[i].name); - - // found match? - if (scope1) { - // set found scope - scope->derivedFrom[i].scope = const_cast(scope1); - break; - } - } - } + for (unsigned int i = 0; i < it->derivedFrom.size(); ++i) + it->derivedFrom[i].type = findType(it->derivedFrom[i].nameTok, it->enclosingScope); } // fill in friend info - for (it = scopeList.begin(); it != scopeList.end(); ++it) { - for (std::list::iterator i = it->friendList.begin(); i != it->friendList.end(); ++i) { - for (std::list::iterator j = scopeList.begin(); j != scopeList.end(); ++j) { - // check scope for match - scope = findScope(i->nameStart, it->nestedIn); - - // found match? - if (scope && scope->isClassOrStruct()) { - // set found scope - i->scope = scope; - break; - } - } + for (std::list::iterator it = typeList.begin(); it != typeList.end(); ++it) { + for (std::list::iterator i = it->friendList.begin(); i != it->friendList.end(); ++i) { + i->type = findType(i->nameStart, it->enclosingScope); } } // fill in using info - for (it = scopeList.begin(); it != scopeList.end(); ++it) { + for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { for (std::list::iterator i = it->usingList.begin(); i != it->usingList.end(); ++i) { // check scope for match scope = findScope(i->start->tokAt(2), &(*it)); @@ -755,13 +723,13 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti } // fill in variable info - for (it = scopeList.begin(); it != scopeList.end(); ++it) { + for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { // find variables it->getVariableList(); } // fill in function arguments - for (it = scopeList.begin(); it != scopeList.end(); ++it) { + for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { std::list::iterator func; for (func = it->functionList.begin(); func != it->functionList.end(); ++func) { @@ -771,13 +739,13 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti } // fill in function scopes - for (it = scopeList.begin(); it != scopeList.end(); ++it) { + for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { if (it->type == Scope::eFunction) functionScopes.push_back(&*it); } // fill in class and struct scopes - for (it = scopeList.begin(); it != scopeList.end(); ++it) { + for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { if (it->isClassOrStruct()) classAndStructScopes.push_back(&*it); } @@ -789,7 +757,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti do { unknowns = 0; - for (it = scopeList.begin(); it != scopeList.end(); ++it) { + for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { scope = &(*it); if (scope->isClassOrStruct() && scope->definedType->needInitialization == Type::Unknown) { @@ -830,9 +798,9 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti if (var->isClass()) { if (var->type()) { // does this type need initialization? - if (var->typeScope()->definedType->needInitialization == Type::True) + if (var->type()->needInitialization == Type::True) needInitialization = true; - else if (var->typeScope()->definedType->needInitialization == Type::Unknown) + else if (var->type()->needInitialization == Type::Unknown) unknown = true; } } else @@ -858,7 +826,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // this shouldn't happen so output a debug warning if (retry == 100 && _settings->debugwarnings) { - for (it = scopeList.begin(); it != scopeList.end(); ++it) { + for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { scope = &(*it); if (scope->isClassOrStruct() && scope->definedType->needInitialization == Type::Unknown) @@ -871,7 +839,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti std::fill_n(_variableList.begin(), _variableList.size(), (const Variable*)NULL); // check all scopes for variables - for (it = scopeList.begin(); it != scopeList.end(); ++it) { + for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { scope = &(*it); // add all variables @@ -1412,7 +1380,7 @@ void SymbolDatabase::addNewFunction(Scope **scope, const Token **tok) } } -const Token *Scope::initBaseInfo(const Token *tok, const Token *tok1) +const Token *Type::initBaseInfo(const Token *tok, const Token *tok1) { // goto initial '{' const Token *tok2 = tok1; @@ -1423,7 +1391,7 @@ const Token *Scope::initBaseInfo(const Token *tok, const Token *tok1) // check for base classes else if (Token::Match(tok2, ":|,")) { - Scope::BaseInfo base; + Type::BaseInfo base; base.isVirtual = false; @@ -1459,21 +1427,20 @@ const Token *Scope::initBaseInfo(const Token *tok, const Token *tok1) tok2 = tok2->next(); } + base.nameTok = tok2; + // handle global namespace if (tok2->str() == "::") { - base.name = ":: "; tok2 = tok2->next(); } // handle derived base classes while (Token::Match(tok2, "%var% ::")) { - base.name += tok2->str(); - base.name += " :: "; tok2 = tok2->tokAt(2); } - base.name += tok2->str(); - base.scope = NULL; + base.name = tok2->str(); + base.type = NULL; // add unhandled templates if (tok2->next() && tok2->next()->str() == "<") { @@ -1628,9 +1595,7 @@ void SymbolDatabase::printOut(const char *title) const if (title) std::cout << "\n### " << title << " ###\n"; - std::list::const_iterator scope; - - for (scope = scopeList.begin(); scope != scopeList.end(); ++scope) { + for (std::list::const_iterator scope = scopeList.begin(); scope != scopeList.end(); ++scope) { std::cout << "Scope: " << &*scope << std::endl; std::cout << " type: " << scope->type << std::endl; std::cout << " className: " << scope->className << std::endl; @@ -1718,48 +1683,6 @@ void SymbolDatabase::printOut(const char *title) const printVariable(&*var, " "); } - std::cout << " derivedFrom[" << scope->derivedFrom.size() << "] = ("; - - std::size_t count = scope->derivedFrom.size(); - for (std::size_t i = 0; i < scope->derivedFrom.size(); ++i) { - if (scope->derivedFrom[i].isVirtual) - std::cout << "Virtual "; - - std::cout << (scope->derivedFrom[i].access == Public ? " Public " : - scope->derivedFrom[i].access == Protected ? " Protected " : - scope->derivedFrom[i].access == Private ? " Private " : - " Unknown"); - - if (scope->derivedFrom[i].scope) - std::cout << scope->derivedFrom[i].scope->type; - else - std::cout << " Unknown"; - - std::cout << " " << scope->derivedFrom[i].name; - if (count-- > 1) - std::cout << ","; - } - - std::cout << " )" << std::endl; - - std::cout << " friendList[" << scope->friendList.size() << "] = ("; - - std::list::const_iterator fii; - - count = scope->friendList.size(); - for (fii = scope->friendList.begin(); fii != scope->friendList.end(); ++fii) { - if (fii->scope) - std::cout << fii->scope->type; - else - std::cout << " Unknown"; - - std::cout << " " << fii->name; - if (count-- > 1) - std::cout << ","; - } - - std::cout << " )" << std::endl; - std::cout << " nestedIn: " << scope->nestedIn; if (scope->nestedIn) { std::cout << " " << scope->nestedIn->type << " " @@ -1767,11 +1690,13 @@ void SymbolDatabase::printOut(const char *title) const } std::cout << std::endl; + std::cout << " definedType: " << scope->definedType; + std::cout << " nestedList[" << scope->nestedList.size() << "] = ("; std::list::const_iterator nsi; - count = scope->nestedList.size(); + std::size_t count = scope->nestedList.size(); for (nsi = scope->nestedList.begin(); nsi != scope->nestedList.end(); ++nsi) { std::cout << " " << (*nsi) << " " << (*nsi)->type << " " << (*nsi)->className; if (count-- > 1) @@ -1780,11 +1705,6 @@ void SymbolDatabase::printOut(const char *title) const std::cout << " )" << std::endl; - std::cout << " needInitialization: " << (scope->definedType->needInitialization == Type::Unknown ? "Unknown" : - scope->definedType->needInitialization == Type::True ? "True" : - scope->definedType->needInitialization == Type::False ? "False" : - "Invalid") << std::endl; - std::list::const_iterator use; for (use = scope->usingList.begin(); use != scope->usingList.end(); ++use) { @@ -1813,7 +1733,59 @@ void SymbolDatabase::printOut(const char *title) const std::cout << std::endl; } - for (std::size_t i = 0; i < _variableList.size(); i++) { + for (std::list::const_iterator type = typeList.begin(); type != typeList.end(); ++type) { + std::cout << "Type: " << type->name() << std::endl; + std::cout << " classDef: " << _tokenizer->list.fileLine(type->classDef) << std::endl; + std::cout << " classScope: " << type->classScope << std::endl; + std::cout << " enclosingScope: " << type->enclosingScope << std::endl; + std::cout << " needInitialization: " << (type->needInitialization == Type::Unknown ? "Unknown" : + type->needInitialization == Type::True ? "True" : + type->needInitialization == Type::False ? "False" : + "Invalid") << std::endl; + + std::cout << " derivedFrom[" << type->derivedFrom.size() << "] = ("; + std::size_t count = type->derivedFrom.size(); + for (std::size_t i = 0; i < type->derivedFrom.size(); ++i) { + if (type->derivedFrom[i].isVirtual) + std::cout << "Virtual "; + + std::cout << (type->derivedFrom[i].access == Public ? " Public " : + type->derivedFrom[i].access == Protected ? " Protected " : + type->derivedFrom[i].access == Private ? " Private " : + " Unknown"); + + if (type->derivedFrom[i].type) + std::cout << type->derivedFrom[i].type; + else + std::cout << " Unknown"; + + std::cout << " " << type->derivedFrom[i].name; + if (count-- > 1) + std::cout << ","; + } + + std::cout << " )" << std::endl; + + std::cout << " friendList[" << type->friendList.size() << "] = ("; + + std::list::const_iterator fii; + + count = type->friendList.size(); + for (fii = type->friendList.begin(); fii != type->friendList.end(); ++fii) { + if (fii->type) + std::cout << fii->type; + else + std::cout << " Unknown"; + + std::cout << " " << fii->name; + if (count-- > 1) + std::cout << ","; + } + + std::cout << " )" << std::endl; + } + + for (std::size_t i = 0; i < typeList.size(); i++) { std::cout << "_variableList[" << i << "] = " << _variableList[i] << std::endl; } } @@ -1924,7 +1896,7 @@ bool Function::isImplicitlyVirtual(bool defaultVal) const return true; else if (access == Private || access == Public || access == Protected) { bool safe = true; - bool hasVirt = isImplicitlyVirtual_rec(nestedIn, safe); + bool hasVirt = isImplicitlyVirtual_rec(nestedIn->definedType, safe); if (hasVirt) return true; else if (safe) @@ -1935,13 +1907,13 @@ bool Function::isImplicitlyVirtual(bool defaultVal) const return false; } -bool Function::isImplicitlyVirtual_rec(const Scope* scope, bool& safe) const +bool Function::isImplicitlyVirtual_rec(const ::Type* type, bool& safe) const { // check each base class - for (unsigned int i = 0; i < scope->derivedFrom.size(); ++i) { + for (unsigned int i = 0; i < type->derivedFrom.size(); ++i) { // check if base class exists in database - if (scope->derivedFrom[i].scope) { - const Scope *parent = scope->derivedFrom[i].scope; + if (type->derivedFrom[i].type && type->derivedFrom[i].type->classScope) { + const Scope *parent = type->derivedFrom[i].type->classScope; std::list::const_iterator func; @@ -1964,14 +1936,14 @@ bool Function::isImplicitlyVirtual_rec(const Scope* scope, bool& safe) const } // check for matching function parameters - if (returnMatch && argsMatch(scope, func->argDef, argDef, "", 0)) { + if (returnMatch && argsMatch(type->classScope, func->argDef, argDef, "", 0)) { return true; } } } - if (!parent->derivedFrom.empty()) - if (isImplicitlyVirtual_rec(parent, safe)) + if (!type->derivedFrom[i].type->derivedFrom.empty()) + if (isImplicitlyVirtual_rec(type->derivedFrom[i].type, safe)) return true; } else { // unable to find base class so assume it has no virtual function @@ -2577,31 +2549,6 @@ Scope *Scope::findInNestedListRecursive(const std::string & name) //--------------------------------------------------------------------------- -const Scope *Scope::findQualifiedScope(const std::string & name) const -{ - if (type == Scope::eClass || type == Scope::eStruct || type == Scope::eNamespace) { - if (name.compare(0, className.size(), className) == 0) { - std::string path = name; - path.erase(0, className.size()); - if (path.compare(0, 4, " :: ") == 0) - path.erase(0, 4); - else if (path.empty()) - return this; - - std::list::const_iterator it; - - for (it = nestedList.begin() ; it != nestedList.end(); ++it) { - const Scope *scope1 = (*it)->findQualifiedScope(path); - if (scope1) - return scope1; - } - } - } - return 0; -} - -//--------------------------------------------------------------------------- - const Function *Scope::getDestructor() const { std::list::const_iterator it; @@ -2660,23 +2607,29 @@ const Scope *SymbolDatabase::findScope(const Token *tok, const Scope *startScope return 0; } -const Type *SymbolDatabase::findType(const Token *tok, const Scope *startScope) const +const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startScope) const { - const Scope *scope = 0; - // absolute path - if (tok->str() == "::") { - tok = tok->next(); - scope = &scopeList.front(); - } - // relative path - else if (tok->isName()) { - scope = startScope; + // absolute path - directly start in global scope + if (startTok->str() == "::") { + startTok = startTok->next(); + startScope = &scopeList.front(); } + const Token* tok = startTok; + const Scope* scope = startScope; + while (scope && tok && tok->isName()) { if (tok->strAt(1) == "::") { scope = scope->findRecordInNestedList(tok->str()); - tok = tok->tokAt(2); + if (scope) { + tok = tok->tokAt(2); + } else { + startScope = startScope->nestedIn; + if (!startScope) + break; + scope = startScope; + tok = startTok; + } } else return scope->findType(tok->str()); } diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 3817cab6b..805dcacde 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -64,6 +64,24 @@ public: Unknown, True, False } needInitialization; + struct BaseInfo { + std::string name; + const Type* type; + const Token* nameTok; + AccessControl access; // public/protected/private + bool isVirtual; + }; + + struct FriendInfo { + const Token* nameStart; + const Token* nameEnd; + std::string name; + const Type* type; + }; + + std::vector derivedFrom; + std::list friendList; + Type(const Token* classDef_ = 0, const Scope* classScope_ = 0, const Scope* enclosingScope_ = 0) : classDef(classDef_), classScope(classScope_), @@ -75,6 +93,8 @@ public: static const std::string empty; return classDef->next()->isName() ? classDef->strAt(1) : empty; } + + const Token *initBaseInfo(const Token *tok, const Token *tok1); }; /** @brief Information about a member variable. */ @@ -471,7 +491,7 @@ public: static bool argsMatch(const Scope *info, const Token *first, const Token *second, const std::string &path, unsigned int depth); private: - bool isImplicitlyVirtual_rec(const Scope* scope, bool& safe) const; + bool isImplicitlyVirtual_rec(const ::Type* type, bool& safe) const; }; class CPPCHECKLIB Scope { @@ -479,20 +499,6 @@ class CPPCHECKLIB Scope { friend class TestSymbolDatabase; public: - struct BaseInfo { - std::string name; - Scope *scope; - AccessControl access; // public/protected/private - bool isVirtual; - }; - - struct FriendInfo { - const Token *nameStart; - const Token *nameEnd; - std::string name; - Scope *scope; - }; - struct UsingInfo { const Token *start; Scope *scope; @@ -510,8 +516,6 @@ public: const Token *classEnd; // '}' token std::list functionList; std::list varlist; - std::vector derivedFrom; - std::list friendList; Scope *nestedIn; std::list nestedList; unsigned int numConstructors; @@ -557,7 +561,10 @@ public: return const_cast(static_cast(this)->findRecordInNestedList(name)); } - const Type *findType(const std::string & name) const; + const Type* findType(const std::string& name) const; + Type* findType(const std::string& name) { + return const_cast(static_cast(this)->findType(name)); + } /** * @brief find if name is in nested list @@ -565,8 +572,6 @@ public: */ Scope *findInNestedListRecursive(const std::string & name); - const Scope *findQualifiedScope(const std::string & name) const; - void addVariable(const Token *token_, const Token *start_, const Token *end_, AccessControl access_, const Type *type_, const Scope *scope_) { @@ -575,8 +580,6 @@ public: type_, scope_)); } - const Token *initBaseInfo(const Token *tok, const Token *tok1); - /** @brief initialize varlist */ void getVariableList(); @@ -653,9 +656,9 @@ public: const Scope *findScopeByName(const std::string& name) const; - const Type *findType(const Token *tok, const Scope *startScope) const; - Type *findType(const Token *tok, Scope *startScope) const { - return const_cast(this->findType(tok, static_cast(startScope))); + const Type* findType(const Token *tok, const Scope *startScope) const; + Type* findType(const Token *tok, Scope *startScope) const { + return const_cast(this->findType(tok, static_cast(startScope))); } const Scope *findScope(const Token *tok, const Scope *startScope) const;