From 9c51d4c12dd5243157f7f9ad6db0f597e0104c28 Mon Sep 17 00:00:00 2001 From: IOBYTE Date: Fri, 4 Dec 2020 02:04:16 -0500 Subject: [PATCH] instantiate nested templates in the proper order (#2930) --- lib/templatesimplifier.cpp | 69 +++++++++-------------------------- test/testsimplifytemplate.cpp | 40 ++++++++++++++++++++ 2 files changed, 57 insertions(+), 52 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 36486e72f..456dbc73f 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -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; } diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 291a3744f..d771b4273 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -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 struct S> {..}; TEST_CASE(template_specialization_2); // #7868 - template specialization template struct S> {..}; 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\n" + "struct adapter : public T {\n" + " template\n" + " adapter(Args&&... args) : T{ std::forward(args)... } {}\n" + "};\n" + "void foo() {\n" + " auto notifyJob = std::make_shared> ();\n" + "}"; + const char exp[] = "???"; + const char act[] = "struct JobEntry { } ; " + "struct adapter ; " + "void foo ( ) { " + "auto notifyJob ; notifyJob = std :: make_shared < adapter > ( ) ; " + "} " + "struct adapter : public JobEntry { " + "template < class ... Args > " + "adapter ( Args && ... args ) : JobEntry { std :: forward < Args > ( args ) ... } { } " + "} ;"; + TODO_ASSERT_EQUALS(exp, act, tok(code)); + } + + void template162() { + const char code[] = "template \n" + "CountryCode::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 struct S> {..}; const char code[] = "template struct C {};\n" "template struct S {a};\n"