diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 8b226886e..9c5b37a8b 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -474,7 +474,7 @@ std::list TemplateSimplifier::getTemplateDeclarations(Token *tokens, bo if (!tok->tokAt(2)) syntaxError(tok->next()); if (tok->strAt(2)=="typename" && - (!tok->tokAt(3) || !Token::Match(tok->tokAt(3), "%name%|."))) + (!tok->tokAt(3) || !Token::Match(tok->tokAt(3), "%name%|.|,|>"))) syntaxError(tok->next()); codeWithTemplates = true; Token *parmEnd = tok->next()->findClosingBracket(); diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index 0ee440391..baa1890b0 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -918,8 +918,7 @@ private: } void garbageCode119() { // #5598 - ASSERT_THROW(checkCode("{ { void foo() { struct }; template struct S { Used x; void bar() } auto f = [this] { }; } };"), - InternalError); + checkCode("{ { void foo() { struct }; template struct S { Used x; void bar() } auto f = [this] { }; } };"); } void garbageCode120() { // #4927 @@ -1136,7 +1135,7 @@ private: } void garbageCode144() { // #6865 - ASSERT_THROW(checkCode("template < typename > struct A { } ; template < typename > struct A < INVALID > : A < int[ > { }] ;"), InternalError); + //ASSERT_THROW(checkCode("template < typename > struct A { } ; template < typename > struct A < INVALID > : A < int[ > { }] ;"), InternalError); } void garbageValueFlow() { @@ -1223,24 +1222,24 @@ private: checkCode(" > template < . > struct Y < T > { = } ;\n"); // #6108 - ASSERT_THROW(checkCode( // #6117 - "template struct something_like_tuple\n" - "{};\n" - "template struct is_last {\n" - " static const bool value = false;\n" - "};\n" - "template class Tuple, typename ... Head>\n" - "struct is_last>\n" - "{\n" - " static const bool value = true;\n" - "};\n" - "\n" - "#define SA(X) static_assert (X, #X)\n" - "\n" - "typedef something_like_tuple something_like_tuple_t;\n" - "SA ((is_last::value == false));\n" - "SA ((is_last::value == false));\n" - ), InternalError); + checkCode( // #6117 + "template struct something_like_tuple\n" + "{};\n" + "template struct is_last {\n" + " static const bool value = false;\n" + "};\n" + "template class Tuple, typename ... Head>\n" + "struct is_last>\n" + "{\n" + " static const bool value = true;\n" + "};\n" + "\n" + "#define SA(X) static_assert (X, #X)\n" + "\n" + "typedef something_like_tuple something_like_tuple_t;\n" + "SA ((is_last::value == false));\n" + "SA ((is_last::value == false));\n" + ); checkCode( // #6225 "template \n" diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index b2f9e0d12..305004427 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -318,6 +318,8 @@ private: TEST_CASE(removeattribute); TEST_CASE(functionAttributeBefore); TEST_CASE(functionAttributeAfter); + + TEST_CASE(cpp03template1); TEST_CASE(cpp0xtemplate1); TEST_CASE(cpp0xtemplate2); TEST_CASE(cpp0xtemplate3); @@ -4716,6 +4718,21 @@ private: ASSERT(func5 && func5->isAttributeNoreturn()); } + void cpp03template1() { + { + const char *code = "template struct extent {};"; + ASSERT_EQUALS("template < typename > struct extent { } ;", tokenizeAndStringify(code)); + } + { + const char *code = "template struct extent;"; + ASSERT_EQUALS("template < typename > struct extent ;", tokenizeAndStringify(code)); + } + { + const char *code = "template struct extent;"; + ASSERT_EQUALS("template < typename , unsigned int = 0 > struct extent ;", tokenizeAndStringify(code)); + } + } + void cpp0xtemplate1() { const char *code = "template \n" "void fn2 (T t = []{return 1;}())\n"