diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index e4ca1c698..887863bd1 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -932,12 +932,16 @@ void TemplateSimplifier::simplifyTemplateAliases() startToken = startToken->tokAt(-5); while (Token::Match(startToken, "%name%|<|>|>>|,")) startToken = startToken->previous(); - if (!Token::Match(startToken, "[;{}] template <")) + // handle case where 'template' is first token + if (!startToken) { + if (!Token::simpleMatch(mTokenList.front(), "template <")) + continue; + } else if (!Token::Match(startToken, "[;{}] template <")) continue; // alias parameters.. std::vector aliasParameters; - getTemplateParametersInDeclaration(startToken->tokAt(3), aliasParameters); + getTemplateParametersInDeclaration(startToken ? startToken->tokAt(3) : mTokenList.front()->tokAt(2), aliasParameters); std::map aliasParameterNames; for (unsigned int argnr = 0; argnr < aliasParameters.size(); ++argnr) aliasParameterNames[aliasParameters[argnr]->str()] = argnr; @@ -1016,7 +1020,7 @@ void TemplateSimplifier::simplifyTemplateAliases() } if (endToken) { // Remove all template instantiations in template alias - for (const Token *tok = startToken; tok != endToken; tok = tok->next()) { + for (const Token *tok = startToken ? startToken : mTokenList.front(); tok != endToken; tok = tok->next()) { if (!Token::Match(tok, "%name% <")) continue; std::list::iterator it = std::find_if(mTemplateInstantiations.begin(), @@ -1031,7 +1035,21 @@ void TemplateSimplifier::simplifyTemplateAliases() mTemplateInstantiations.erase(it,next); } - Token::eraseTokens(startToken, endToken); + // find declaration + const std::list::iterator it2 = std::find_if(mTemplateDeclarations.begin(), + mTemplateDeclarations.end(), + FindToken(startToken ? startToken : mTokenList.front())); + + if (startToken) + eraseTokens(startToken, endToken); + else { + eraseTokens(mTokenList.front(), endToken); + deleteToken(mTokenList.front()); + } + + // remove declaration + if (it2 != mTemplateDeclarations.end()) + mTemplateDeclarations.erase(it2); } } } @@ -1125,6 +1143,8 @@ int TemplateSimplifier::getTemplateNamePosition(const Token *tok) int namepos = 0; if (Token::Match(tok, "> class|struct|union %type% :|<|;|{")) namepos = 2; + else if (Token::Match(tok, "> using %name% =")) + namepos = 2; else if (getTemplateNamePositionTemplateVariable(tok, namepos)) ; else if (!getTemplateNamePositionTemplateFunction(tok, namepos)) diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 64619c25a..4492481d5 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -135,6 +135,7 @@ private: TEST_CASE(template95); // #7417 TEST_CASE(template96); // #7854 TEST_CASE(template97); + TEST_CASE(template98); // #8959 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) @@ -2052,6 +2053,25 @@ private: ASSERT_EQUALS(exp, tok(code)); } + void template98() { // #8959 + const char code[] = "template \n" + "using unique_ptr_with_deleter = std::unique_ptr>;\n" + "class A {};\n" + "static void func() {\n" + " unique_ptr_with_deleter tmp(new A(), [](A* a) {\n" + " delete a;\n" + " });\n" + "}"; + const char exp[] = "; " + "class A { } ; " + "static void func ( ) { " + "std :: unique_ptr < A , std :: function < void ( A * ) > > tmp ( new A ( ) , [ ] ( A * a ) { " + "delete a ; " + "} ) ; " + "}"; + 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" diff --git a/test/testvarid.cpp b/test/testvarid.cpp index cc4ff0744..889e56457 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -2144,10 +2144,9 @@ private: void varid_templateUsing() { // #5781 #7273 const char code[] = "template using X = Y;\n" "X x;"; - TODO_ASSERT_EQUALS("\nY x@1;\n", - "1: template < class T > using X = Y < T , 4 > ;\n" - "2: X < int > x@1 ;\n", - tokenize(code)); + ASSERT_EQUALS("1: ;\n" + "2: Y < int , 4 > x@1 ;\n", + tokenize(code)); } void varid_not_template_in_condition() {