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->bodyStart = tok2;
|
||||
new_scope->bodyEnd = tok2->link();
|
||||
new_scope->setBodyStartEnd(tok2);
|
||||
// make sure we have valid code
|
||||
if (!new_scope->bodyEnd) {
|
||||
mTokenizer->syntaxError(tok);
|
||||
|
@ -278,8 +277,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
|||
tok2 = tok2->tokAt(2);
|
||||
}
|
||||
|
||||
new_scope->bodyStart = tok2;
|
||||
new_scope->bodyEnd = tok2->link();
|
||||
new_scope->setBodyStartEnd(tok2);
|
||||
|
||||
// make sure we have valid code
|
||||
if (!new_scope->bodyEnd) {
|
||||
|
@ -314,8 +312,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
|||
|
||||
const Token *tok2 = tok->linkAt(3)->next();
|
||||
|
||||
new_scope->bodyStart = tok2;
|
||||
new_scope->bodyEnd = tok2->link();
|
||||
new_scope->setBodyStartEnd(tok2);
|
||||
|
||||
// make sure we have valid code
|
||||
if (!new_scope->bodyEnd) {
|
||||
|
@ -403,8 +400,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
|||
|
||||
const Token *tok2 = tok->next();
|
||||
|
||||
new_scope->bodyStart = tok2;
|
||||
new_scope->bodyEnd = tok2->link();
|
||||
new_scope->setBodyStartEnd(tok2);
|
||||
|
||||
// make sure we have valid code
|
||||
if (!new_scope->bodyEnd) {
|
||||
|
@ -430,8 +426,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
|||
|
||||
const Token *tok2 = tok->next();
|
||||
|
||||
new_scope->bodyStart = tok2;
|
||||
new_scope->bodyEnd = tok2->link();
|
||||
new_scope->setBodyStartEnd(tok2);
|
||||
|
||||
typeList.emplace_back(tok, new_scope, scope);
|
||||
{
|
||||
|
@ -1003,26 +998,20 @@ void SymbolDatabase::createSymbolDatabaseVariableSymbolTable()
|
|||
|
||||
void SymbolDatabase::createSymbolDatabaseSetScopePointers()
|
||||
{
|
||||
// Set scope pointers
|
||||
for (const Scope& scope: scopeList) {
|
||||
Token* start = const_cast<Token*>(scope.bodyStart);
|
||||
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);
|
||||
auto setScopePointers = [this](const Scope &scope, const Token *bodyStart, const Token *bodyEnd) {
|
||||
assert(bodyStart);
|
||||
assert(bodyEnd);
|
||||
|
||||
end->scope(&scope);
|
||||
const_cast<Token *>(bodyEnd)->scope(&scope);
|
||||
|
||||
for (Token* tok = start; tok != end; tok = tok->next()) {
|
||||
if (start != end && tok->str() == "{") {
|
||||
for (Token* tok = const_cast<Token *>(bodyStart); tok != bodyEnd; tok = tok->next()) {
|
||||
if (bodyStart != bodyEnd && tok->str() == "{") {
|
||||
bool isEndOfScope = false;
|
||||
for (const Scope* innerScope: scope.nestedList) {
|
||||
if (tok == innerScope->bodyStart) { // Is begin of inner scope
|
||||
for (Scope* innerScope: scope.nestedList) {
|
||||
const auto &list = innerScope->bodyStartList;
|
||||
if (std::find(list.begin(), list.end(), tok) != list.end()) { // Is begin of inner scope
|
||||
tok = tok->link();
|
||||
if (tok->next() == end || !tok->next()) {
|
||||
if (tok->next() == bodyEnd || !tok->next()) {
|
||||
isEndOfScope = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1035,6 +1024,16 @@ void SymbolDatabase::createSymbolDatabaseSetScopePointers()
|
|||
}
|
||||
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() == "{") {
|
||||
newScope->bodyStart = tok1;
|
||||
newScope->bodyEnd = tok1->link();
|
||||
newScope->setBodyStartEnd(tok1);
|
||||
|
||||
// syntax error?
|
||||
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_) :
|
||||
check(check_),
|
||||
classDef(classDef_),
|
||||
bodyStart(start_),
|
||||
bodyEnd(start_->link()),
|
||||
nestedIn(nestedIn_),
|
||||
numConstructors(0),
|
||||
numCopyOrMoveConstructors(0),
|
||||
|
@ -4081,7 +4077,9 @@ Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *
|
|||
function(nullptr),
|
||||
enumType(nullptr),
|
||||
enumClass(false)
|
||||
{}
|
||||
{
|
||||
setBodyStartEnd(start_);
|
||||
}
|
||||
|
||||
Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *nestedIn_) :
|
||||
check(check_),
|
||||
|
@ -4173,19 +4171,22 @@ void Scope::addVariable(const Token *token_, const Token *start_, const Token *e
|
|||
// Get variable list..
|
||||
void Scope::getVariableList(const Settings* settings)
|
||||
{
|
||||
const Token *start;
|
||||
|
||||
if (bodyStart)
|
||||
start = bodyStart->next();
|
||||
if (!bodyStartList.empty()) {
|
||||
for (const Token *bodyStart: bodyStartList)
|
||||
getVariableList(settings, bodyStart->next());
|
||||
}
|
||||
|
||||
// global scope
|
||||
else if (className.empty())
|
||||
start = check->mTokenizer->tokens();
|
||||
else if (type == Scope::eGlobal)
|
||||
getVariableList(settings, check->mTokenizer->tokens());
|
||||
|
||||
// forward declaration
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
void Scope::getVariableList(const Settings* settings, const Token* start)
|
||||
{
|
||||
// Variable declared in condition: if (auto x = bar())
|
||||
if (Token::Match(classDef, "if|while ( %type%") && Token::simpleMatch(classDef->next()->astOperand2(), "=")) {
|
||||
checkVariable(classDef->tokAt(2), defaultAccess(), settings);
|
||||
|
|
|
@ -1038,6 +1038,7 @@ public:
|
|||
ScopeType type;
|
||||
Type* definedType;
|
||||
std::map<std::string, Type*> definedTypesMap;
|
||||
std::vector<const Token *> bodyStartList;
|
||||
|
||||
// function specific fields
|
||||
const Scope *functionOf; ///< scope this function belongs to
|
||||
|
@ -1049,6 +1050,13 @@ public:
|
|||
|
||||
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 {
|
||||
// TODO: Check if class/struct is anonymous
|
||||
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;
|
||||
|
||||
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 {
|
||||
|
|
|
@ -353,6 +353,7 @@ private:
|
|||
TEST_CASE(symboldatabase95); // #10295
|
||||
|
||||
TEST_CASE(createSymbolDatabaseFindAllScopes1);
|
||||
TEST_CASE(createSymbolDatabaseFindAllScopes2);
|
||||
|
||||
TEST_CASE(enum1);
|
||||
TEST_CASE(enum2);
|
||||
|
@ -4788,6 +4789,18 @@ private:
|
|||
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() {
|
||||
GET_SYMBOL_DB("enum BOOL { FALSE, TRUE }; enum BOOL b;");
|
||||
|
||||
|
|
Loading…
Reference in New Issue