diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 01a0e6228..cef8e3b2f 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -471,6 +471,11 @@ std::list TemplateSimplifier::getTemplateDeclarations(Token *tokens, bo if (Token::simpleMatch(tok, "template <")) { Token *parmEnd = tok->next()->findClosingBracket(); + if (!tok->tokAt(2)) + syntaxError(tok->next()); + if (tok->tokAt(2)->str()=="typename" && + (!tok->tokAt(3) || !Token::Match(tok->tokAt(3), "%name%|."))) + syntaxError(tok->next()); codeWithTemplates = true; int indentlevel = 0; diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index d5d4c313c..0ee440391 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -192,6 +192,7 @@ private: TEST_CASE(garbageCode141); // #7043 TEST_CASE(garbageCode142); // #7050 TEST_CASE(garbageCode143); // #6922 + TEST_CASE(garbageCode144); // #6865 TEST_CASE(garbageValueFlow); TEST_CASE(garbageSymbolDatabase); @@ -917,7 +918,8 @@ private: } void garbageCode119() { // #5598 - checkCode("{ { void foo() { struct }; template struct S { Used x; void bar() } auto f = [this] { }; } };"); + ASSERT_THROW(checkCode("{ { void foo() { struct }; template struct S { Used x; void bar() } auto f = [this] { }; } };"), + InternalError); } void garbageCode120() { // #4927 @@ -1133,6 +1135,10 @@ private: "}"), InternalError); } + void garbageCode144() { // #6865 + ASSERT_THROW(checkCode("template < typename > struct A { } ; template < typename > struct A < INVALID > : A < int[ > { }] ;"), InternalError); + } + void garbageValueFlow() { // #6089 const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n" @@ -1217,24 +1223,24 @@ private: checkCode(" > template < . > struct Y < T > { = } ;\n"); // #6108 - 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" - ); + 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( // #6225 "template \n" diff --git a/test/testvarid.cpp b/test/testvarid.cpp index 1df6496e6..0d57cf2bc 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -663,8 +663,7 @@ private: } void varid28() { // ticket #2630 (segmentation fault) - tokenize("template \n"); - ASSERT_EQUALS("", errout.str()); + ASSERT_THROW(tokenize("template \n"), InternalError); } void varid29() {