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;
}
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)
{
if (!begin || begin == end)
@ -829,18 +866,9 @@ void TemplateSimplifier::getTemplateInstantiations()
// #7914
// Ignore template instantiations within template definitions: they will only be
// handled if the definition is actually instantiated
Token * tok2 = tok->next();
while (tok2 && !Token::Match(tok2, ";|{")) {
if (tok2->str() == "<")
tok2 = tok2->findClosingBracket();
else if (Token::Match(tok2, "(|[") && tok2->link())
tok2 = tok2->link();
Token * tok2 = findTemplateDeclarationEnd(tok->next());
if (tok2)
tok2 = tok2->next();
}
if (tok2 && tok2->str() == "{")
tok = tok2->link();
else if (tok2 && tok2->str() == ";")
tok = tok2;
}
} 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
* @param instance template instantiation

View File

@ -1878,8 +1878,6 @@ bool Tokenizer::simplifyUsing()
{
bool substitute = false;
std::list<ScopeInfo3> scopeList;
bool inTemplateDefinition = false;
const Token *endOfTemplateDefinition = nullptr;
struct Using {
Using(Token *start, Token *end) : startTok(start), endTok(end) { }
Token *startTok;
@ -1901,33 +1899,21 @@ bool Tokenizer::simplifyUsing()
setScopeInfo(tok, &scopeList);
}
if (inTemplateDefinition) {
if (!endOfTemplateDefinition) {
if (tok->str() == "{")
endOfTemplateDefinition = tok->link();
else if (tok->str() == ";")
endOfTemplateDefinition = tok;
}
if (tok == endOfTemplateDefinition) {
inTemplateDefinition = false;
endOfTemplateDefinition = nullptr;
// skip template declarations
if (Token::Match(tok, "template < !!>")) {
Token *endToken = TemplateSimplifier::findTemplateDeclarationEnd(tok);
if (endToken)
tok = endToken;
continue;
}
}
if (tok->str()=="template") {
if (Token::Match(tok->next(), "< !!>"))
inTemplateDefinition = true;
else
inTemplateDefinition = false;
}
if (!inTemplateDefinition) {
// 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% [ [") &&
Token::Match(tok->linkAt(2), "] ] = ::| %name%")))) {
Token::Match(tok->linkAt(2), "] ] = ::| %name%")))))
continue;
std::list<ScopeInfo3> scopeList1;
scopeList1.emplace_back("", nullptr);
std::string name = tok->strAt(1);
@ -2013,22 +1999,9 @@ bool Tokenizer::simplifyUsing()
// skip template definitions
if (Token::Match(tok1, "template < !!>")) {
tok1 = tok1->next()->findClosingBracket();
if (tok1) {
Token * tok2 = tok1->next();
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;
}
Token *endToken = TemplateSimplifier::findTemplateDeclarationEnd(tok1);
if (endToken)
tok1 = endToken;
continue;
}
@ -2195,8 +2168,6 @@ bool Tokenizer::simplifyUsing()
if (!skip)
usingList.emplace_back(usingStart, usingEnd);
}
}
}
// delete all used type alias definitions
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(findTemplateDeclarationEnd);
TEST_CASE(expandSpecialized1);
TEST_CASE(expandSpecialized2);
TEST_CASE(expandSpecialized3); // #8671
@ -3713,6 +3715,35 @@ private:
"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() {
ASSERT_EQUALS("class A<int> { } ;", tok("template<> class A<int> {};"));
ASSERT_EQUALS("class A<int> : public B { } ;", tok("template<> class A<int> : public B {};"));