SymbolDatabase; First fix to handle when a namespace have many scopes
This commit is contained in:
parent
5e9feb7db1
commit
e6cc7201b0
|
@ -41,6 +41,21 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static std::vector<const Scope *> getAllScopes(const Scope *scope)
|
||||||
|
{
|
||||||
|
if (!scope)
|
||||||
|
return {};
|
||||||
|
if (scope->type != Scope::ScopeType::eNamespace)
|
||||||
|
return {scope};
|
||||||
|
std::vector<const Scope *> ret;
|
||||||
|
for (const Scope *s: scope->nestedIn->nestedList) {
|
||||||
|
if (s->type == Scope::ScopeType::eNamespace && s->className == scope->className)
|
||||||
|
ret.push_back(s);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||||
: mTokenizer(tokenizer), mSettings(settings), mErrorLogger(errorLogger)
|
: mTokenizer(tokenizer), mSettings(settings), mErrorLogger(errorLogger)
|
||||||
{
|
{
|
||||||
|
@ -211,6 +226,8 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
||||||
name = name->next();
|
name = name->next();
|
||||||
|
|
||||||
Scope *new_scope = findScope(name, scope);
|
Scope *new_scope = findScope(name, scope);
|
||||||
|
if (new_scope && new_scope->bodyStart && Token::Match(name, "%name% {") && new_scope->type == Scope::ScopeType::eNamespace)
|
||||||
|
new_scope = nullptr;
|
||||||
|
|
||||||
if (new_scope) {
|
if (new_scope) {
|
||||||
// only create base list for classes and structures
|
// only create base list for classes and structures
|
||||||
|
@ -730,14 +747,21 @@ void SymbolDatabase::createSymbolDatabaseClassInfo()
|
||||||
|
|
||||||
// fill in base class info
|
// fill in base class info
|
||||||
for (Type& type : typeList) {
|
for (Type& type : typeList) {
|
||||||
|
const std::vector<const Scope *> allEnclosingScopes = getAllScopes(type.enclosingScope);
|
||||||
// finish filling in base class info
|
// finish filling in base class info
|
||||||
for (Type::BaseInfo & i : type.derivedFrom) {
|
for (Type::BaseInfo & baseInfo : type.derivedFrom) {
|
||||||
const Type* found = findType(i.nameTok, type.enclosingScope);
|
baseInfo.type = nullptr;
|
||||||
if (found && found->findDependency(&type)) {
|
for (const Scope *enclosingScope: allEnclosingScopes) {
|
||||||
|
const Type* found = findType(baseInfo.nameTok, enclosingScope);
|
||||||
|
if (found) {
|
||||||
|
if (found->findDependency(&type)) {
|
||||||
// circular dependency
|
// circular dependency
|
||||||
//mTokenizer->syntaxError(nullptr);
|
//mTokenizer->syntaxError(nullptr);
|
||||||
} else {
|
} else {
|
||||||
i.type = found;
|
baseInfo.type = found;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4699,15 +4723,16 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
|
||||||
return start->definedType;
|
return start->definedType;
|
||||||
|
|
||||||
while (scope) {
|
while (scope) {
|
||||||
|
for (const Scope *scope2: getAllScopes(scope)) {
|
||||||
// look for type in this scope
|
// look for type in this scope
|
||||||
const Type * type = scope->findType(typeTok->str());
|
const Type * type = scope2->findType(typeTok->str());
|
||||||
|
|
||||||
if (type)
|
if (type)
|
||||||
return type;
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
// look for type in base classes if possible
|
// look for type in base classes if possible
|
||||||
if (scope->isClassOrStruct()) {
|
if (scope->isClassOrStruct()) {
|
||||||
type = findVariableTypeInBase(scope, typeTok);
|
const Type* type = findVariableTypeInBase(scope, typeTok);
|
||||||
|
|
||||||
if (type)
|
if (type)
|
||||||
return type;
|
return type;
|
||||||
|
@ -4717,7 +4742,7 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
|
||||||
if (scope->type == Scope::eFunction && scope->functionOf) {
|
if (scope->type == Scope::eFunction && scope->functionOf) {
|
||||||
const Scope *scope1 = scope->functionOf;
|
const Scope *scope1 = scope->functionOf;
|
||||||
|
|
||||||
type = scope1->findType(typeTok->str());
|
const Type* type = scope1->findType(typeTok->str());
|
||||||
|
|
||||||
if (type)
|
if (type)
|
||||||
return type;
|
return type;
|
||||||
|
|
|
@ -788,7 +788,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void garbageCode83() { // #6771
|
void garbageCode83() { // #6771
|
||||||
ASSERT_THROW(checkCode("namespace A { class } class A { friend C ; } { } ;"), InternalError);
|
checkCode("namespace A { class } class A { friend C ; } { } ;");
|
||||||
}
|
}
|
||||||
|
|
||||||
void garbageCode84() { // #6780
|
void garbageCode84() { // #6780
|
||||||
|
|
|
@ -259,6 +259,7 @@ private:
|
||||||
TEST_CASE(namespaces2);
|
TEST_CASE(namespaces2);
|
||||||
TEST_CASE(namespaces3); // #3854 - unknown macro
|
TEST_CASE(namespaces3); // #3854 - unknown macro
|
||||||
TEST_CASE(namespaces4);
|
TEST_CASE(namespaces4);
|
||||||
|
TEST_CASE(namespacesSameName1);
|
||||||
|
|
||||||
TEST_CASE(tryCatch1);
|
TEST_CASE(tryCatch1);
|
||||||
|
|
||||||
|
@ -354,6 +355,7 @@ private:
|
||||||
TEST_CASE(symboldatabase95); // #10295
|
TEST_CASE(symboldatabase95); // #10295
|
||||||
|
|
||||||
TEST_CASE(createSymbolDatabaseFindAllScopes1);
|
TEST_CASE(createSymbolDatabaseFindAllScopes1);
|
||||||
|
TEST_CASE(createSymbolDatabaseFindAllScopes2);
|
||||||
|
|
||||||
TEST_CASE(enum1);
|
TEST_CASE(enum1);
|
||||||
TEST_CASE(enum2);
|
TEST_CASE(enum2);
|
||||||
|
@ -2606,6 +2608,18 @@ private:
|
||||||
ASSERT_EQUALS(2U, fredAType->classDef->linenr());
|
ASSERT_EQUALS(2U, fredAType->classDef->linenr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void namespacesSameName1() {
|
||||||
|
GET_SYMBOL_DB("namespace N { struct Base{}; }\n"
|
||||||
|
"namespace N { class Derived : public Base {}; }\n");
|
||||||
|
const Token *Base = Token::findsimplematch(tokenizer.tokens(), "public Base")->next();
|
||||||
|
const Type *baseType = Base->type();
|
||||||
|
ASSERT(baseType);
|
||||||
|
const Type *derivedType = Token::findsimplematch(tokenizer.tokens(), "Derived")->type();
|
||||||
|
ASSERT(derivedType);
|
||||||
|
ASSERT_EQUALS(1, derivedType->derivedFrom.size());
|
||||||
|
ASSERT_EQUALS(baseType, derivedType->derivedFrom[0].type);
|
||||||
|
}
|
||||||
|
|
||||||
void tryCatch1() {
|
void tryCatch1() {
|
||||||
const char str[] = "void foo() {\n"
|
const char str[] = "void foo() {\n"
|
||||||
" try { }\n"
|
" try { }\n"
|
||||||
|
@ -3794,31 +3808,31 @@ private:
|
||||||
"}");
|
"}");
|
||||||
|
|
||||||
ASSERT(db != nullptr);
|
ASSERT(db != nullptr);
|
||||||
ASSERT(db && db->scopeList.size() == 8);
|
ASSERT_EQUALS(9, db->scopeList.size());
|
||||||
ASSERT(db && db->classAndStructScopes.size() == 2);
|
ASSERT_EQUALS(2, db->classAndStructScopes.size());
|
||||||
ASSERT(db && db->typeList.size() == 2);
|
ASSERT_EQUALS(2, db->typeList.size());
|
||||||
ASSERT(db && db->functionScopes.size() == 4);
|
ASSERT_EQUALS(4, db->functionScopes.size());
|
||||||
|
|
||||||
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
|
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
|
||||||
ASSERT(db && functionToken && functionToken->function() &&
|
ASSERT(functionToken && functionToken->function() &&
|
||||||
functionToken->function()->functionScope &&
|
functionToken->function()->functionScope &&
|
||||||
functionToken->function()->tokenDef->linenr() == 5 &&
|
functionToken->function()->tokenDef->linenr() == 5 &&
|
||||||
functionToken->function()->token->linenr() == 11);
|
functionToken->function()->token->linenr() == 11);
|
||||||
|
|
||||||
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
|
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
|
||||||
ASSERT(db && functionToken && functionToken->next()->function() &&
|
ASSERT(functionToken && functionToken->next()->function() &&
|
||||||
functionToken->next()->function()->functionScope &&
|
functionToken->next()->function()->functionScope &&
|
||||||
functionToken->next()->function()->tokenDef->linenr() == 6 &&
|
functionToken->next()->function()->tokenDef->linenr() == 6 &&
|
||||||
functionToken->next()->function()->token->linenr() == 12);
|
functionToken->next()->function()->token->linenr() == 12);
|
||||||
|
|
||||||
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred :: impl & ) { }");
|
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred :: impl & ) { }");
|
||||||
ASSERT(db && functionToken && functionToken->function() &&
|
ASSERT(functionToken && functionToken->function() &&
|
||||||
functionToken->function()->functionScope &&
|
functionToken->function()->functionScope &&
|
||||||
functionToken->function()->tokenDef->linenr() == 7 &&
|
functionToken->function()->tokenDef->linenr() == 7 &&
|
||||||
functionToken->function()->token->linenr() == 13);
|
functionToken->function()->token->linenr() == 13);
|
||||||
|
|
||||||
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred :: impl & , const Fred :: impl & ) const { }");
|
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred :: impl & , const Fred :: impl & ) const { }");
|
||||||
ASSERT(db && functionToken && functionToken->function() &&
|
ASSERT(functionToken && functionToken->function() &&
|
||||||
functionToken->function()->functionScope &&
|
functionToken->function()->functionScope &&
|
||||||
functionToken->function()->tokenDef->linenr() == 8 &&
|
functionToken->function()->tokenDef->linenr() == 8 &&
|
||||||
functionToken->function()->token->linenr() == 14);
|
functionToken->function()->token->linenr() == 14);
|
||||||
|
@ -4186,31 +4200,31 @@ private:
|
||||||
"}");
|
"}");
|
||||||
|
|
||||||
ASSERT(db != nullptr);
|
ASSERT(db != nullptr);
|
||||||
ASSERT(db && db->scopeList.size() == 8);
|
ASSERT_EQUALS(9, db->scopeList.size());
|
||||||
ASSERT(db && db->classAndStructScopes.size() == 2);
|
ASSERT_EQUALS(2, db->classAndStructScopes.size());
|
||||||
ASSERT(db && db->typeList.size() == 2);
|
ASSERT_EQUALS(2, db->typeList.size());
|
||||||
ASSERT(db && db->functionScopes.size() == 4);
|
ASSERT_EQUALS(4, db->functionScopes.size());
|
||||||
|
|
||||||
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
|
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
|
||||||
ASSERT(db && functionToken && functionToken->function() &&
|
ASSERT(functionToken && functionToken->function() &&
|
||||||
functionToken->function()->functionScope &&
|
functionToken->function()->functionScope &&
|
||||||
functionToken->function()->tokenDef->linenr() == 5 &&
|
functionToken->function()->tokenDef->linenr() == 5 &&
|
||||||
functionToken->function()->token->linenr() == 11);
|
functionToken->function()->token->linenr() == 11);
|
||||||
|
|
||||||
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
|
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
|
||||||
ASSERT(db && functionToken && functionToken->next()->function() &&
|
ASSERT(functionToken && functionToken->next()->function() &&
|
||||||
functionToken->next()->function()->functionScope &&
|
functionToken->next()->function()->functionScope &&
|
||||||
functionToken->next()->function()->tokenDef->linenr() == 6 &&
|
functionToken->next()->function()->tokenDef->linenr() == 6 &&
|
||||||
functionToken->next()->function()->token->linenr() == 12);
|
functionToken->next()->function()->token->linenr() == 12);
|
||||||
|
|
||||||
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred < A > :: impl & ) { }");
|
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred < A > :: impl & ) { }");
|
||||||
ASSERT(db && functionToken && functionToken->function() &&
|
ASSERT(functionToken && functionToken->function() &&
|
||||||
functionToken->function()->functionScope &&
|
functionToken->function()->functionScope &&
|
||||||
functionToken->function()->tokenDef->linenr() == 7 &&
|
functionToken->function()->tokenDef->linenr() == 7 &&
|
||||||
functionToken->function()->token->linenr() == 13);
|
functionToken->function()->token->linenr() == 13);
|
||||||
|
|
||||||
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred < A > :: impl & , const Fred < A > :: impl & ) const { }");
|
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred < A > :: impl & , const Fred < A > :: impl & ) const { }");
|
||||||
ASSERT(db && functionToken && functionToken->function() &&
|
ASSERT(functionToken && functionToken->function() &&
|
||||||
functionToken->function()->functionScope &&
|
functionToken->function()->functionScope &&
|
||||||
functionToken->function()->tokenDef->linenr() == 8 &&
|
functionToken->function()->tokenDef->linenr() == 8 &&
|
||||||
functionToken->function()->token->linenr() == 14);
|
functionToken->function()->token->linenr() == 14);
|
||||||
|
@ -4789,6 +4803,17 @@ private:
|
||||||
ASSERT_EQUALS(Scope::eUnion, db->scopeList.back().type);
|
ASSERT_EQUALS(Scope::eUnion, db->scopeList.back().type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void createSymbolDatabaseFindAllScopes2() {
|
||||||
|
GET_SYMBOL_DB("namespace ns { auto var1{0}; }\n"
|
||||||
|
"namespace ns { auto var2{0}; }\n");
|
||||||
|
ASSERT(db);
|
||||||
|
ASSERT_EQUALS(3, db->scopeList.size());
|
||||||
|
const Token* const var1 = Token::findsimplematch(tokenizer.tokens(), "var1");
|
||||||
|
const Token* const var2 = Token::findsimplematch(tokenizer.tokens(), "var2");
|
||||||
|
ASSERT(var1->variable());
|
||||||
|
ASSERT(var2->variable());
|
||||||
|
}
|
||||||
|
|
||||||
void enum1() {
|
void enum1() {
|
||||||
GET_SYMBOL_DB("enum BOOL { FALSE, TRUE }; enum BOOL b;");
|
GET_SYMBOL_DB("enum BOOL { FALSE, TRUE }; enum BOOL b;");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue