From e9a44f70b225c0d4bc240571eb6e4e45466f05ef Mon Sep 17 00:00:00 2001 From: IOBYTE Date: Fri, 14 Sep 2018 08:16:34 -0400 Subject: [PATCH] Remove out of line member functions of instantiated template classes. (#1377) * Remove out of line member functions of instantiated template classes. --- lib/templatesimplifier.cpp | 56 ++++++++++++++++++++++------------- lib/templatesimplifier.h | 4 +++ test/testsimplifytemplate.cpp | 46 +++++----------------------- test/testtokenize.cpp | 3 +- 4 files changed, 48 insertions(+), 61 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 91b212ed2..f642cb7ed 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -929,25 +929,24 @@ bool TemplateSimplifier::instantiateMatch(const Token *instance, const std::size // hence this pattern: "> %type% [%type%] < ... > :: %type% (" static bool getTemplateNamePositionTemplateMember(const Token *tok, int &namepos) { - if (!Token::Match(tok, "> %type% <") && !Token::Match(tok, "> %type% %type% <")) - return false; - - int currPos = 0; - currPos = 2 + (Token::Match(tok, "> %type% %type%")); - - // Find the end of the template argument list - const Token *templateParmEnd = tok->linkAt(currPos); - if (!templateParmEnd) - templateParmEnd = tok->tokAt(currPos)->findClosingBracket(); - if (!templateParmEnd) - return false; - - 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 + (templateParmEnd->strAt(2) == "~" ? 3 : 2); - return true; + namepos = 2; + while (tok && tok->next()) { + if (Token::Match(tok->next(), ";|{")) + return false; + else if (Token::Match(tok->next(), "%type% <")) { + const Token *closing = tok->tokAt(2)->findClosingBracket(); + if (closing && Token::Match(closing->next(), ":: ~| %name% (")) { + if (closing->strAt(1) == "~") + closing = closing->next(); + while (tok && tok->next() != closing->next()) { + tok = tok->next(); + namepos++; + } + return true; + } + } + tok = tok->next(); + namepos++; } return false; } @@ -990,6 +989,7 @@ void TemplateSimplifier::expandTemplate( { std::list scopeInfo; bool inTemplateDefinition = false; + const Token *startOfTemplateDeclaration = nullptr; const Token *endOfTemplateDefinition = nullptr; const Token * const templateDeclarationNameToken = templateDeclarationToken->tokAt(getTemplateNamePosition(templateDeclarationToken)); for (const Token *tok3 = mTokenList.front(); tok3; tok3 = tok3 ? tok3->next() : nullptr) { @@ -1000,8 +1000,10 @@ void TemplateSimplifier::expandTemplate( if (inTemplateDefinition) { if (!endOfTemplateDefinition && tok3->str() == "{") endOfTemplateDefinition = tok3->link(); - if (tok3 == endOfTemplateDefinition) + if (tok3 == endOfTemplateDefinition) { inTemplateDefinition = false; + startOfTemplateDeclaration = nullptr; + } } if (tok3->str()=="template") { @@ -1015,6 +1017,7 @@ void TemplateSimplifier::expandTemplate( } else { inTemplateDefinition = false; // Only template instantiation } + startOfTemplateDeclaration = tok3; } if (Token::Match(tok3, "(|[")) tok3 = tok3->link(); @@ -1064,6 +1067,12 @@ void TemplateSimplifier::expandTemplate( mTokenList.addtoken(newName, tok3->linenr(), tok3->fileIndex()); while (tok3 && tok3->str() != "::") tok3 = tok3->next(); + + std::list::iterator it = std::find_if(mTemplateDeclarations.begin(), + mTemplateDeclarations.end(), + FindToken(startOfTemplateDeclaration)); + if (it != mTemplateDeclarations.end()) + mMemberFunctionsToDelete.push_back(*it); } // not part of template.. go on to next token @@ -1855,6 +1864,13 @@ void TemplateSimplifier::simplifyTemplates( removeTemplate(it->token); } } + + // remove out of line member functions + while (!mMemberFunctionsToDelete.empty()) { + removeTemplate(mMemberFunctionsToDelete.begin()->token); + mTemplateDeclarations.remove(mMemberFunctionsToDelete.front()); + mMemberFunctionsToDelete.erase(mMemberFunctionsToDelete.begin()); + } } } diff --git a/lib/templatesimplifier.h b/lib/templatesimplifier.h index e83873a9f..0917f13a1 100644 --- a/lib/templatesimplifier.h +++ b/lib/templatesimplifier.h @@ -69,6 +69,9 @@ public: */ struct TokenAndName { TokenAndName(Token *tok, const std::string &s, const std::string &n); + bool operator == (const TokenAndName & rhs) const { + return token == rhs.token && scope == rhs.scope && name == rhs.name; + } Token *token; std::string scope; std::string name; @@ -234,6 +237,7 @@ private: std::list mTemplateDeclarations; std::list mTemplateInstantiations; std::list mInstantiatedTemplates; + std::list mMemberFunctionsToDelete; }; /// @} diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 35b5da151..db3a6d1ac 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -215,12 +215,7 @@ private: "class Fred { } ; " "Fred :: Fred ( ) { }"; - 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)); + ASSERT_EQUALS(expected, tok(code)); } void template6() { @@ -563,8 +558,7 @@ private: "A a;\n"; // The expected result.. - const char expected[] = "template < class T > A < T > :: ~ A ( ) { } " // <- TODO: this should be removed - "A a ; " + const char expected[] = "A a ; " "class A { public: ~ A ( ) ; } ; " "A :: ~ A ( ) { }"; ASSERT_EQUALS(expected, tok(code)); @@ -950,9 +944,7 @@ private: "template void Fred::f();\n" "template void Fred::g();\n"; - const char expected[] = "template < class T > void Fred < T > :: f ( ) { } " - "template < class T > void Fred < T > :: g ( ) { } " - "template void Fred :: f ( ) ; " + const char expected[] = "template void Fred :: f ( ) ; " "template void Fred :: g ( ) ; " "class Fred { void f ( ) ; void g ( ) ; } ; " "void Fred :: f ( ) { } " @@ -1147,7 +1139,6 @@ private: "template C3::C3(const C3 &v) { C1 c1; }\n" "C3 c3;"; const char exp[] = "template < class T > void f ( ) { x = y ? C1 < int > :: allocate ( 1 ) : 0 ; } " - "template < class T , int S > C3 < T , S > :: C3 ( const C3 < T , S > & v ) { C1 < T * > c1 ; } " "C3 c3 ; " "class C3 { } ; " "C3 :: C3 ( const C3 & v ) { C1 c1 ; } " @@ -1208,12 +1199,7 @@ private: "const int * * foo ( ) ; " "} ; " "const int * * Fred :: foo ( ) { return nullptr ; }"; - const char curr[] = "template < class T > const int * * Fred < T > :: foo ( ) { return nullptr ; } " - "Fred fred ; struct Fred { " - "const int * * foo ( ) ; " - "} ; " - "const int * * Fred :: foo ( ) { return nullptr ; }"; - TODO_ASSERT_EQUALS(exp, curr, tok(code)); + ASSERT_EQUALS(exp, tok(code)); } void template67() { // ticket #8122 @@ -1241,29 +1227,11 @@ private: "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 Containter & x ) { nElements = x . nElements ; c = x . c ; } " + "Containter & Containter :: operator= ( const Containter & x ) { mElements = x . mElements ; c = x . c ; return * this ; } " "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)); + ASSERT_EQUALS(expected, tok(code)); } void template_specialization_1() { // #7868 - template specialization template struct S> {..}; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 099fa85a3..ebce0c6c8 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -839,8 +839,7 @@ private: "};\n" "template Containter::Containter() : mElements(nullptr) {}\n" "Containter intContainer;"; - const char exp [] = "5: template < class T > Containter < T > :: Containter ( ) : mElements ( nullptr ) { }\n" - "6: Containter intContainer@1 ; struct Containter {\n" + const char exp [] = "6: Containter intContainer@1 ; struct Containter {\n" "2: Containter ( ) ;\n" "3: int * mElements@2 ;\n" "4: } ;\n"