- Moved more functionality from Scope to Type: BaseInfo and FriendInfo

- Replaced Scope->findQualifiedScope by SymbolDatabase::findScope
- Improved SymbolDatabase::findType
This commit is contained in:
PKEuS 2013-03-05 06:28:40 -08:00
parent 66a3555897
commit 7bc729bc63
5 changed files with 210 additions and 252 deletions

View File

@ -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> &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<Function>::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::list<const Functio
}
// has friends, so we assume it initializes everything
if (!scope->friendList.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<const Function*>::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<Scope::FriendInfo>::const_iterator it = scope->friendList.begin(); !used && it != scope->friendList.end(); ++it)
used = checkFunctionUsage(funcName, it->scope);
for (std::list<Type::FriendInfo>::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<Function>::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<unsigned int> 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<unsigned int> dontDelete;
@ -1257,14 +1266,7 @@ 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% =") &&
if (Token::Match(tok, "[;{}] %var% =") &&
tok->next()->varId() > 0 &&
basepointer.find(tok->next()->varId()) != basepointer.end()) {
// new derived class..
@ -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;
}
}

View File

@ -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());

View File

@ -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<Scope::BaseInfo>::const_iterator i = type->derivedFrom.begin(); yes && i != type->derivedFrom.end(); ++i)
yes = isRecordTypeWithoutSideEffects(i->scope);
for (std::vector<Type::BaseInfo>::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;
}
}

View File

@ -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<Scope>::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<Type>::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<Scope>::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<Scope *>(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<Scope::FriendInfo>::iterator i = it->friendList.begin(); i != it->friendList.end(); ++i) {
for (std::list<Scope>::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<Type>::iterator it = typeList.begin(); it != typeList.end(); ++it) {
for (std::list<Type::FriendInfo>::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<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
for (std::list<Scope::UsingInfo>::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<Scope>::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<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
std::list<Function>::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<Scope>::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<Scope>::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<Scope>::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<Scope>::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<Scope>::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<Scope>::const_iterator scope;
for (scope = scopeList.begin(); scope != scopeList.end(); ++scope) {
for (std::list<Scope>::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<Scope::FriendInfo>::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<Scope *>::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<Scope::UsingInfo>::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<Type>::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<Type::FriendInfo>::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<Function>::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<Scope *>::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<Function>::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());
if (scope) {
tok = tok->tokAt(2);
} else {
startScope = startScope->nestedIn;
if (!startScope)
break;
scope = startScope;
tok = startTok;
}
} else
return scope->findType(tok->str());
}

View File

@ -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<BaseInfo> derivedFrom;
std::list<FriendInfo> 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<Function> functionList;
std::list<Variable> varlist;
std::vector<BaseInfo> derivedFrom;
std::list<FriendInfo> friendList;
Scope *nestedIn;
std::list<Scope *> nestedList;
unsigned int numConstructors;
@ -557,7 +561,10 @@ public:
return const_cast<Scope *>(static_cast<const Scope *>(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<Type*>(static_cast<const Scope *>(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<Type *>(this->findType(tok, static_cast<const Scope *>(startScope)));
const Type* findType(const Token *tok, const Scope *startScope) const;
Type* findType(const Token *tok, Scope *startScope) const {
return const_cast<Type*>(this->findType(tok, static_cast<const Scope *>(startScope)));
}
const Scope *findScope(const Token *tok, const Scope *startScope) const;