diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index fb76b0f60..5213df7fd 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -369,7 +369,7 @@ bool TemplateSimplifier::removeTemplate(Token *tok) // don't remove constructor if (tok2->str() == "explicit" || (countgt == 1 && Token::Match(tok2->previous(), "> %type% (") && - Tokenizer::startOfExecutableScope(const_cast(tok2->next()->link())))) { + Tokenizer::startOfExecutableScope(tok2->linkAt(1)))) { Token::eraseTokens(tok, tok2); tok->deleteThis(); return true; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 09a0276d4..eb3bf241e 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -53,23 +53,31 @@ namespace { } const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &endsWith) const +{ + return Tokenizer::isFunctionHead(tok, endsWith, isCPP()); +} + +const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &endsWith, bool cpp) { if (!tok) return nullptr; if (tok->str() == "(") tok = tok->link(); - if (Token::Match(tok, ") const| [;{]")) { + if (Token::Match(tok, ") [;{]")) { tok = tok->next(); if (tok->isName()) tok = tok->next(); return (endsWith.find(tok->str()) != std::string::npos) ? tok : nullptr; } - if (isCPP() && tok->str() == ")") { + if (cpp && tok->str() == ")") { tok = tok->next(); - while (Token::Match(tok, "const|noexcept|override|volatile|&|&& !!(")) + while (Token::Match(tok, "const|noexcept|override|volatile|&|&& !!(") || + (Token::Match(tok, "%name% !!(") && tok->isUpperCaseName())) tok = tok->next(); if (Token::Match(tok, "throw|noexcept (")) tok = tok->linkAt(1)->next(); + if (Token::Match(tok, "%name% (") && tok->isUpperCaseName()) + tok = tok->linkAt(1)->next(); if (Token::Match(tok, "= 0|default|delete ;")) tok = tok->tokAt(2); return (tok && endsWith.find(tok->str()) != std::string::npos) ? tok : nullptr; @@ -2238,47 +2246,17 @@ static Token *skipTernaryOp(Token *tok) const Token * Tokenizer::startOfExecutableScope(const Token * tok) { - if (tok && tok->str() == ")") { - tok = tok->next(); - bool inInit = false; - while (tok && tok->str() != "{") { - if (!inInit) { - if (Token::Match(tok, "const|override|volatile")) { - tok = tok->next(); - } else if (tok->str() == "noexcept") { - tok = tok->next(); - if (tok && tok->str() == "(") { - tok = tok->link()->next(); - } - } else if (tok->str() == "throw" && tok->next() && tok->next()->str() == "(") { - tok = tok->next()->link()->next(); - } else if (tok->str() == ":") { - inInit = true; - tok = tok->next(); - } - // unknown macros ") MACRO {" and ") MACRO(...) {" - else if (tok->isUpperCaseName()) { - tok = tok->next(); - if (tok && tok->str() == "(") { - tok = tok->link()->next(); - } - } else - return nullptr; - } else { - if (tok->isName() && tok->next() && (tok->next()->str() == "(" || - (inInit && tok->next()->str() == "{"))) { - tok = tok->next()->link()->next(); - } else if (tok->str() == ",") { - tok = tok->next(); - } else - return nullptr; - } - } + if (tok->str() != ")") + return nullptr; - return tok; + tok = isFunctionHead(tok, ":{", true); + + if (Token::Match(tok, ": %name% [({]")) { + while (Token::Match(tok, "[:,] %name% [({]")) + tok = tok->linkAt(2)->next(); } - return nullptr; + return (tok && tok->str() == "{") ? tok : nullptr; } @@ -2290,7 +2268,7 @@ void Tokenizer::simplifyLabelsCaseDefault() unsigned int indentlevel = 0; for (Token *tok = list.front(); tok; tok = tok->next()) { // Simplify labels in the executable scope.. - Token *start = startOfExecutableScope(tok); + Token *start = const_cast(startOfExecutableScope(tok)); if (start) { tok = start; executablescope = true; @@ -4038,7 +4016,7 @@ void Tokenizer::removeRedundantAssignment() if (tok->str() == "{") tok = tok->link(); - Token * start = startOfExecutableScope(tok); + Token * start = const_cast(startOfExecutableScope(tok)); if (start) { tok = start->previous(); // parse in this function.. @@ -6211,7 +6189,7 @@ bool Tokenizer::simplifyKnownVariables() // auto variables.. for (Token *tok = list.front(); tok; tok = tok->next()) { // Search for a block of code - Token *start = startOfExecutableScope(tok); + Token *start = const_cast(startOfExecutableScope(tok)); if (!start) continue; @@ -7038,7 +7016,7 @@ void Tokenizer::simplifyReference() for (Token *tok = list.front(); tok; tok = tok->next()) { // starting executable scope.. - Token *start = startOfExecutableScope(tok); + Token *start = const_cast(startOfExecutableScope(tok)); if (start) { tok = start; // replace references in this scope.. diff --git a/lib/tokenize.h b/lib/tokenize.h index 05eb78494..d5746e632 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -534,6 +534,16 @@ public: const Token * isFunctionHead(const Token *tok, const std::string &endsWith) const; private: + + /** + * is token pointing at function head? + * @param tok A '(' or ')' token in a possible function head + * @param endsWith string after function head + * @param cpp c++ code + * @return token matching with endsWith if syntax seems to be a function head else nullptr + */ + static const Token * isFunctionHead(const Token *tok, const std::string &endsWith, bool cpp); + /** * simplify "while (0)" */ @@ -817,7 +827,7 @@ public: /** * Helper function to check for start of function execution scope. * Do not use this in checks. Use the symbol database. - * @param tok --> pointer to end parentheses of parameter list + * @param tok pointer to end parentheses of parameter list * @return pointer to start brace of function scope or nullptr if not start. */ static const Token * startOfExecutableScope(const Token * tok); @@ -829,10 +839,6 @@ private: /** Disable assignment operator, no implementation */ Tokenizer &operator=(const Tokenizer &); - static Token * startOfExecutableScope(Token * tok) { - return const_cast(startOfExecutableScope(const_cast(tok))); - } - Token *processFunc(Token *tok2, bool inOperator) const; /** Set pod types */ diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index 86282c1f7..ca13c365e 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -559,7 +559,7 @@ private: } void garbageCode33() { // #6613 - ASSERT_THROW(checkCode("main(()B{});"), InternalError); + checkCode("main(()B{});"); checkCode("f::y:y :