Skip to content

Commit 771eb64

Browse files
committed
Fixes from feedback
1 parent 8016585 commit 771eb64

4 files changed

Lines changed: 282 additions & 17 deletions

File tree

‎Makefile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ test/testsarifreport.o: test/testsarifreport.cpp externals/picojson/picojson.h l
882882
test/testsettings.o: test/testsettings.cpp lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h
883883
$(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsettings.cpp
884884

885-
test/testsimplifytemplate.o: test/testsimplifytemplate.cpp lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h
885+
test/testsimplifytemplate.o: test/testsimplifytemplate.cpp lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h
886886
$(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsimplifytemplate.cpp
887887

888888
test/testsimplifytokens.o: test/testsimplifytokens.cpp lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h

‎lib/symboldatabase.cpp‎

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

20042062
void 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

‎lib/symboldatabase.h‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,10 +1484,11 @@ class CPPCHECKLIB SymbolDatabase {
14841484
/**
14851485
* Find the scopes in the given token range (endToken is exclusive, nullptr means
14861486
* the end of the token list) and add the symbols to the database. startScope is
1487-
* the scope the range is in.
1487+
* the scope the range is in and startAccess the access control that is in force
1488+
* at startToken when startScope is a class, struct or union.
14881489
* @throws InternalError thrown on unhandled code
14891490
*/
1490-
void findAllScopes(const Token* startToken, const Token* endToken, Scope* startScope);
1491+
void findAllScopes(const Token* startToken, const Token* endToken, Scope* startScope, AccessControl startAccess);
14911492
void createSymbolDatabaseClassInfo();
14921493
void createSymbolDatabaseVariableInfo();
14931494
void createSymbolDatabaseCopyAndMoveConstructors();

0 commit comments

Comments
 (0)