5656#include < utility>
5757// ---------------------------------------------------------------------------
5858
59- SymbolDatabase::SymbolDatabase (Tokenizer& tokenizer)
59+ SymbolDatabase::SymbolDatabase (Tokenizer& tokenizer, bool deferFinalizePhases )
6060 : mTokenizer(tokenizer)
6161 , mSettings(tokenizer.getSettings())
6262 , mErrorLogger(tokenizer.getErrorLogger())
@@ -74,11 +74,9 @@ SymbolDatabase::SymbolDatabase(Tokenizer& tokenizer)
7474 createSymbolDatabaseFindAllScopes ();
7575 createSymbolDatabaseClassInfo ();
7676 createSymbolDatabaseVariableInfo ();
77- createSymbolDatabaseCopyAndMoveConstructors ();
7877 createSymbolDatabaseFunctionScopes ();
7978 createSymbolDatabaseClassAndStructScopes ();
8079 createSymbolDatabaseFunctionReturnTypes ();
81- createSymbolDatabaseNeedInitialization ();
8280 createSymbolDatabaseVariableSymbolTable ();
8381 createSymbolDatabaseSetScopePointers ();
8482 createSymbolDatabaseSetVariablePointers ();
@@ -88,6 +86,22 @@ SymbolDatabase::SymbolDatabase(Tokenizer& tokenizer)
8886 createSymbolDatabaseSetSmartPointerType ();
8987 setValueTypeInTokenList (false );
9088 createSymbolDatabaseEnums ();
89+
90+ if (!deferFinalizePhases)
91+ finalize ();
92+ }
93+
94+ void SymbolDatabase::finalize ()
95+ {
96+ if (mFinalized )
97+ return ;
98+ mFinalized = true ;
99+
100+ if (!mTokenizer .tokens ())
101+ return ;
102+
103+ createSymbolDatabaseCopyAndMoveConstructors ();
104+ createSymbolDatabaseNeedInitialization ();
91105 createSymbolDatabaseEscapeFunctions ();
92106 createSymbolDatabaseIncompleteVars ();
93107 createSymbolDatabaseExprIds ();
@@ -148,8 +162,13 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
148162 // create global scope
149163 scopeList.emplace_back (*this , nullptr , nullptr );
150164
165+ findAllScopes (mTokenizer .tokens (), nullptr , &scopeList.back ());
166+ }
167+
168+ void SymbolDatabase::findAllScopes (const Token* startToken, const Token* endToken, Scope* startScope)
169+ {
151170 // pointer to current scope
152- Scope *scope = &scopeList. back () ;
171+ Scope *scope = startScope ;
153172
154173 // Store the ending of init lists
155174 std::stack<std::pair<const Token*, const Scope*>> endInitList;
@@ -174,6 +193,8 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
174193
175194 // Store current access in each scope (depends on evaluation progress)
176195 std::map<const Scope*, AccessControl> access;
196+ if (startScope->isClassOrStructOrUnion ())
197+ access[startScope] = startScope->type == ScopeType::eClass ? AccessControl::Private : AccessControl::Public;
177198
178199 std::map<const Scope *, std::set<std::string>> forwardDecls;
179200
@@ -202,7 +223,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
202223 ProgressReporter progressReporter (mErrorLogger , mSettings .reportProgress , mTokenizer .list .getSourceFilePath (), " SymbolDatabase (find all scopes)" );
203224
204225 // find all scopes
205- for (const Token *tok = mTokenizer . tokens () ; tok; tok = tok ? tok->next () : nullptr ) {
226+ for (const Token *tok = startToken ; tok && tok != endToken ; tok = tok ? tok->next () : nullptr ) {
206227 // #5593 suggested to add here:
207228
208229 progressReporter.report (tok->progressValue ());
@@ -1835,6 +1856,266 @@ void SymbolDatabase::createSymbolDatabaseExprIds()
18351856 }
18361857}
18371858
1859+ void SymbolDatabase::removeSymbolsInTokenRanges (const std::vector<std::pair<Token*, const Token*>>& ranges)
1860+ {
1861+ if (ranges.empty ())
1862+ return ;
1863+
1864+ // all tokens that are going to be removed
1865+ std::set<const Token*> removedTokens;
1866+ for (const auto & range : ranges) {
1867+ for (const Token* tok = range.first ; tok; tok = tok->next ()) {
1868+ removedTokens.insert (tok);
1869+ if (tok == range.second )
1870+ break ;
1871+ }
1872+ }
1873+
1874+ // the scopes, functions, variables, types and enumerators declared by those tokens
1875+ std::set<const Scope*> removedScopes;
1876+ for (const Scope& scope : scopeList) {
1877+ if ((scope.classDef && removedTokens.count (scope.classDef ) != 0 ) ||
1878+ (scope.bodyStart && removedTokens.count (scope.bodyStart ) != 0 ))
1879+ removedScopes.insert (&scope);
1880+ }
1881+ std::set<const Function*> removedFunctions;
1882+ for (Scope& scope : scopeList) {
1883+ for (Function& function : scope.functionList ) {
1884+ if (function.tokenDef && removedTokens.count (function.tokenDef ) != 0 )
1885+ removedFunctions.insert (&function);
1886+ else if (function.token && removedTokens.count (function.token ) != 0 ) {
1887+ // only the function definition is removed - the declaration remains
1888+ function.token = nullptr ;
1889+ function.arg = function.argDef ;
1890+ function.functionScope = nullptr ;
1891+ function.hasBody (false );
1892+ }
1893+ }
1894+ }
1895+ std::set<const Variable*> removedVariables;
1896+ for (const Scope* scope : removedScopes) {
1897+ std::transform (scope->varlist .cbegin (), scope->varlist .cend (), std::inserter (removedVariables, removedVariables.end ()), [](const Variable& var) {
1898+ return &var;
1899+ });
1900+ }
1901+ for (const Function* function : removedFunctions) {
1902+ std::transform (function->argumentList .cbegin (), function->argumentList .cend (), std::inserter (removedVariables, removedVariables.end ()), [](const Variable& arg) {
1903+ return &arg;
1904+ });
1905+ }
1906+ std::set<const Type*> removedTypes;
1907+ for (const Type& type : typeList) {
1908+ if (type.classDef && removedTokens.count (type.classDef ) != 0 )
1909+ removedTypes.insert (&type);
1910+ }
1911+ std::set<const Enumerator*> removedEnumerators;
1912+ for (const Scope* scope : removedScopes) {
1913+ std::transform (scope->enumeratorList .cbegin (), scope->enumeratorList .cend (), std::inserter (removedEnumerators, removedEnumerators.end ()), [](const Enumerator& enumerator) {
1914+ return &enumerator;
1915+ });
1916+ }
1917+
1918+ // clear the references from the surviving tokens
1919+ for (Token* tok = mTokenizer .list .front (); tok; tok = tok->next ()) {
1920+ if (removedTokens.count (tok) != 0 )
1921+ continue ;
1922+ if (tok->function () && removedFunctions.count (tok->function ()) != 0 )
1923+ tok->function (nullptr );
1924+ if (tok->variable () && removedVariables.count (tok->variable ()) != 0 )
1925+ tok->variable (nullptr );
1926+ if (tok->type () && removedTypes.count (tok->type ()) != 0 )
1927+ tok->type (nullptr );
1928+ if (tok->enumerator () && removedEnumerators.count (tok->enumerator ()) != 0 )
1929+ tok->enumerator (nullptr );
1930+ if (tok->scope () && removedScopes.count (tok->scope ()) != 0 )
1931+ tok->scope (nullptr );
1932+ }
1933+
1934+ // remove from the indexes
1935+ for (std::size_t i = 0 ; i < mVariableList .size (); ++i) {
1936+ if (mVariableList [i] && removedVariables.count (mVariableList [i]) != 0 )
1937+ mVariableList [i] = nullptr ;
1938+ }
1939+ functionScopes.erase (std::remove_if (functionScopes.begin (), functionScopes.end (), [&](const Scope* scope) {
1940+ return removedScopes.count (scope) != 0 ;
1941+ }), functionScopes.end ());
1942+ classAndStructScopes.erase (std::remove_if (classAndStructScopes.begin (), classAndStructScopes.end (), [&](const Scope* scope) {
1943+ return removedScopes.count (scope) != 0 ;
1944+ }), classAndStructScopes.end ());
1945+
1946+ // remove from the owning scopes
1947+ for (Scope& scope : scopeList) {
1948+ if (removedScopes.count (&scope) != 0 )
1949+ continue ;
1950+ scope.nestedList .erase (std::remove_if (scope.nestedList .begin (), scope.nestedList .end (), [&](const Scope* nested) {
1951+ return removedScopes.count (nested) != 0 ;
1952+ }), scope.nestedList .end ());
1953+ for (auto it = scope.functionMap .begin (); it != scope.functionMap .end ();) {
1954+ if (removedFunctions.count (it->second ) != 0 )
1955+ it = scope.functionMap .erase (it);
1956+ else
1957+ ++it;
1958+ }
1959+ for (auto it = scope.functionList .begin (); it != scope.functionList .end ();) {
1960+ if (removedFunctions.count (&(*it)) != 0 )
1961+ it = scope.functionList .erase (it);
1962+ else
1963+ ++it;
1964+ }
1965+ for (auto it = scope.definedTypesMap .begin (); it != scope.definedTypesMap .end ();) {
1966+ if (removedTypes.count (it->second ) != 0 )
1967+ it = scope.definedTypesMap .erase (it);
1968+ else
1969+ ++it;
1970+ }
1971+ }
1972+ typeList.remove_if ([&](const Type& type) {
1973+ return removedTypes.count (&type) != 0 ;
1974+ });
1975+ scopeList.remove_if ([&](const Scope& scope) {
1976+ return removedScopes.count (&scope) != 0 ;
1977+ });
1978+ }
1979+
1980+ void SymbolDatabase::addSymbolsForNewTokenRanges (const std::vector<std::pair<Token*, Token*>>& newRanges)
1981+ {
1982+ if (newRanges.empty ())
1983+ return ;
1984+
1985+ const std::size_t oldScopeCount = scopeList.size ();
1986+
1987+ // all new tokens - the new functions are found through them afterwards
1988+ std::set<const Token*> newTokens;
1989+ for (const auto & range : newRanges) {
1990+ for (const Token* tok = range.first ; tok; tok = tok->next ()) {
1991+ newTokens.insert (tok);
1992+ if (tok == range.second )
1993+ break ;
1994+ }
1995+ }
1996+
1997+ for (const auto & range : newRanges) {
1998+ // the scope the new tokens are in is the scope of the nearest preceding token
1999+ const Token* anchor = range.first ->previous ();
2000+ while (anchor && !anchor->scope ())
2001+ anchor = anchor->previous ();
2002+ const Scope* enclosing = anchor ? anchor->scope () : &scopeList.front ();
2003+ if (!enclosing)
2004+ continue ;
2005+ if (anchor && anchor == enclosing->bodyEnd )
2006+ enclosing = enclosing->nestedIn ? enclosing->nestedIn : &scopeList.front ();
2007+ findAllScopes (range.first , range.second ->next (), const_cast <Scope*>(enclosing));
2008+ }
2009+
2010+ // the scopes and functions that were added
2011+ std::vector<Scope*> newScopes;
2012+ {
2013+ auto it = scopeList.begin ();
2014+ std::advance (it, oldScopeCount);
2015+ for (; it != scopeList.end (); ++it)
2016+ newScopes.push_back (&(*it));
2017+ }
2018+ std::vector<std::pair<Function*, Scope*>> newFunctions; // the function and the scope it is declared in
2019+ for (Scope& scope : scopeList) {
2020+ for (Function& function : scope.functionList ) {
2021+ if (function.tokenDef && newTokens.count (function.tokenDef ) != 0 )
2022+ newFunctions.emplace_back (&function, &scope);
2023+ }
2024+ }
2025+
2026+ // set the scope pointers - the old tokens keep their scopes
2027+ createSymbolDatabaseSetScopePointers ();
2028+
2029+ // the variables of the new scopes, the arguments and return types of the new functions
2030+ for (Scope* scope : newScopes)
2031+ scope->getVariableList ();
2032+ for (const auto & f : newFunctions) {
2033+ if (f.first ->argumentList .empty ())
2034+ f.first ->addArguments (f.second );
2035+ if (f.first ->retDef ) {
2036+ const Token *type = f.first ->retDef ;
2037+ while (Token::Match (type, " static|const|struct|union|enum" ))
2038+ type = type->next ();
2039+ if (type) {
2040+ f.first ->retType = findVariableTypeInBase (f.second , type);
2041+ if (!f.first ->retType )
2042+ f.first ->retType = findTypeInNested (type, f.first ->nestedIn );
2043+ }
2044+ }
2045+ }
2046+
2047+ // fast access vectors
2048+ for (const Scope* scope : newScopes) {
2049+ if (scope->type == ScopeType::eFunction)
2050+ functionScopes.push_back (scope);
2051+ if (scope->isClassOrStruct ())
2052+ classAndStructScopes.push_back (scope);
2053+ }
2054+
2055+ // variable symbol table: add the new variables (incremental version of
2056+ // createSymbolDatabaseVariableSymbolTable)
2057+ mVariableList .resize (mTokenizer .varIdCount () + 1 );
2058+ for (Scope* scope : newScopes) {
2059+ for (Variable& var : scope->varlist ) {
2060+ const int varId = var.declarationId ();
2061+ if (varId)
2062+ mVariableList [varId] = &var;
2063+ // fix up variables without type
2064+ if (!var.type () && !var.typeStartToken ()->isStandardType ()) {
2065+ const Type *type = findType (var.typeStartToken (), scope);
2066+ if (type)
2067+ var.type (type);
2068+ }
2069+ }
2070+ }
2071+ for (const auto & f : newFunctions) {
2072+ for (Variable& arg : f.first ->argumentList ) {
2073+ if (arg.nameToken () && arg.declarationId ()) {
2074+ mVariableList [arg.declarationId ()] = &arg;
2075+ // fix up parameters without type
2076+ if (!arg.type () && !arg.typeStartToken ()->isStandardType ()) {
2077+ const Type *type = findTypeInNested (arg.typeStartToken (), f.second );
2078+ if (type)
2079+ arg.type (type);
2080+ }
2081+ }
2082+ }
2083+ }
2084+ // fill in missing variables in the new code if possible
2085+ for (const Scope* func : newScopes) {
2086+ if (func->type != ScopeType::eFunction)
2087+ continue ;
2088+ for (const Token *tok = func->bodyStart ->next (); tok && tok != func->bodyEnd ; tok = tok->next ()) {
2089+ // check for member variable
2090+ if (!Token::Match (tok, " %var% .|[" ))
2091+ continue ;
2092+ const Token* tokDot = tok->next ();
2093+ while (Token::simpleMatch (tokDot, " [" ))
2094+ tokDot = tokDot->link ()->next ();
2095+ if (!Token::Match (tokDot, " . %var%" ))
2096+ continue ;
2097+ const Token *member = tokDot->next ();
2098+ if (mVariableList [member->varId ()] == nullptr ) {
2099+ const Variable *var1 = mVariableList [tok->varId ()];
2100+ if (var1 && var1->typeScope ()) {
2101+ const Variable* memberVar = var1->typeScope ()->getVariable (member->str ());
2102+ if (memberVar) {
2103+ // add this variable to the look up table
2104+ mVariableList [member->varId ()] = memberVar;
2105+ }
2106+ }
2107+ }
2108+ }
2109+ }
2110+
2111+ // function/type/enumerator pointers - these only set pointers that are not set, so
2112+ // the old tokens are not affected
2113+ createSymbolDatabaseSetFunctionPointers (true );
2114+ createSymbolDatabaseSetTypePointers ();
2115+ createSymbolDatabaseSetSmartPointerType ();
2116+ createSymbolDatabaseEnums ();
2117+ }
2118+
18382119// cppcheck-suppress functionConst - has side effects
18392120void SymbolDatabase::setArrayDimensionsUsingValueFlow ()
18402121{
0 commit comments