@@ -163,10 +163,13 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
163163 // create global scope
164164 scopeList.emplace_back (*this , nullptr , nullptr );
165165
166- findAllScopes (mTokenizer .tokens (), nullptr , &scopeList.back ());
166+ findAllScopes (mTokenizer .tokens (), nullptr , &scopeList.back (), AccessControl::Public );
167167}
168168
169- void SymbolDatabase::findAllScopes (const Token* startToken, const Token* endToken, Scope* startScope)
169+ void SymbolDatabase::findAllScopes (const Token* startToken,
170+ const Token* endToken,
171+ Scope* startScope,
172+ AccessControl startAccess)
170173{
171174 // pointer to current scope
172175 Scope* scope = startScope;
@@ -195,7 +198,7 @@ void SymbolDatabase::findAllScopes(const Token* startToken, const Token* endToke
195198 // Store current access in each scope (depends on evaluation progress)
196199 std::map<const Scope*, AccessControl> access;
197200 if (startScope->isClassOrStructOrUnion ())
198- access[startScope] = startScope-> type == ScopeType::eClass ? AccessControl::Private : AccessControl::Public ;
201+ access[startScope] = startAccess ;
199202
200203 std::map<const Scope *, std::set<std::string>> forwardDecls;
201204
@@ -1902,20 +1905,30 @@ void SymbolDatabase::removeSymbolsForTokens(const std::unordered_set<const Token
19021905 }
19031906 }
19041907 std::unordered_set<const Function*> removedFunctions;
1908+ // the functions whose definition is removed while their declaration remains, with
1909+ // the scope they are declared in. Their argument variables were created from the
1910+ // definition - they are recreated from the declaration when the removal is done.
1911+ std::vector<std::pair<Function*, Scope*>> functionsWithoutDefinition;
19051912 for (Scope& scope : scopeList) {
19061913 for (Function& function : scope.functionList ) {
1907- if (function.tokenDef && removedTokens.count (function.tokenDef ) != 0 ) {
1914+ const bool declarationRemoved = function.tokenDef && removedTokens.count (function.tokenDef ) != 0 ;
1915+ const bool definitionRemoved = function.token && removedTokens.count (function.token ) != 0 ;
1916+ if (!declarationRemoved && !definitionRemoved)
1917+ continue ;
1918+ std::transform (function.argumentList .cbegin (),
1919+ function.argumentList .cend (),
1920+ std::inserter (removedVariables, removedVariables.end ()),
1921+ [](const Variable& arg) {
1922+ return &arg;
1923+ });
1924+ if (declarationRemoved)
19081925 removedFunctions.insert (&function);
1909- std::transform (function.argumentList .cbegin (),
1910- function.argumentList .cend (),
1911- std::inserter (removedVariables, removedVariables.end ()),
1912- [](const Variable& arg) {
1913- return &arg;
1914- });
1915- } else if (function.token && removedTokens.count (function.token ) != 0 ) {
1916- // only the function definition is removed - the declaration remains
1926+ else {
1927+ // only the function definition is removed - the declaration remains,
1928+ // like a declaration that never had a definition
1929+ functionsWithoutDefinition.emplace_back (&function, &scope);
19171930 function.token = nullptr ;
1918- function.arg = function.argDef ;
1931+ function.arg = scope. isClassOrStructOrUnion () ? function.argDef : nullptr ;
19191932 function.functionScope = nullptr ;
19201933 function.hasBody (false );
19211934 }
@@ -1999,6 +2012,51 @@ void SymbolDatabase::removeSymbolsForTokens(const std::unordered_set<const Token
19992012 scopeList.remove_if ([&](const Scope& scope) {
20002013 return removedScopes.count (&scope) != 0 ;
20012014 });
2015+
2016+ // recreate the arguments of the functions that lost their definition from their
2017+ // declaration - the old argument variables were removed from the indexes above
2018+ for (const auto & f : functionsWithoutDefinition) {
2019+ f.first ->argumentList .clear ();
2020+ f.first ->initArgCount = 0 ;
2021+ f.first ->addArguments (f.second );
2022+ addArgumentsToSymbolTable (*f.first , *f.second );
2023+ }
2024+ }
2025+
2026+ // The access control that is in force at tok in the body of the given class, struct or
2027+ // union scope: the last access specifier before tok at the level of the class body, or
2028+ // the default access of the class kind
2029+ static AccessControl accessControlAt (const Scope& classScope, const Token* tok)
2030+ {
2031+ AccessControl access = classScope.type == ScopeType::eClass ? AccessControl::Private : AccessControl::Public;
2032+ if (!classScope.bodyStart )
2033+ return access;
2034+ int depth = 0 ;
2035+ for (const Token* tok2 = classScope.bodyStart ->next (); tok2 && tok2 != tok && tok2 != classScope.bodyEnd ;
2036+ tok2 = tok2->next ()) {
2037+ if (tok2->str () == " {" )
2038+ ++depth;
2039+ else if (tok2->str () == " }" )
2040+ --depth;
2041+ if (depth != 0 )
2042+ continue ;
2043+ if (tok2->str () == " private:" )
2044+ access = AccessControl::Private;
2045+ else if (tok2->str () == " protected:" )
2046+ access = AccessControl::Protected;
2047+ else if (tok2->str () == " public:" || tok2->str () == " __published:" )
2048+ access = AccessControl::Public;
2049+ else if (Token::Match (tok2, " public|protected|private %name% :" )) {
2050+ if (tok2->str () == " private" )
2051+ access = AccessControl::Private;
2052+ else if (tok2->str () == " protected" )
2053+ access = AccessControl::Protected;
2054+ else
2055+ access = AccessControl::Public;
2056+ tok2 = tok2->tokAt (2 );
2057+ }
2058+ }
2059+ return access;
20022060}
20032061
20042062void SymbolDatabase::addSymbolsForNewTokenRanges (const std::vector<std::pair<Token*, Token*>>& newRanges)
@@ -2037,7 +2095,10 @@ void SymbolDatabase::addSymbolsForNewTokenRanges(const std::vector<std::pair<Tok
20372095 // latest block - so for namespaces any closing brace with the namespace scope closes it.
20382096 if (anchor && anchor->str () == " }" && (anchor == enclosing->bodyEnd || enclosing->type == ScopeType::eNamespace))
20392097 enclosing = enclosing->nestedIn ? enclosing->nestedIn : &scopeList.front ();
2040- findAllScopes (range.first , range.second ->next (), const_cast <Scope*>(enclosing));
2098+ // in a class body the access specifier that is in force at the new tokens applies to them
2099+ const AccessControl startAccess =
2100+ enclosing->isClassOrStructOrUnion () ? accessControlAt (*enclosing, range.first ) : AccessControl::Public;
2101+ findAllScopes (range.first , range.second ->next (), const_cast <Scope*>(enclosing), startAccess);
20412102 }
20422103
20432104 // the scopes and functions that were added
0 commit comments