SymbolDatabase; Better handling of namespace that is defined in several scopes
This commit is contained in:
parent
0f897acecd
commit
0093452bed
|
@ -235,8 +235,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
||||||
}
|
}
|
||||||
|
|
||||||
new_scope->classDef = tok;
|
new_scope->classDef = tok;
|
||||||
new_scope->bodyStart = tok2;
|
new_scope->setBodyStartEnd(tok2);
|
||||||
new_scope->bodyEnd = tok2->link();
|
|
||||||
// make sure we have valid code
|
// make sure we have valid code
|
||||||
if (!new_scope->bodyEnd) {
|
if (!new_scope->bodyEnd) {
|
||||||
mTokenizer->syntaxError(tok);
|
mTokenizer->syntaxError(tok);
|
||||||
|
@ -278,8 +277,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
||||||
tok2 = tok2->tokAt(2);
|
tok2 = tok2->tokAt(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_scope->bodyStart = tok2;
|
new_scope->setBodyStartEnd(tok2);
|
||||||
new_scope->bodyEnd = tok2->link();
|
|
||||||
|
|
||||||
// make sure we have valid code
|
// make sure we have valid code
|
||||||
if (!new_scope->bodyEnd) {
|
if (!new_scope->bodyEnd) {
|
||||||
|
@ -314,8 +312,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
||||||
|
|
||||||
const Token *tok2 = tok->linkAt(3)->next();
|
const Token *tok2 = tok->linkAt(3)->next();
|
||||||
|
|
||||||
new_scope->bodyStart = tok2;
|
new_scope->setBodyStartEnd(tok2);
|
||||||
new_scope->bodyEnd = tok2->link();
|
|
||||||
|
|
||||||
// make sure we have valid code
|
// make sure we have valid code
|
||||||
if (!new_scope->bodyEnd) {
|
if (!new_scope->bodyEnd) {
|
||||||
|
@ -403,8 +400,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
||||||
|
|
||||||
const Token *tok2 = tok->next();
|
const Token *tok2 = tok->next();
|
||||||
|
|
||||||
new_scope->bodyStart = tok2;
|
new_scope->setBodyStartEnd(tok2);
|
||||||
new_scope->bodyEnd = tok2->link();
|
|
||||||
|
|
||||||
// make sure we have valid code
|
// make sure we have valid code
|
||||||
if (!new_scope->bodyEnd) {
|
if (!new_scope->bodyEnd) {
|
||||||
|
@ -430,8 +426,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
||||||
|
|
||||||
const Token *tok2 = tok->next();
|
const Token *tok2 = tok->next();
|
||||||
|
|
||||||
new_scope->bodyStart = tok2;
|
new_scope->setBodyStartEnd(tok2);
|
||||||
new_scope->bodyEnd = tok2->link();
|
|
||||||
|
|
||||||
typeList.emplace_back(tok, new_scope, scope);
|
typeList.emplace_back(tok, new_scope, scope);
|
||||||
{
|
{
|
||||||
|
@ -1003,26 +998,20 @@ void SymbolDatabase::createSymbolDatabaseVariableSymbolTable()
|
||||||
|
|
||||||
void SymbolDatabase::createSymbolDatabaseSetScopePointers()
|
void SymbolDatabase::createSymbolDatabaseSetScopePointers()
|
||||||
{
|
{
|
||||||
// Set scope pointers
|
auto setScopePointers = [this](const Scope &scope, const Token *bodyStart, const Token *bodyEnd) {
|
||||||
for (const Scope& scope: scopeList) {
|
assert(bodyStart);
|
||||||
Token* start = const_cast<Token*>(scope.bodyStart);
|
assert(bodyEnd);
|
||||||
Token* end = const_cast<Token*>(scope.bodyEnd);
|
|
||||||
if (scope.type == Scope::eGlobal) {
|
|
||||||
start = const_cast<Token*>(mTokenizer->list.front());
|
|
||||||
end = const_cast<Token*>(mTokenizer->list.back());
|
|
||||||
}
|
|
||||||
assert(start);
|
|
||||||
assert(end);
|
|
||||||
|
|
||||||
end->scope(&scope);
|
const_cast<Token *>(bodyEnd)->scope(&scope);
|
||||||
|
|
||||||
for (Token* tok = start; tok != end; tok = tok->next()) {
|
for (Token* tok = const_cast<Token *>(bodyStart); tok != bodyEnd; tok = tok->next()) {
|
||||||
if (start != end && tok->str() == "{") {
|
if (bodyStart != bodyEnd && tok->str() == "{") {
|
||||||
bool isEndOfScope = false;
|
bool isEndOfScope = false;
|
||||||
for (const Scope* innerScope: scope.nestedList) {
|
for (Scope* innerScope: scope.nestedList) {
|
||||||
if (tok == innerScope->bodyStart) { // Is begin of inner scope
|
const auto &list = innerScope->bodyStartList;
|
||||||
|
if (std::find(list.begin(), list.end(), tok) != list.end()) { // Is begin of inner scope
|
||||||
tok = tok->link();
|
tok = tok->link();
|
||||||
if (tok->next() == end || !tok->next()) {
|
if (tok->next() == bodyEnd || !tok->next()) {
|
||||||
isEndOfScope = true;
|
isEndOfScope = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1035,6 +1024,16 @@ void SymbolDatabase::createSymbolDatabaseSetScopePointers()
|
||||||
}
|
}
|
||||||
tok->scope(&scope);
|
tok->scope(&scope);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set scope pointers
|
||||||
|
for (Scope& scope: scopeList) {
|
||||||
|
if (scope.type == Scope::eGlobal)
|
||||||
|
setScopePointers(scope, mTokenizer->list.front(), mTokenizer->list.back());
|
||||||
|
else {
|
||||||
|
for (const Token *bodyStart: scope.bodyStartList)
|
||||||
|
setScopePointers(scope, bodyStart, bodyStart->link());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3005,8 +3004,7 @@ void SymbolDatabase::addNewFunction(Scope **scope, const Token **tok)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok1 && tok1->str() == "{") {
|
if (tok1 && tok1->str() == "{") {
|
||||||
newScope->bodyStart = tok1;
|
newScope->setBodyStartEnd(tok1);
|
||||||
newScope->bodyEnd = tok1->link();
|
|
||||||
|
|
||||||
// syntax error?
|
// syntax error?
|
||||||
if (!newScope->bodyEnd) {
|
if (!newScope->bodyEnd) {
|
||||||
|
@ -4070,8 +4068,6 @@ const Variable* Function::getArgumentVar(nonneg int num) const
|
||||||
Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *nestedIn_, ScopeType type_, const Token *start_) :
|
Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *nestedIn_, ScopeType type_, const Token *start_) :
|
||||||
check(check_),
|
check(check_),
|
||||||
classDef(classDef_),
|
classDef(classDef_),
|
||||||
bodyStart(start_),
|
|
||||||
bodyEnd(start_->link()),
|
|
||||||
nestedIn(nestedIn_),
|
nestedIn(nestedIn_),
|
||||||
numConstructors(0),
|
numConstructors(0),
|
||||||
numCopyOrMoveConstructors(0),
|
numCopyOrMoveConstructors(0),
|
||||||
|
@ -4081,7 +4077,9 @@ Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *
|
||||||
function(nullptr),
|
function(nullptr),
|
||||||
enumType(nullptr),
|
enumType(nullptr),
|
||||||
enumClass(false)
|
enumClass(false)
|
||||||
{}
|
{
|
||||||
|
setBodyStartEnd(start_);
|
||||||
|
}
|
||||||
|
|
||||||
Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *nestedIn_) :
|
Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *nestedIn_) :
|
||||||
check(check_),
|
check(check_),
|
||||||
|
@ -4173,19 +4171,22 @@ void Scope::addVariable(const Token *token_, const Token *start_, const Token *e
|
||||||
// Get variable list..
|
// Get variable list..
|
||||||
void Scope::getVariableList(const Settings* settings)
|
void Scope::getVariableList(const Settings* settings)
|
||||||
{
|
{
|
||||||
const Token *start;
|
if (!bodyStartList.empty()) {
|
||||||
|
for (const Token *bodyStart: bodyStartList)
|
||||||
if (bodyStart)
|
getVariableList(settings, bodyStart->next());
|
||||||
start = bodyStart->next();
|
}
|
||||||
|
|
||||||
// global scope
|
// global scope
|
||||||
else if (className.empty())
|
else if (type == Scope::eGlobal)
|
||||||
start = check->mTokenizer->tokens();
|
getVariableList(settings, check->mTokenizer->tokens());
|
||||||
|
|
||||||
// forward declaration
|
// forward declaration
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scope::getVariableList(const Settings* settings, const Token* start)
|
||||||
|
{
|
||||||
// Variable declared in condition: if (auto x = bar())
|
// Variable declared in condition: if (auto x = bar())
|
||||||
if (Token::Match(classDef, "if|while ( %type%") && Token::simpleMatch(classDef->next()->astOperand2(), "=")) {
|
if (Token::Match(classDef, "if|while ( %type%") && Token::simpleMatch(classDef->next()->astOperand2(), "=")) {
|
||||||
checkVariable(classDef->tokAt(2), defaultAccess(), settings);
|
checkVariable(classDef->tokAt(2), defaultAccess(), settings);
|
||||||
|
|
|
@ -1038,6 +1038,7 @@ public:
|
||||||
ScopeType type;
|
ScopeType type;
|
||||||
Type* definedType;
|
Type* definedType;
|
||||||
std::map<std::string, Type*> definedTypesMap;
|
std::map<std::string, Type*> definedTypesMap;
|
||||||
|
std::vector<const Token *> bodyStartList;
|
||||||
|
|
||||||
// function specific fields
|
// function specific fields
|
||||||
const Scope *functionOf; ///< scope this function belongs to
|
const Scope *functionOf; ///< scope this function belongs to
|
||||||
|
@ -1049,6 +1050,13 @@ public:
|
||||||
|
|
||||||
std::vector<Enumerator> enumeratorList;
|
std::vector<Enumerator> enumeratorList;
|
||||||
|
|
||||||
|
void setBodyStartEnd(const Token *start) {
|
||||||
|
bodyStart = start;
|
||||||
|
bodyEnd = start ? start->link() : nullptr;
|
||||||
|
if (start)
|
||||||
|
bodyStartList.push_back(start);
|
||||||
|
}
|
||||||
|
|
||||||
bool isAnonymous() const {
|
bool isAnonymous() const {
|
||||||
// TODO: Check if class/struct is anonymous
|
// TODO: Check if class/struct is anonymous
|
||||||
return className.size() > 9 && className.compare(0,9,"Anonymous") == 0 && std::isdigit(className[9]);
|
return className.size() > 9 && className.compare(0,9,"Anonymous") == 0 && std::isdigit(className[9]);
|
||||||
|
@ -1194,6 +1202,9 @@ private:
|
||||||
bool isVariableDeclaration(const Token* const tok, const Token*& vartok, const Token*& typetok) const;
|
bool isVariableDeclaration(const Token* const tok, const Token*& vartok, const Token*& typetok) const;
|
||||||
|
|
||||||
void findFunctionInBase(const std::string & name, nonneg int args, std::vector<const Function *> & matches) const;
|
void findFunctionInBase(const std::string & name, nonneg int args, std::vector<const Function *> & matches) const;
|
||||||
|
|
||||||
|
/** @brief initialize varlist */
|
||||||
|
void getVariableList(const Settings* settings, const Token *start);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Reference {
|
enum class Reference {
|
||||||
|
|
|
@ -353,6 +353,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);
|
||||||
|
@ -4788,6 +4789,18 @@ 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(2, db->scopeList.size());
|
||||||
|
ASSERT_EQUALS(2, db->scopeList.back().varlist.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