instantiate nested templates in the proper order (#2930)

This commit is contained in:
IOBYTE 2020-12-04 02:04:16 -05:00 committed by GitHub
parent 894b79227d
commit 9c51d4c12d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 52 deletions

View File

@ -581,11 +581,19 @@ Token *TemplateSimplifier::findTemplateDeclarationEnd(Token *tok)
return nullptr;
Token * tok2 = tok;
bool in_init = false;
while (tok2 && !Token::Match(tok2, ";|{")) {
if (tok2->str() == "<")
tok2 = tok2->findClosingBracket();
else if (Token::Match(tok2, "(|[") && tok2->link())
tok2 = tok2->link();
else if (tok2->str() == ":")
in_init = true;
else if (in_init && Token::Match(tok2, "%name% (|{")) {
tok2 = tok2->linkAt(1);
if (tok2->strAt(1) == "{")
in_init = false;
}
if (tok2)
tok2 = tok2->next();
}
@ -624,57 +632,11 @@ bool TemplateSimplifier::removeTemplate(Token *tok)
if (!Token::simpleMatch(tok, "template <"))
return false;
int indentlevel = 0;
unsigned int countgt = 0; // Counter for ">"
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
if (tok2->str() == "(") {
tok2 = tok2->link();
} else if (tok2->str() == ")") { // garbage code! (#3504)
eraseTokens(tok,tok2);
deleteToken(tok);
return false;
}
else if (tok2->str() == "{") {
tok2 = tok2->link();
if (indentlevel < 2) {
tok2 = tok2->next();
if (tok2 && tok2->str() == ";" && tok2->next())
tok2 = tok2->next();
eraseTokens(tok, tok2);
deleteToken(tok);
return true;
}
} else if (tok2->str() == "}") { // garbage code! (#3449)
eraseTokens(tok,tok2);
deleteToken(tok);
return false;
}
// Count ">"
if (tok2->str() == ">")
countgt++;
if (tok2->str() == ";") {
tok2 = tok2->next();
eraseTokens(tok, tok2);
deleteToken(tok);
return true;
}
if (tok2->str() == "<")
++indentlevel;
else if (indentlevel >= 2 && tok2->str() == ">")
--indentlevel;
else if (Token::Match(tok2, "> class|struct|union %name% [,)]")) {
tok2 = tok2->next();
eraseTokens(tok, tok2);
deleteToken(tok);
return true;
}
Token *end = findTemplateDeclarationEnd(tok);
if (end && end->next()) {
eraseTokens(tok, end->next());
deleteToken(tok);
return true;
}
return false;
@ -731,6 +693,9 @@ bool TemplateSimplifier::getTemplateDeclarations()
// Implementation => add to mTemplateDeclarations
mTemplateDeclarations.emplace_back(std::move(decl));
}
Token *end = findTemplateDeclarationEnd(tok);
if (end)
tok = end;
break;
}
}
@ -2238,7 +2203,7 @@ void TemplateSimplifier::expandTemplate(
mTokenList.addtoken(tokSemicolon, tokSemicolon->linenr(), tokSemicolon->fileIndex());
}
brackets.pop();
if (brackets.empty() && !Token::Match(tok3, "} >|,|%cop%")) {
if (brackets.empty() && !Token::Match(tok3, "} >|,|{|%cop%")) {
inTemplateDefinition = false;
break;
}

View File

@ -203,6 +203,8 @@ private:
TEST_CASE(template158); // daca crash
TEST_CASE(template159); // #9886
TEST_CASE(template160);
TEST_CASE(template161);
TEST_CASE(template162);
TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
@ -4068,6 +4070,44 @@ private:
ASSERT_EQUALS(exp, tok(code));
}
void template161() {
const char code[] = "struct JobEntry { };\n"
"template<class T>\n"
"struct adapter : public T {\n"
" template<class... Args>\n"
" adapter(Args&&... args) : T{ std::forward<Args>(args)... } {}\n"
"};\n"
"void foo() {\n"
" auto notifyJob = std::make_shared<adapter<JobEntry>> ();\n"
"}";
const char exp[] = "???";
const char act[] = "struct JobEntry { } ; "
"struct adapter<JobEntry> ; "
"void foo ( ) { "
"auto notifyJob ; notifyJob = std :: make_shared < adapter<JobEntry> > ( ) ; "
"} "
"struct adapter<JobEntry> : public JobEntry { "
"template < class ... Args > "
"adapter<JobEntry> ( Args && ... args ) : JobEntry { std :: forward < Args > ( args ) ... } { } "
"} ;";
TODO_ASSERT_EQUALS(exp, act, tok(code));
}
void template162() {
const char code[] = "template <std::size_t N>\n"
"CountryCode<N>::CountryCode(std::string cc) : m_String{std::move(cc)} {\n"
"}\n"
"template class CountryCode<2>;\n"
"template class CountryCode<3>;";
const char exp[] = "CountryCode<2> :: CountryCode<2> ( std :: string cc ) ; "
"CountryCode<3> :: CountryCode<3> ( std :: string cc ) ; "
"CountryCode<2> :: CountryCode<2> ( std :: string cc ) : m_String { std :: move ( cc ) } { "
"} "
"CountryCode<3> :: CountryCode<3> ( std :: string cc ) : m_String { std :: move ( cc ) } { "
"}";
ASSERT_EQUALS(exp, tok(code));
}
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
const char code[] = "template <typename T> struct C {};\n"
"template <typename T> struct S {a};\n"