Added --remove-unused-included-templates option

This commit is contained in:
Daniel Marjamäki 2019-03-04 19:10:16 +01:00
parent 973ccda733
commit 3675318208
4 changed files with 63 additions and 39 deletions

View File

@ -158,6 +158,8 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
// --check-headers=no // --check-headers=no
else if (std::strcmp(argv[i], "--check-headers=no") == 0) else if (std::strcmp(argv[i], "--check-headers=no") == 0)
mSettings->checkHeaders = false; mSettings->checkHeaders = false;
else if (std::strcmp(argv[i], "--remove-unused-included-templates") == 0)
mSettings->removeUnusedIncludedTemplates = true;
// max ctu depth // max ctu depth
else if (std::strncmp(argv[i], "--max-ctu-depth=", 16) == 0) else if (std::strncmp(argv[i], "--max-ctu-depth=", 16) == 0)
@ -1075,6 +1077,9 @@ void CmdLineParser::printHelp()
" using e.g. ~ for home folder does not work. It is\n" " using e.g. ~ for home folder does not work. It is\n"
" currently only possible to apply the base paths to\n" " currently only possible to apply the base paths to\n"
" files that are on a lower level in the directory tree.\n" " files that are on a lower level in the directory tree.\n"
" --remove-unused-included-templates\n"
" Remove unused templates in included files. This option\n"
" can be used to speed up the analysis.\n"
" --report-progress Report progress messages while checking a file.\n" " --report-progress Report progress messages while checking a file.\n"
#ifdef HAVE_RULES #ifdef HAVE_RULES
" --rule=<rule> Match regular expression.\n" " --rule=<rule> Match regular expression.\n"

View File

@ -50,6 +50,7 @@ Settings::Settings()
enforcedLang(None), enforcedLang(None),
reportProgress(false), reportProgress(false),
checkHeaders(true), checkHeaders(true),
removeUnusedIncludedTemplates(false),
checkConfiguration(false), checkConfiguration(false),
checkLibrary(false) checkLibrary(false)
{ {

View File

@ -285,10 +285,14 @@ public:
/** Check for incomplete info in library files? */ /** Check for incomplete info in library files? */
bool checkLibrary; bool checkLibrary;
/** Check code in the headers, this is on by default but can /**
* Check code in the headers, this is on by default but can
* be turned off to save CPU */ * be turned off to save CPU */
bool checkHeaders; bool checkHeaders;
/** Remove unused included templates */
bool removeUnusedIncludedTemplates;
/** Struct contains standards settings */ /** Struct contains standards settings */
Standards standards; Standards standards;

View File

@ -4256,10 +4256,15 @@ void Tokenizer::simplifyHeaders()
// TODO : can we remove anything in headers here? Like unused declarations. // TODO : can we remove anything in headers here? Like unused declarations.
// Maybe if --dump is used we want to have _everything_. // Maybe if --dump is used we want to have _everything_.
if (mSettings->checkHeaders) if (mSettings->checkHeaders && !mSettings->removeUnusedIncludedTemplates)
// Default=full analysis. All information in the headers are kept. // Default=full analysis. All information in the headers are kept.
return; return;
const bool checkHeaders = mSettings->checkHeaders;
const bool removeUnusedIncludedFunctions = mSettings->checkHeaders;
const bool removeUnusedIncludedClasses = mSettings->checkHeaders;
const bool removeUnusedIncludedTemplates = mSettings->checkHeaders || mSettings->removeUnusedIncludedTemplates;
// We want to remove selected stuff from the headers but not *everything*. // We want to remove selected stuff from the headers but not *everything*.
// The intention here is to not damage the analysis of the source file. // The intention here is to not damage the analysis of the source file.
// You should get all warnings in the source file. // You should get all warnings in the source file.
@ -4269,7 +4274,10 @@ void Tokenizer::simplifyHeaders()
// functions and types to keep // functions and types to keep
std::set<std::string> keep; std::set<std::string> keep;
for (const Token *tok = list.front(); tok; tok = tok->next()) { for (const Token *tok = list.front(); tok; tok = tok->next()) {
if (tok->fileIndex() != 0 || !tok->isName()) if (!tok->isName())
continue;
if (checkHeaders && tok->fileIndex() != 0)
continue; continue;
if (Token::Match(tok, "%name% (") && !Token::simpleMatch(tok->linkAt(1), ") {")) { if (Token::Match(tok, "%name% (") && !Token::simpleMatch(tok->linkAt(1), ") {")) {
@ -4290,7 +4298,7 @@ void Tokenizer::simplifyHeaders()
continue; continue;
// Remove executable code // Remove executable code
if (tok->str() == "{") { if (mSettings->checkHeaders && tok->str() == "{") {
// TODO: We probably need to keep the executable code if this function is called from the source file. // TODO: We probably need to keep the executable code if this function is called from the source file.
const Token *prev = tok->previous(); const Token *prev = tok->previous();
while (prev && prev->isName()) while (prev && prev->isName())
@ -4305,48 +4313,54 @@ void Tokenizer::simplifyHeaders()
if (Token::Match(tok, "[;{}]")) { if (Token::Match(tok, "[;{}]")) {
// Remove unused function declarations // Remove unused function declarations
while (1) { if (removeUnusedIncludedFunctions) {
Token *start = tok->next(); while (1) {
while (start && functionStart.find(start->str()) != functionStart.end()) Token *start = tok->next();
start = start->next(); while (start && functionStart.find(start->str()) != functionStart.end())
if (Token::Match(start, "%name% (") && Token::Match(start->linkAt(1), ") const| ;") && keep.find(start->str()) == keep.end()) start = start->next();
Token::eraseTokens(tok, start->linkAt(1)->tokAt(2)); if (Token::Match(start, "%name% (") && Token::Match(start->linkAt(1), ") const| ;") && keep.find(start->str()) == keep.end())
else Token::eraseTokens(tok, start->linkAt(1)->tokAt(2));
break; else
break;
}
} }
if (Token::Match(tok, "[;{}] class|struct %name% [:{]") && keep.find(tok->strAt(2)) == keep.end()) { if (removeUnusedIncludedClasses) {
// Remove this class/struct if (Token::Match(tok, "[;{}] class|struct %name% [:{]") && keep.find(tok->strAt(2)) == keep.end()) {
const Token *endToken = tok->tokAt(3); // Remove this class/struct
if (endToken->str() == ":") { const Token *endToken = tok->tokAt(3);
endToken = endToken->next();
while (Token::Match(endToken, "%name%|,"))
endToken = endToken->next();
}
if (endToken && endToken->str() == "{" && Token::simpleMatch(endToken->link(), "} ;"))
Token::eraseTokens(tok, endToken->link()->next());
}
if (Token::Match(tok->next(), "template < %name%")) {
const Token *tok2 = tok->tokAt(3);
while (Token::Match(tok2, "%name% %name% [,=>]")) {
tok2 = tok2->tokAt(2);
if (Token::Match(tok2, "= %name% [,>]"))
tok2 = tok2->tokAt(2);
if (tok2->str() == ",")
tok2 = tok2->next();
}
if (Token::Match(tok2, "> class|struct %name% [;:{]") && keep.find(tok2->strAt(2)) == keep.end()) {
const Token *endToken = tok2->tokAt(3);
if (endToken->str() == ":") { if (endToken->str() == ":") {
endToken = endToken->next(); endToken = endToken->next();
while (Token::Match(endToken, "%name%|,")) while (Token::Match(endToken, "%name%|,"))
endToken = endToken->next(); endToken = endToken->next();
} }
if (endToken && endToken->str() == "{") if (endToken && endToken->str() == "{" && Token::simpleMatch(endToken->link(), "} ;"))
endToken = endToken->link()->next(); Token::eraseTokens(tok, endToken->link()->next());
if (endToken && endToken->str() == ";") }
Token::eraseTokens(tok, endToken); }
if (removeUnusedIncludedTemplates) {
if (Token::Match(tok->next(), "template < %name%")) {
const Token *tok2 = tok->tokAt(3);
while (Token::Match(tok2, "%name% %name% [,=>]")) {
tok2 = tok2->tokAt(2);
if (Token::Match(tok2, "= %name% [,>]"))
tok2 = tok2->tokAt(2);
if (tok2->str() == ",")
tok2 = tok2->next();
}
if (Token::Match(tok2, "> class|struct %name% [;:{]") && keep.find(tok2->strAt(2)) == keep.end()) {
const Token *endToken = tok2->tokAt(3);
if (endToken->str() == ":") {
endToken = endToken->next();
while (Token::Match(endToken, "%name%|,"))
endToken = endToken->next();
}
if (endToken && endToken->str() == "{")
endToken = endToken->link()->next();
if (endToken && endToken->str() == ";")
Token::eraseTokens(tok, endToken);
}
} }
} }
} }