instantiate nested templates in the proper order (#2930)
This commit is contained in:
parent
894b79227d
commit
9c51d4c12d
|
@ -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,58 +632,12 @@ 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);
|
||||
Token *end = findTemplateDeclarationEnd(tok);
|
||||
if (end && end->next()) {
|
||||
eraseTokens(tok, end->next());
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue