From d204c5f89477a9a89ee75475cb90cd2650150052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 25 Jun 2022 17:09:51 +0200 Subject: [PATCH] Tokenizer: Cleanup stuff in simplifyTokenList2 --- lib/tokenize.cpp | 293 ----------------------------------------------- lib/tokenize.h | 22 ---- 2 files changed, 315 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index fcfdd740e..3cdb03998 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5187,33 +5187,6 @@ bool Tokenizer::simplifyTokenList2() removeRedundantSemicolons(); - simplifyFlowControl(); - - simplifyRedundantConsecutiveBraces(); - - simplifyEmptyNamespaces(); - - validate(); - - Token::assignProgressValues(list.front()); - - list.front()->assignIndexes(); - - list.createAst(); - // needed for #7208 (garbage code) and #7724 (ast max depth limit) - list.validateAst(); - - // Create symbol database and then remove const keywords - createSymbolDatabase(); - mSymbolDatabase->setValueTypeInTokenList(true); - - ValueFlow::setValues(&list, mSymbolDatabase, mErrorLogger, mSettings); - - if (Settings::terminated()) - return false; - - printDebugOutput(2); - return true; } //--------------------------------------------------------------------------- @@ -5766,82 +5739,6 @@ void Tokenizer::simplifyEmptyNamespaces() } } -void Tokenizer::simplifyFlowControl() -{ - for (Token *begin = list.front(); begin; begin = begin->next()) { - - if (Token::Match(begin, "(|[") || - (begin->str() == "{" && begin->previous() && begin->strAt(-1) == "=")) - begin = begin->link(); - - //function scope - if (!Token::simpleMatch(begin, ") {") && !Token::Match(begin, ") %name% {")) - continue; - - Token* end = begin->linkAt(1+(begin->next()->str() == "{" ? 0 : 1)); - int indentLevel = 0; - bool stilldead = false; - - for (Token *tok = begin; tok && tok != end; tok = tok->next()) { - if (Token::Match(tok, "(|[")) { - tok = tok->link(); - continue; - } - - if (tok->str() == "{") { - if (tok->previous() && tok->previous()->str() == "=") { - tok = tok->link(); - continue; - } - ++indentLevel; - } else if (tok->str() == "}") { - if (indentLevel == 0) - break; - --indentLevel; - if (stilldead) { - eraseDeadCode(tok, nullptr); - if (indentLevel == 1 || tok->next()->str() != "}" || !Token::Match(tok->next()->link()->previous(), ";|{|}|do {")) - stilldead = false; - continue; - } - } - - if (indentLevel == 0) - continue; - - if (Token::Match(tok,"continue|break ;")) { - tok = tok->next(); - eraseDeadCode(tok, nullptr); - - } else if (Token::Match(tok,"return|goto") || - (Token::Match(tok->previous(), "[;{}] %name% (") && - mSettings->library.isnoreturn(tok)) || - (isCPP() && tok->str() == "throw")) { - if (tok->next()->str() == "}") - syntaxError(tok->next()); // invalid code like in #6731 - //TODO: ensure that we exclude user-defined 'exit|abort|throw', except for 'noreturn' - //catch the first ';' - for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) { - if (Token::Match(tok2, "(|[")) { - tok2 = tok2->link(); - } else if (tok2->str() == ";") { - tok = tok2; - eraseDeadCode(tok, nullptr); - break; - } else if (Token::Match(tok2, "[{}]")) - break; - } - //if everything is removed, then remove also the code after an inferior scope - //only if the actual scope is not special - if (indentLevel > 1 && tok->next()->str() == "}" && Token::Match(tok->next()->link()->previous(), ";|{|}|do {")) - stilldead = true; - } - } - begin = end; - } -} - - void Tokenizer::removeRedundantSemicolons() { for (Token *tok = list.front(); tok; tok = tok->next()) { @@ -7399,196 +7296,6 @@ bool Tokenizer::isScopeNoReturn(const Token *endScopeToken, bool *unknown) const //--------------------------------------------------------------------------- -void Tokenizer::eraseDeadCode(Token *begin, const Token *end) -{ - if (!begin) - return; - const bool isgoto = Token::Match(begin->tokAt(-2), "goto %name% ;"); - int indentlevel = 1; - int indentcase = 0; - int indentswitch = 0; - int indentlabel = 0; - int roundbraces = 0; - int indentcheck = 0; - std::vector switchindents; - bool checklabel = false; - Token *tok = begin; - Token *tokcheck = nullptr; - while (tok->next() && tok->next() != end) { - if (tok->next()->str() == "(") { - ++roundbraces; - tok->deleteNext(); - continue; - } else if (tok->next()->str() == ")") { - if (!roundbraces) - break; //too many ending round parentheses - --roundbraces; - tok->deleteNext(); - continue; - } - - if (roundbraces) { - tok->deleteNext(); - continue; - } - - if (Token::Match(tok, "[{};] switch (")) { - if (!checklabel) { - if (!indentlabel) { - //remove 'switch ( ... )' - Token::eraseTokens(tok, tok->linkAt(2)->next()); - } else { - tok = tok->linkAt(2); - } - if (tok->next()->str() == "{") { - ++indentswitch; - indentcase = indentlevel + 1; - switchindents.push_back(indentcase); - } - } else { - tok = tok->linkAt(2); - if (Token::simpleMatch(tok, ") {")) { - ++indentswitch; - indentcase = indentlevel + 1; - switchindents.push_back(indentcase); - } - } - } else if (tok->next()->str() == "{") { - ++indentlevel; - if (!checklabel) { - checklabel = true; - tokcheck = tok; - indentcheck = indentlevel; - indentlabel = 0; - } - tok = tok->next(); - } else if (tok->next()->str() == "}") { - --indentlevel; - if (!indentlevel) - break; - - if (!checklabel) { - tok->deleteNext(); - } else { - if (indentswitch && indentlevel == indentcase) - --indentlevel; - if (indentlevel < indentcheck) { - const Token *end2 = tok->next(); - tok = end2->link()->previous(); //return to initial '{' - if (indentswitch && Token::simpleMatch(tok, ") {") && Token::Match(tok->link()->tokAt(-2), "[{};] switch (")) - tok = tok->link()->tokAt(-2); //remove also 'switch ( ... )' - Token::eraseTokens(tok, end2->next()); - checklabel = false; - tokcheck = nullptr; - indentcheck = 0; - } else { - tok = tok->next(); - } - } - if (indentswitch && indentlevel <= indentcase) { - --indentswitch; - switchindents.pop_back(); - if (!indentswitch) - indentcase = 0; - else - indentcase = switchindents[indentswitch-1]; - } - } else if (Token::Match(tok, "[{};:] case")) { - const Token *tok2 = Token::findsimplematch(tok->next(), ": ;", end); - if (!tok2) { - tok->deleteNext(); - continue; - } - if (indentlevel == 1) - break; //it seems like the function was called inside a case-default block. - if (indentlevel == indentcase) - ++indentlevel; - tok2 = tok2->next(); - if (!checklabel || !indentswitch) { - Token::eraseTokens(tok, tok2->next()); - } else { - tok = const_cast(tok2); - } - } else if (Token::Match(tok, "[{};] default : ;")) { - if (indentlevel == 1) - break; //it seems like the function was called inside a case-default block. - if (indentlevel == indentcase) - ++indentlevel; - if (!checklabel || !indentswitch) { - tok->deleteNext(3); - } else { - tok = tok->tokAt(3); - } - } else if (Token::Match(tok, "[{};] %name% : ;") && tok->next()->str() != "default") { - if (checklabel) { - indentlabel = indentlevel; - tok = tokcheck->next(); - checklabel = false; - indentlevel = indentcheck; - } else { - if (indentswitch) { - //Before stopping the function, since the 'switch()' - //instruction is removed, there's no sense to keep the - //case instructions. Remove them, if there are any. - Token *tok2 = tok->tokAt(3); - int indentlevel2 = indentlevel; - while (tok2->next() && tok2->next() != end) { - if (Token::Match(tok2->next(), "{|[|(")) { - tok2 = tok2->next()->link(); - } else if (Token::Match(tok2, "[{};:] case")) { - const Token *tok3 = Token::findsimplematch(tok2->next(), ": ;", end); - if (!tok3) { - tok2 = tok2->next(); - continue; - } - Token::eraseTokens(tok2, tok3->next()); - } else if (Token::Match(tok2, "[{};] default : ;")) { - tok2->deleteNext(3); - } else if (tok2->next()->str() == "}") { - --indentlevel2; - if (indentlevel2 <= indentcase) - break; - tok2 = tok2->next(); - } else { - tok2 = tok2->next(); - } - } - } - break; //stop removing tokens, we arrived to the label. - } - } else if (isgoto && Token::Match(tok, "[{};] do|while|for|BOOST_FOREACH")) { - //it's possible that code inside loop is not dead, - //because of the possible presence of the label pointed by 'goto' - const Token *start = tok->tokAt(2); - if (start && start->str() == "(") - start = start->link()->next(); - if (start && start->str() == "{") { - std::string labelpattern = "[{};] " + begin->previous()->str() + " : ;"; - bool simplify = true; - for (Token *tok2 = start->next(); tok2 != start->link(); tok2 = tok2->next()) { - if (Token::Match(tok2, labelpattern.c_str())) { - simplify = false; - break; - } - } - //bailout for now - if (!simplify) - break; - } - tok->deleteNext(); - } else { - // no need to keep the other strings, remove them. - if (tok->strAt(1) == "while") { - if (tok->str() == "}" && tok->link()->strAt(-1) == "do") - tok->link()->previous()->deleteThis(); - } - tok->deleteNext(); - } - } -} - -//--------------------------------------------------------------------------- - void Tokenizer::syntaxError(const Token *tok, const std::string &code) const { printDebugOutput(0); diff --git a/lib/tokenize.h b/lib/tokenize.h index c5c1c3ce6..a919170b2 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -159,23 +159,6 @@ public: void splitTemplateRightAngleBrackets(bool check); - /** - * Deletes dead code between 'begin' and 'end'. - * In general not everything can be erased, such as: - * - code after labels; - * - code outside the scope where the function is called; - * - code after a change of scope caused by 'switch(...);' - * instructions, like 'case %any%;' or 'default;' - * Also, if the dead code contains a 'switch' block - * and inside it there's a label, the function removes all - * the 'switch(..)' tokens and every occurrence of 'case %any%; | default;' - * expression, such as the 'switch' block is reduced to a simple block. - * - * @param begin Tokens after this have a possibility to be erased. - * @param end Tokens before this have a possibility to be erased. - */ - static void eraseDeadCode(Token *begin, const Token *end); - /** * Calculates sizeof value for given type. * @param type Token which will contain e.g. "int", "*", or string. @@ -332,11 +315,6 @@ public: /** Simplify useless C++ empty namespaces, like: 'namespace %name% { }'*/ void simplifyEmptyNamespaces(); - /** Simplify redundant code placed after control flow statements : - * 'return', 'throw', 'goto', 'break' and 'continue' - */ - void simplifyFlowControl(); - /** Simplify "if else" */ void elseif();