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;
|
return nullptr;
|
||||||
|
|
||||||
Token * tok2 = tok;
|
Token * tok2 = tok;
|
||||||
|
bool in_init = false;
|
||||||
while (tok2 && !Token::Match(tok2, ";|{")) {
|
while (tok2 && !Token::Match(tok2, ";|{")) {
|
||||||
if (tok2->str() == "<")
|
if (tok2->str() == "<")
|
||||||
tok2 = tok2->findClosingBracket();
|
tok2 = tok2->findClosingBracket();
|
||||||
else if (Token::Match(tok2, "(|[") && tok2->link())
|
else if (Token::Match(tok2, "(|[") && tok2->link())
|
||||||
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)
|
if (tok2)
|
||||||
tok2 = tok2->next();
|
tok2 = tok2->next();
|
||||||
}
|
}
|
||||||
|
@ -624,58 +632,12 @@ bool TemplateSimplifier::removeTemplate(Token *tok)
|
||||||
if (!Token::simpleMatch(tok, "template <"))
|
if (!Token::simpleMatch(tok, "template <"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int indentlevel = 0;
|
Token *end = findTemplateDeclarationEnd(tok);
|
||||||
unsigned int countgt = 0; // Counter for ">"
|
if (end && end->next()) {
|
||||||
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
|
eraseTokens(tok, end->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);
|
deleteToken(tok);
|
||||||
return true;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -731,6 +693,9 @@ bool TemplateSimplifier::getTemplateDeclarations()
|
||||||
// Implementation => add to mTemplateDeclarations
|
// Implementation => add to mTemplateDeclarations
|
||||||
mTemplateDeclarations.emplace_back(std::move(decl));
|
mTemplateDeclarations.emplace_back(std::move(decl));
|
||||||
}
|
}
|
||||||
|
Token *end = findTemplateDeclarationEnd(tok);
|
||||||
|
if (end)
|
||||||
|
tok = end;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2238,7 +2203,7 @@ void TemplateSimplifier::expandTemplate(
|
||||||
mTokenList.addtoken(tokSemicolon, tokSemicolon->linenr(), tokSemicolon->fileIndex());
|
mTokenList.addtoken(tokSemicolon, tokSemicolon->linenr(), tokSemicolon->fileIndex());
|
||||||
}
|
}
|
||||||
brackets.pop();
|
brackets.pop();
|
||||||
if (brackets.empty() && !Token::Match(tok3, "} >|,|%cop%")) {
|
if (brackets.empty() && !Token::Match(tok3, "} >|,|{|%cop%")) {
|
||||||
inTemplateDefinition = false;
|
inTemplateDefinition = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,6 +203,8 @@ private:
|
||||||
TEST_CASE(template158); // daca crash
|
TEST_CASE(template158); // daca crash
|
||||||
TEST_CASE(template159); // #9886
|
TEST_CASE(template159); // #9886
|
||||||
TEST_CASE(template160);
|
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_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_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)
|
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
|
||||||
|
@ -4068,6 +4070,44 @@ private:
|
||||||
ASSERT_EQUALS(exp, tok(code));
|
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>> {..};
|
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||||
const char code[] = "template <typename T> struct C {};\n"
|
const char code[] = "template <typename T> struct C {};\n"
|
||||||
"template <typename T> struct S {a};\n"
|
"template <typename T> struct S {a};\n"
|
||||||
|
|
Loading…
Reference in New Issue