diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index a84f6361f..02f554c60 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -269,7 +269,7 @@ unsigned int TemplateSimplifier::templateParameters(const Token *tok) return 0; // num/type .. - if (!tok->isNumber() && tok->tokType() != Token::eChar && !tok->isName()) + if (!tok->isNumber() && tok->tokType() != Token::eChar && !tok->isName() && !tok->isOp()) return 0; tok = tok->next(); if (!tok) @@ -509,6 +509,12 @@ std::list TemplateSimplifier::getTemplateInstantiations(Token *tokens) tok = tok->next()->findClosingBracket(); if (!tok) break; + // #7914 + // Ignore template instantiations within template definitions: they will only be + // handled if the definition is actually instantiated + const Token *tok2 = Token::findmatch(tok, "{|;"); + if (tok2 && tok2->str() == "{") + tok = tok2->link(); } else if (Token::Match(tok->previous(), "[({};=] %name% <") || Token::Match(tok->previous(), "%type% %name% <") || Token::Match(tok->tokAt(-2), "[,:] private|protected|public %name% <")) { diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index c9b0de102..4835c6533 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -915,8 +915,7 @@ private: } void garbageCode125() { - ASSERT_THROW(checkCode("{ T struct B : T valueA_AA ; } T : [ T > ( ) { B } template < T > struct A < > : ] { ( ) { return valueA_AC struct { : } } b A < int > AC ( ) a_aa.M ; ( ) ( ) }"), - InternalError); + checkCode("{ T struct B : T valueA_AA ; } T : [ T > ( ) { B } template < T > struct A < > : ] { ( ) { return valueA_AC struct { : } } b A < int > AC ( ) a_aa.M ; ( ) ( ) }"); ASSERT_THROW(checkCode("template < Types > struct S :{ ( S < ) S >} { ( ) { } } ( ) { return S < void > ( ) }"), InternalError); } diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 5d82ba498..e4980c40e 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -310,7 +310,7 @@ private: // The expected result.. const char expected[] = "void f ( ) { A < int > a ; } " "template < typename T > class B { void g ( ) { A < T > b ; b = A < T > :: h ( ) ; } } ; " - "class A < int > { } ; class A < T > { } ;"; + "class A < int > { } ;"; ASSERT_EQUALS(expected, tok(code)); } @@ -473,7 +473,6 @@ private: const char expected[] = "int main ( ) { b < 2 > ( ) ; return 0 ; } " "void b < 2 > ( ) { a < 2 > ( ) ; } " - "void a < i > ( ) { } " "void a < 2 > ( ) { }"; ASSERT_EQUALS(expected, tok(code)); @@ -722,7 +721,6 @@ private: ASSERT_EQUALS("C < int > c ; " "struct C < int > { A < B < X < int > > > ab ; } ; " "struct B < X < int > > { } ; " // <- redundant.. but nevermind - "struct A < B < X < T > > > { } ; " // <- redundant.. but nevermind "struct A < B < X < int > > > { } ;", tok(code)); } @@ -912,11 +910,12 @@ private: "template < class T > void Fred < T > :: g ( ) { } " "template void Fred < float > :: f ( ) ; " "template void Fred < int > :: g ( ) ; " - "class Fred < T > { void f ( ) ; void g ( ) ; } ; " - "Fred < T > :: f ( ) { } " - "Fred < T > :: g ( ) { } " "class Fred < float > { void f ( ) ; void g ( ) ; } ; " - "class Fred < int > { void f ( ) ; void g ( ) ; } ;"; + "Fred < float > :: f ( ) { } " + "Fred < float > :: g ( ) { } " + "class Fred < int > { void f ( ) ; void g ( ) ; } ; " + "Fred < int > :: f ( ) { } " + "Fred < int > :: g ( ) { }"; ASSERT_EQUALS(expected, tok(code)); } @@ -927,13 +926,10 @@ private: "template<> void Fred::f() { }\n" "template<> void Fred::g() { }\n"; - const char expected[] = "template < class T > void Fred < T > :: f ( ) { } " + const char expected[] = "template < class T > class Fred { void f ( ) ; } ; " + "template < class T > void Fred < T > :: f ( ) { } " "template < > void Fred < float > :: f ( ) { } " - "template < > void Fred < int > :: g ( ) { } " - "class Fred < T > { void f ( ) ; } ; " - "Fred < T > :: f ( ) { } " - "class Fred < float > { void f ( ) ; } ; " - "class Fred < int > { void f ( ) ; } ;"; + "template < > void Fred < int > :: g ( ) { }"; ASSERT_EQUALS(expected, tok(code)); } @@ -982,13 +978,10 @@ private: void template55() { // #6604 // Avoid constconstconst in macro instantiations ASSERT_EQUALS( - "class AtSmartPtr < T > : public ConstCastHelper < AtSmartPtr < const T > , T > { " + "template < class T > class AtSmartPtr : public ConstCastHelper < AtSmartPtr < const T > , T > { " "friend struct ConstCastHelper < AtSmartPtr < const T > , T > ; " - "AtSmartPtr < T > ( const AtSmartPtr < T > & r ) ; " - "} ; " - "class AtSmartPtr < const T > : public ConstCastHelper < AtSmartPtr < const const T > , const T > { " - "friend struct ConstCastHelper < AtSmartPtr < const const T > , const T > ; " - "AtSmartPtr < const T > ( const AtSmartPtr < T > & r ) ; } ;", + "AtSmartPtr ( const AtSmartPtr < T > & r ) ; " + "} ;", tok("template class AtSmartPtr : public ConstCastHelper, T>\n" "{\n" " friend struct ConstCastHelper, T>;\n" @@ -1062,17 +1055,12 @@ private: " enum {value = !type_equal::type>::value };\n" "};"; const char exp1[] = "template < class T > struct Unconst { } ; " + "template < class T > struct Unconst < const T > { } ; " + "template < class T > struct Unconst < const T & > { } ; " + "template < class T > struct Unconst < T * const > { } ; " + "template < class T1 , class T2 > struct type_equal { enum Anonymous0 { value = 0 } ; } ; " "template < class T > struct type_equal < T , T > { enum Anonymous1 { value = 1 } ; } ; " - "template < class T > struct template_is_const { enum Anonymous2 { value = ! type_equal < T , Unconst < T > :: type > :: value } ; } ; " - "struct type_equal < T , T > { enum Anonymous0 { value = 0 } ; } ; " - "struct Unconst < const T * const > { } ; " - "struct Unconst < const T & * const > { } ; " - "struct Unconst < T * const * const > { } ; " - "struct Unconst < T * const > { } ; " - "struct Unconst < T * const > { } ; " - "struct Unconst < T * const > { } ; " - "struct Unconst < const T & > { } ; " - "struct Unconst < const T > { } ;"; + "template < class T > struct template_is_const { enum Anonymous2 { value = ! type_equal < T , Unconst < T > :: type > :: value } ; } ;"; ASSERT_EQUALS(exp1, tok(code1)); } @@ -1346,6 +1334,10 @@ private: ASSERT_EQUALS(3U, templateParameters("X x;")); TODO_ASSERT_EQUALS(1U, 0U, templateParameters("X x;")); // Mishandled valid syntax TODO_ASSERT_EQUALS(2U, 0U, templateParameters("X x;")); // Mishandled valid syntax + ASSERT_EQUALS(2U, templateParameters("X<1, T> x;")); + ASSERT_EQUALS(1U, templateParameters("X x;")); + ASSERT_EQUALS(2U, templateParameters("X=0> x;")); + ASSERT_EQUALS(3U, templateParameters("X=0, i - 2> x;")); } // Helper function to unit test TemplateSimplifier::getTemplateNamePosition diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index a4fb66208..e86e46ff2 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -2500,16 +2500,13 @@ private: void simplifyOperator2() { // #6576 - ASSERT_EQUALS("class TClass { " - "public: " - "TClass & operator= ( const TClass & rhs ) ; " + ASSERT_EQUALS("template < class T > class SharedPtr { " + "SharedPtr & operator= ( SharedPtr < Y > const & r ) ; " "} ; " - "TClass :: TClass ( const TClass & other ) " - "{ " - "operator= ( other ) ; " - "} class SharedPtr < Y > { " - "SharedPtr < Y > & operator= ( SharedPtr < Y > const & r ) ; " - "} ;", + "class TClass { " + "public: TClass & operator= ( const TClass & rhs ) ; " + "} ; " + "TClass :: TClass ( const TClass & other ) { operator= ( other ) ; }", tok("template\n" " class SharedPtr {\n" " SharedPtr& operator=(SharedPtr const & r);\n"