Add --remove-unused-templates flag to remove all unused templates

This commit is contained in:
Daniel Marjamäki 2019-03-05 14:57:37 +01:00
parent 0ae24b950f
commit fda0f52424
4 changed files with 18 additions and 13 deletions

View File

@ -155,9 +155,13 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
else if (std::strcmp(argv[i], "--dump") == 0) else if (std::strcmp(argv[i], "--dump") == 0)
mSettings->dump = true; mSettings->dump = true;
// TODO: These options are about removing code. Instead of having lots of different options
// can we create one option that is customizable somehow.
// --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-templates") == 0)
mSettings->removeUnusedTemplates = true;
else if (std::strcmp(argv[i], "--remove-unused-included-templates") == 0) else if (std::strcmp(argv[i], "--remove-unused-included-templates") == 0)
mSettings->removeUnusedIncludedTemplates = true; mSettings->removeUnusedIncludedTemplates = true;
@ -1077,12 +1081,10 @@ 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-templates\n"
" Remove unused templates.\n"
" --remove-unused-included-templates\n" " --remove-unused-included-templates\n"
" Remove unused templates in included files. This option\n" " Remove unused templates in included files.\n"
" can be used to speed up the analysis. The analysis of a\n"
" template can be more accurate when it is instantiated and\n"
" therefore it can be a good idea to only analyse the\n"
" instantiated templates.\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

@ -51,6 +51,7 @@ Settings::Settings()
reportProgress(false), reportProgress(false),
checkHeaders(true), checkHeaders(true),
removeUnusedIncludedTemplates(false), removeUnusedIncludedTemplates(false),
removeUnusedTemplates(false),
checkConfiguration(false), checkConfiguration(false),
checkLibrary(false) checkLibrary(false)
{ {

View File

@ -290,6 +290,9 @@ public:
* be turned off to save CPU */ * be turned off to save CPU */
bool checkHeaders; bool checkHeaders;
/** Remove unused templates in all files */
bool removeUnusedTemplates;
/** Remove unused included templates */ /** Remove unused included templates */
bool removeUnusedIncludedTemplates; bool removeUnusedIncludedTemplates;

View File

@ -4256,13 +4256,14 @@ 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 && !mSettings->removeUnusedIncludedTemplates) if (mSettings->checkHeaders && !mSettings->removeUnusedTemplates && !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 checkHeaders = mSettings->checkHeaders;
const bool removeUnusedIncludedFunctions = mSettings->checkHeaders; const bool removeUnusedIncludedFunctions = mSettings->checkHeaders;
const bool removeUnusedIncludedClasses = mSettings->checkHeaders; const bool removeUnusedIncludedClasses = mSettings->checkHeaders;
const bool removeUnusedTemplates = mSettings->removeUnusedTemplates;
const bool removeUnusedIncludedTemplates = mSettings->checkHeaders || mSettings->removeUnusedIncludedTemplates; 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*.
@ -4293,12 +4294,10 @@ void Tokenizer::simplifyHeaders()
const std::set<std::string> functionStart{"static", "const", "unsigned", "signed", "void", "bool", "char", "short", "int", "long", "float", "*"}; const std::set<std::string> functionStart{"static", "const", "unsigned", "signed", "void", "bool", "char", "short", "int", "long", "float", "*"};
for (Token *tok = list.front(); tok; tok = tok->next()) { for (Token *tok = list.front(); tok; tok = tok->next()) {
if (tok->fileIndex() == 0) const bool isIncluded = (tok->fileIndex() != 0);
// Keep all code in the source file
continue;
// Remove executable code // Remove executable code
if (mSettings->checkHeaders && tok->str() == "{") { if (isIncluded && 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())
@ -4313,7 +4312,7 @@ void Tokenizer::simplifyHeaders()
if (Token::Match(tok, "[;{}]")) { if (Token::Match(tok, "[;{}]")) {
// Remove unused function declarations // Remove unused function declarations
if (removeUnusedIncludedFunctions) { if (isIncluded && removeUnusedIncludedFunctions) {
while (1) { while (1) {
Token *start = tok->next(); Token *start = tok->next();
while (start && functionStart.find(start->str()) != functionStart.end()) while (start && functionStart.find(start->str()) != functionStart.end())
@ -4325,7 +4324,7 @@ void Tokenizer::simplifyHeaders()
} }
} }
if (removeUnusedIncludedClasses) { if (isIncluded && removeUnusedIncludedClasses) {
if (Token::Match(tok, "[;{}] class|struct %name% [:{]") && keep.find(tok->strAt(2)) == keep.end()) { if (Token::Match(tok, "[;{}] class|struct %name% [:{]") && keep.find(tok->strAt(2)) == keep.end()) {
// Remove this class/struct // Remove this class/struct
const Token *endToken = tok->tokAt(3); const Token *endToken = tok->tokAt(3);
@ -4339,7 +4338,7 @@ void Tokenizer::simplifyHeaders()
} }
} }
if (removeUnusedIncludedTemplates) { if (removeUnusedTemplates || (isIncluded && removeUnusedIncludedTemplates)) {
if (Token::Match(tok->next(), "template < %name%")) { if (Token::Match(tok->next(), "template < %name%")) {
const Token *tok2 = tok->tokAt(3); const Token *tok2 = tok->tokAt(3);
while (Token::Match(tok2, "%name% %name% [,=>]")) { while (Token::Match(tok2, "%name% %name% [,=>]")) {