diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index a501b7623..91b212ed2 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -942,11 +942,11 @@ static bool getTemplateNamePositionTemplateMember(const Token *tok, int &namepos if (!templateParmEnd) return false; - if (Token::Match(templateParmEnd->next(), ":: %type% (")) { + if (Token::Match(templateParmEnd->next(), ":: ~| %type% (")) { // We have a match, and currPos points at the template list opening '<'. Move it to the closing '>' for (const Token *tok2 = tok->tokAt(currPos) ; tok2 != templateParmEnd ; tok2 = tok2->next()) ++currPos; - namepos = currPos + 2; + namepos = currPos + (templateParmEnd->strAt(2) == "~" ? 3 : 2); return true; } return false; @@ -1053,7 +1053,12 @@ void TemplateSimplifier::expandTemplate( tok5 = tok5->next(); // copy return type while (tok5 && tok5 != tok3) { - mTokenList.addtoken(tok5, tok5->linenr(), tok5->fileIndex()); + // replace name if found + if (Token::Match(tok5, "%name% <") && tok5->str() == fullName) { + mTokenList.addtoken(newName, tok5->linenr(), tok5->fileIndex()); + tok5 = tok5->next()->findClosingBracket(); + } else + mTokenList.addtoken(tok5, tok5->linenr(), tok5->fileIndex()); tok5 = tok5->next(); } mTokenList.addtoken(newName, tok3->linenr(), tok3->fileIndex()); @@ -1100,9 +1105,7 @@ void TemplateSimplifier::expandTemplate( // replace name.. if (tok3->str() == lastName) { - if (Token::Match(tok3->tokAt(-2), "> :: %name% ( )")) { - ; // Ticket #7942: Replacing for out-of-line constructors generates invalid syntax - } else if (!Token::simpleMatch(tok3->next(), "<")) { + if (!Token::simpleMatch(tok3->next(), "<")) { mTokenList.addtoken(newName, tok3->linenr(), tok3->fileIndex()); continue; } else if (tok3 == templateDeclarationNameToken) { diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index c8217cc74..35b5da151 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -104,6 +104,7 @@ private: TEST_CASE(template64); // #8683 TEST_CASE(template65); // #8321 TEST_CASE(template66); // #8725 + TEST_CASE(template67); // #8122 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) @@ -210,12 +211,16 @@ private: "template Fred::Fred() { }\n" "Fred fred;"; - const char expected[] = "template < class T > Fred < T > :: Fred ( ) { } " // <- TODO: this should be removed - "Fred fred ; " + const char expected[] = "Fred fred ; " "class Fred { } ; " - "Fred :: Fred ( ) { }"; + "Fred :: Fred ( ) { }"; - ASSERT_EQUALS(expected, tok(code)); + const char actual[] = "template < class T > Fred < T > :: Fred ( ) { } " // <- TODO: this should be removed + "Fred fred ; " + "class Fred { } ; " + "Fred :: Fred ( ) { }"; + + TODO_ASSERT_EQUALS(expected, actual, tok(code)); } void template6() { @@ -1211,6 +1216,56 @@ private: TODO_ASSERT_EQUALS(exp, curr, tok(code)); } + void template67() { // ticket #8122 + const char code[] = "template struct Containter {\n" + " Containter();\n" + " Containter(const Containter &);\n" + " Containter & operator = (const Containter &);\n" + " ~Containter();\n" + " T* mElements;\n" + " const Containter * c;\n" + "};\n" + "template Containter::Containter() : mElements(nullptr), c(nullptr) {}\n" + "template Containter::Containter(const Containter & x) { nElements = x.nElements; c = x.c; }\n" + "template Containter & Containter::operator = (const Containter & x) { mElements = x.mElements; c = x.c; return *this; }\n" + "template Containter::~Containter() {}\n" + "Containter intContainer;"; + + const char expected[] = "Containter intContainer ; " + "struct Containter { " + "Containter ( ) ; " + "Containter ( const Containter & ) ; " + "Containter & operator= ( const Containter & ) ; " + "~ Containter ( ) ; " + "int * mElements ; " + "const Containter * c ; " + "} ; " + "Containter :: Containter ( ) : mElements ( nullptr ) , c ( nullptr ) { } " + "Containter :: Containter ( const Containter & ) { nElements = x . nElements ; c = x . c ; } " + "Containter & Containter :: operator= ( const Containter & x) { mElements = x . mElements ; c = x . c ; return * this ; }\n" + "Containter :: ~ Containter ( ) { }"; + + const char actual[] = "template < class T > Containter < T > :: Containter ( ) : mElements ( nullptr ) , c ( nullptr ) { } " + "template < class T > Containter < T > :: Containter ( const Containter & x ) { nElements = x . nElements ; c = x . c ; } " + "template < class T > Containter < T > & Containter < T > :: operator= ( const Containter & x ) { mElements = x . mElements ; c = x . c ; return * this ; } " + "template < class T > Containter < T > :: ~ Containter ( ) { } " + "Containter intContainer ; " + "struct Containter { " + "Containter ( ) ; " + "Containter ( const Containter & ) ; " + "Containter & operator= ( const Containter & ) ; " + "~ Containter ( ) ; " + "int * mElements ; " + "const Containter * c ; " + "} ; " + "Containter :: Containter ( ) : mElements ( nullptr ) , c ( nullptr ) { } " + "Containter :: Containter ( const Containter & x ) { nElements = x . nElements ; c = x . c ; } " + "Containter & Containter :: operator= ( const Containter & x ) { mElements = x . mElements ; c = x . c ; return * this ; } " + "Containter :: ~ Containter ( ) { }"; + + TODO_ASSERT_EQUALS(expected, actual, 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/testtokenize.cpp b/test/testtokenize.cpp index 4b1dfc0d0..3552f8ff8 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -843,7 +843,7 @@ private: "2: Containter ( ) ;\n" "3: int * mElements@2 ;\n" "4: } ;\n" - "5: Containter :: Containter ( ) : mElements@2 ( nullptr ) { }\n"; + "5: Containter :: Containter ( ) : mElements@2 ( nullptr ) { }\n"; ASSERT_EQUALS(exp, tokenizeDebugListing(code, /*simplify=*/true)); } }