Refactoring Tokenizer::startOfExecutableScope(). Improve and reuse Tokenizer::isFunctionHead().

This commit is contained in:
Daniel Marjamäki 2016-01-03 22:52:24 +01:00
parent d6fd4705cf
commit 036306d7c2
4 changed files with 36 additions and 52 deletions

View File

@ -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<const Token *>(tok2->next()->link())))) {
Tokenizer::startOfExecutableScope(tok2->linkAt(1)))) {
Token::eraseTokens(tok, tok2);
tok->deleteThis();
return true;

View File

@ -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<Token *>(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<Token *>(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<Token *>(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<Token *>(startOfExecutableScope(tok));
if (start) {
tok = start;
// replace references in this scope..

View File

@ -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<Token*>(startOfExecutableScope(const_cast<const Token *>(tok)));
}
Token *processFunc(Token *tok2, bool inOperator) const;
/** Set pod types */

View File

@ -559,7 +559,7 @@ private:
}
void garbageCode33() { // #6613
ASSERT_THROW(checkCode("main(()B{});"), InternalError);
checkCode("main(()B{});");
checkCode("f::y:y : <x::");