- Moved more functionality from Scope to Type: BaseInfo and FriendInfo
- Replaced Scope->findQualifiedScope by SymbolDatabase::findScope - Improved SymbolDatabase::findType
This commit is contained in:
parent
66a3555897
commit
7bc729bc63
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue