Refactor Tokenizer::simplifyUsing to use continue to reduce indentation (#1967)

* Refactor Tokenizer::simplifyUsing to use continue to reduce indentation

added function findTemplateDeclarationEnd to skip template declarations
to reduce duplicate code

* fix travis build
This commit is contained in:
IOBYTE 2019-07-07 12:33:33 -04:00 committed by Daniel Marjamäki
parent db43dcd601
commit e551057f59
4 changed files with 341 additions and 303 deletions

View File

@ -545,6 +545,43 @@ unsigned int TemplateSimplifier::templateParameters(const Token *tok)
return 0; return 0;
} }
const Token *TemplateSimplifier::findTemplateDeclarationEnd(const Token *tok)
{
return const_cast<const Token *>(findTemplateDeclarationEnd(const_cast<Token *>(tok)));
}
Token *TemplateSimplifier::findTemplateDeclarationEnd(Token *tok)
{
if (Token::simpleMatch(tok, "template <")) {
tok = tok->next()->findClosingBracket();
if (tok)
tok = tok->next();
}
if (!tok)
return nullptr;
Token * tok2 = tok;
while (tok2 && !Token::Match(tok2, ";|{")) {
if (tok2->str() == "<")
tok2 = tok2->findClosingBracket();
else if (Token::Match(tok2, "(|[") && tok2->link())
tok2 = tok2->link();
if (tok2)
tok2 = tok2->next();
}
if (tok2 && tok2->str() == "{") {
tok = tok2->link();
if (tok && tok->strAt(1) == ";")
tok = tok->next();
} else if (tok2 && tok2->str() == ";")
tok = tok2;
else
tok = nullptr;
return tok;
}
void TemplateSimplifier::eraseTokens(Token *begin, const Token *end) void TemplateSimplifier::eraseTokens(Token *begin, const Token *end)
{ {
if (!begin || begin == end) if (!begin || begin == end)
@ -829,18 +866,9 @@ void TemplateSimplifier::getTemplateInstantiations()
// #7914 // #7914
// Ignore template instantiations within template definitions: they will only be // Ignore template instantiations within template definitions: they will only be
// handled if the definition is actually instantiated // handled if the definition is actually instantiated
Token * tok2 = tok->next();
while (tok2 && !Token::Match(tok2, ";|{")) { Token * tok2 = findTemplateDeclarationEnd(tok->next());
if (tok2->str() == "<")
tok2 = tok2->findClosingBracket();
else if (Token::Match(tok2, "(|[") && tok2->link())
tok2 = tok2->link();
if (tok2) if (tok2)
tok2 = tok2->next();
}
if (tok2 && tok2->str() == "{")
tok = tok2->link();
else if (tok2 && tok2->str() == ";")
tok = tok2; tok = tok2;
} }
} else if (Token::Match(tok, "template using %name% <")) { } else if (Token::Match(tok, "template using %name% <")) {

View File

@ -222,6 +222,14 @@ public:
} }
}; };
/**
* Find last token of a template declaration.
* @param tok start token of declaration "template" or token after "template < ... >"
* @return last token of declaration or nullptr if syntax error
*/
static Token *findTemplateDeclarationEnd(Token *tok);
static const Token *findTemplateDeclarationEnd(const Token *tok);
/** /**
* Match template declaration/instantiation * Match template declaration/instantiation
* @param instance template instantiation * @param instance template instantiation

View File

@ -1878,8 +1878,6 @@ bool Tokenizer::simplifyUsing()
{ {
bool substitute = false; bool substitute = false;
std::list<ScopeInfo3> scopeList; std::list<ScopeInfo3> scopeList;
bool inTemplateDefinition = false;
const Token *endOfTemplateDefinition = nullptr;
struct Using { struct Using {
Using(Token *start, Token *end) : startTok(start), endTok(end) { } Using(Token *start, Token *end) : startTok(start), endTok(end) { }
Token *startTok; Token *startTok;
@ -1901,33 +1899,21 @@ bool Tokenizer::simplifyUsing()
setScopeInfo(tok, &scopeList); setScopeInfo(tok, &scopeList);
} }
if (inTemplateDefinition) { // skip template declarations
if (!endOfTemplateDefinition) { if (Token::Match(tok, "template < !!>")) {
if (tok->str() == "{") Token *endToken = TemplateSimplifier::findTemplateDeclarationEnd(tok);
endOfTemplateDefinition = tok->link(); if (endToken)
else if (tok->str() == ";") tok = endToken;
endOfTemplateDefinition = tok;
}
if (tok == endOfTemplateDefinition) {
inTemplateDefinition = false;
endOfTemplateDefinition = nullptr;
continue; continue;
} }
}
if (tok->str()=="template") {
if (Token::Match(tok->next(), "< !!>"))
inTemplateDefinition = true;
else
inTemplateDefinition = false;
}
if (!inTemplateDefinition) {
// look for non-template type aliases // look for non-template type aliases
if (tok->strAt(-1) != ">" && if (!(tok->strAt(-1) != ">" &&
(Token::Match(tok, "using %name% = ::| %name%") || (Token::Match(tok, "using %name% = ::| %name%") ||
(Token::Match(tok, "using %name% [ [") && (Token::Match(tok, "using %name% [ [") &&
Token::Match(tok->linkAt(2), "] ] = ::| %name%")))) { Token::Match(tok->linkAt(2), "] ] = ::| %name%")))))
continue;
std::list<ScopeInfo3> scopeList1; std::list<ScopeInfo3> scopeList1;
scopeList1.emplace_back("", nullptr); scopeList1.emplace_back("", nullptr);
std::string name = tok->strAt(1); std::string name = tok->strAt(1);
@ -2013,22 +1999,9 @@ bool Tokenizer::simplifyUsing()
// skip template definitions // skip template definitions
if (Token::Match(tok1, "template < !!>")) { if (Token::Match(tok1, "template < !!>")) {
tok1 = tok1->next()->findClosingBracket(); Token *endToken = TemplateSimplifier::findTemplateDeclarationEnd(tok1);
if (tok1) { if (endToken)
Token * tok2 = tok1->next(); tok1 = endToken;
while (tok2 && !Token::Match(tok2, ";|{")) {
if (tok2->str() == "<")
tok2 = tok2->findClosingBracket();
else if (Token::Match(tok2, "(|[") && tok2->link())
tok2 = tok2->link();
if (tok2)
tok2 = tok2->next();
}
if (tok2 && tok2->str() == "{")
tok1 = tok2->link();
else if (tok2 && tok2->str() == ";")
tok1 = tok2;
}
continue; continue;
} }
@ -2195,8 +2168,6 @@ bool Tokenizer::simplifyUsing()
if (!skip) if (!skip)
usingList.emplace_back(usingStart, usingEnd); usingList.emplace_back(usingStart, usingEnd);
} }
}
}
// delete all used type alias definitions // delete all used type alias definitions
for (std::list<Using>::reverse_iterator it = usingList.rbegin(); it != usingList.rend(); ++it) { for (std::list<Using>::reverse_iterator it = usingList.rbegin(); it != usingList.rend(); ++it) {

View File

@ -190,6 +190,8 @@ private:
TEST_CASE(templateNamePosition); TEST_CASE(templateNamePosition);
TEST_CASE(findTemplateDeclarationEnd);
TEST_CASE(expandSpecialized1); TEST_CASE(expandSpecialized1);
TEST_CASE(expandSpecialized2); TEST_CASE(expandSpecialized2);
TEST_CASE(expandSpecialized3); // #8671 TEST_CASE(expandSpecialized3); // #8671
@ -3713,6 +3715,35 @@ private:
"template<> unsigned A<int, v<char> >::foo() { return 0; }", 2)); "template<> unsigned A<int, v<char> >::foo() { return 0; }", 2));
} }
// Helper function to unit test TemplateSimplifier::findTemplateDeclarationEnd
bool findTemplateDeclarationEndHelper(const char code[], const char pattern[], unsigned offset = 0) {
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.createTokens(istr, "test.cpp");
tokenizer.createLinks();
tokenizer.mTemplateSimplifier->fixAngleBrackets();
const Token *_tok = tokenizer.tokens();
for (unsigned i = 0 ; i < offset ; ++i)
_tok = _tok->next();
const Token *tok1 = tokenizer.mTemplateSimplifier->findTemplateDeclarationEnd(_tok);
return (tok1 == Token::findsimplematch(tokenizer.list.front(), pattern));
}
void findTemplateDeclarationEnd() {
ASSERT(findTemplateDeclarationEndHelper("template <typename T> class Fred { }; int x;", "; int x ;"));
ASSERT(findTemplateDeclarationEndHelper("template <typename T> void Fred() { } int x;", "} int x ;"));
ASSERT(findTemplateDeclarationEndHelper("template <typename T> int Fred = 0; int x;", "; int x ;"));
ASSERT(findTemplateDeclarationEndHelper("template <typename T> constexpr auto func = [](auto x){ return T(x);}; int x;", "; int x ;"));
ASSERT(findTemplateDeclarationEndHelper("template <class, class a> auto b() -> decltype(a{}.template b<void(int, int)>); int x;", "; int x ;"));
ASSERT(findTemplateDeclarationEndHelper("template <class, class a> auto b() -> decltype(a{}.template b<void(int, int)>){} int x;", "} int x ;"));
ASSERT(findTemplateDeclarationEndHelper("template <typename... f, c<h<e<typename f::d...>>::g>> void i(); int x;", "; int x ;"));
ASSERT(findTemplateDeclarationEndHelper("template <typename... f, c<h<e<typename f::d...>>::g>> void i(){} int x;", "} int x ;"));
}
void expandSpecialized1() { void expandSpecialized1() {
ASSERT_EQUALS("class A<int> { } ;", tok("template<> class A<int> {};")); ASSERT_EQUALS("class A<int> { } ;", tok("template<> class A<int> {};"));
ASSERT_EQUALS("class A<int> : public B { } ;", tok("template<> class A<int> : public B {};")); ASSERT_EQUALS("class A<int> : public B { } ;", tok("template<> class A<int> : public B {};"));