From 4ebd9d43fdb37906c3b0dfe354a80cec8eb4c644 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Sun, 14 Mar 2021 13:37:52 -0400 Subject: [PATCH 1/5] small template simplifier optimization --- lib/templatesimplifier.cpp | 8 ++++---- lib/templatesimplifier.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index d22bbb7c9a3..ea16fe80a58 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -1650,7 +1650,7 @@ void TemplateSimplifier::expandTemplate( std::stack brackets1; // holds "(" and "{" tokens bool pointerType = false; Token * const dst1 = dst->previous(); - for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token(); + for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype]; typetok && (typeindentlevel > 0 || !Token::Match(typetok, ",|>")); typetok = typetok->next()) { if (typeindentlevel == 0 && typetok->str() == "*") @@ -1896,7 +1896,7 @@ void TemplateSimplifier::expandTemplate( if (itype < typeParametersInDeclaration.size()) { unsigned int typeindentlevel = 0; std::stack brackets1; // holds "(" and "{" tokens - for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token(); + for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype]; typetok && (typeindentlevel>0 || !Token::Match(typetok, ",|>")); typetok = typetok->next()) { if (!Token::simpleMatch(typetok, "...")) { @@ -2003,7 +2003,7 @@ void TemplateSimplifier::expandTemplate( std::stack brackets1; // holds "(" and "{" tokens Token * const beforeTypeToken = mTokenList.back(); bool pointerType = false; - for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token(); + for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype]; typetok && (typeindentlevel > 0 || !Token::Match(typetok, ",|>")); typetok = typetok->next()) { if (typeindentlevel == 0 && typetok->str() == "*") @@ -2909,7 +2909,7 @@ std::string TemplateSimplifier::getNewName( else if (indentlevel > 0 && Token::Match(tok3, "> [,>]")) --indentlevel; if (indentlevel == 0 && Token::Match(tok3->previous(), "[<,]")) { - mTypesUsedInTemplateInstantiation.emplace_back(tok3, ""); + mTypesUsedInTemplateInstantiation.push_back(tok3); } if (tok3->str() == "(") ++indentlevel; diff --git a/lib/templatesimplifier.h b/lib/templatesimplifier.h index 65ab648aad2..241ba722760 100644 --- a/lib/templatesimplifier.h +++ b/lib/templatesimplifier.h @@ -501,7 +501,7 @@ class CPPCHECKLIB TemplateSimplifier { std::list mInstantiatedTemplates; std::list mMemberFunctionsToDelete; std::vector mExplicitInstantiationsToDelete; - std::vector mTypesUsedInTemplateInstantiation; + std::vector mTypesUsedInTemplateInstantiation; std::unordered_map mTemplateNamePos; }; From b24667f64c2b315217310ef21b059149d1f3d92f Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Sun, 14 Mar 2021 13:41:21 -0400 Subject: [PATCH 2/5] don't look for template parameter name in default values --- lib/templatesimplifier.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index ea16fe80a58..b5eff7156b6 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -2825,6 +2825,7 @@ const Token * TemplateSimplifier::getTemplateParametersInDeclaration( typeParametersInDeclaration.clear(); const Token *end = tok->previous()->findClosingBracket(); + bool inDefaultValue = false; for (; tok && tok!= end; tok = tok->next()) { if (Token::simpleMatch(tok, "template <")) { const Token *closing = tok->next()->findClosingBracket(); @@ -2832,8 +2833,21 @@ const Token * TemplateSimplifier::getTemplateParametersInDeclaration( tok = closing->next(); } else if (tok->link() && Token::Match(tok, "{|(|[")) tok = tok->link(); - else if (Token::Match(tok, "%name% ,|>|=")) - typeParametersInDeclaration.push_back(tok); + else if (Token::Match(tok, "%name% ,|>|=")) { + if (!inDefaultValue) { + typeParametersInDeclaration.push_back(tok); + if (tok->strAt(1) == "=") + inDefaultValue = true; + } + } else if (inDefaultValue) { + if (tok->str() == ",") + inDefaultValue = false; + else if (tok->str() == "<") { + const Token *end = tok->findClosingBracket(); + if (end) + tok = end; + } + } } return tok; } From 8d57f2a88ec23b7df2ab37ad95aa5012caeb6d48 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Sun, 14 Mar 2021 14:04:46 -0400 Subject: [PATCH 3/5] fix cppcheck warning --- lib/templatesimplifier.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index b5eff7156b6..7a3813d2a92 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -2843,9 +2843,9 @@ const Token * TemplateSimplifier::getTemplateParametersInDeclaration( if (tok->str() == ",") inDefaultValue = false; else if (tok->str() == "<") { - const Token *end = tok->findClosingBracket(); - if (end) - tok = end; + const Token *closing = tok->findClosingBracket(); + if (closing) + tok = closing; } } } From f7e2d2ed2cd0a9bd6452b21e322c0681e8e6d8d8 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Mon, 15 Mar 2021 11:39:01 -0400 Subject: [PATCH 4/5] add test for TemplateSimplifier::getTemplateParametersInDeclaration() Also removed TemplateSimplifier::getTemplateParametersInDeclaration() return value since it wasn't used. --- lib/templatesimplifier.cpp | 3 +-- lib/templatesimplifier.h | 6 +++--- test/testsimplifytemplate.cpp | 31 +++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 7a3813d2a92..e9cfc3a09bf 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -2817,7 +2817,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToke return ret; } -const Token * TemplateSimplifier::getTemplateParametersInDeclaration( +void TemplateSimplifier::getTemplateParametersInDeclaration( const Token * tok, std::vector & typeParametersInDeclaration) { @@ -2849,7 +2849,6 @@ const Token * TemplateSimplifier::getTemplateParametersInDeclaration( } } } - return tok; } bool TemplateSimplifier::matchSpecialization( diff --git a/lib/templatesimplifier.h b/lib/templatesimplifier.h index 241ba722760..f65d0b35a0c 100644 --- a/lib/templatesimplifier.h +++ b/lib/templatesimplifier.h @@ -43,6 +43,8 @@ class TokenList; /** @brief Simplify templates from the preprocessed and partially simplified code. */ class CPPCHECKLIB TemplateSimplifier { + friend class TestSimplifyTemplate; + public: explicit TemplateSimplifier(Tokenizer *tokenizer); ~TemplateSimplifier(); @@ -437,10 +439,8 @@ class CPPCHECKLIB TemplateSimplifier { * ^ tok * @param typeParametersInDeclaration template < typename T, typename S > * ^ [0] ^ [1] - * @return template < typename T, typename S > - * ^ return */ - static const Token * getTemplateParametersInDeclaration( + static void getTemplateParametersInDeclaration( const Token * tok, std::vector & typeParametersInDeclaration); diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index a6afd8190cb..922d19552e0 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -243,6 +243,8 @@ class TestSimplifyTemplate : public TestFixture { TEST_CASE(findTemplateDeclarationEnd); + TEST_CASE(getTemplateParametersInDeclaration); + TEST_CASE(expandSpecialized1); TEST_CASE(expandSpecialized2); TEST_CASE(expandSpecialized3); // #8671 @@ -5206,6 +5208,35 @@ class TestSimplifyTemplate : public TestFixture { ASSERT(findTemplateDeclarationEndHelper("template >::g>> void i(){} int x;", "} int x ;")); } + // Helper function to unit test TemplateSimplifier::getTemplateParametersInDeclaration + bool getTemplateParametersInDeclarationHelper(const char code[], const std::vector & params) { + Tokenizer tokenizer(&settings, this); + + std::istringstream istr(code); + tokenizer.createTokens(istr, "test.cpp"); + tokenizer.createLinks(); + tokenizer.splitTemplateRightAngleBrackets(false); + + std::vector typeParametersInDeclaration; + TemplateSimplifier::getTemplateParametersInDeclaration(tokenizer.tokens()->tokAt(2), typeParametersInDeclaration); + + if (params.size() != typeParametersInDeclaration.size()) + return false; + + for (size_t i = 0; i < typeParametersInDeclaration.size(); ++i) { + if (typeParametersInDeclaration[i]->str() != params[i]) + return false; + } + return true; + } + + void getTemplateParametersInDeclaration() { + ASSERT(getTemplateParametersInDeclarationHelper("template class Fred {};", std::vector{"T"})); + ASSERT(getTemplateParametersInDeclarationHelper("template class Fred {};", std::vector{"T"})); + ASSERT(getTemplateParametersInDeclarationHelper("template class Fred {};", std::vector{"T","U"})); + ASSERT(getTemplateParametersInDeclarationHelper("template class Fred {};", std::vector{"T","U"})); + } + void expandSpecialized1() { ASSERT_EQUALS("class A { } ;", tok("template<> class A {};")); ASSERT_EQUALS("class A : public B { } ;", tok("template<> class A : public B {};")); From 9f27d5524f17e2b5cd28bc260748a1105356e18e Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Mon, 15 Mar 2021 12:52:52 -0400 Subject: [PATCH 5/5] added another test --- test/testsimplifytemplate.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 922d19552e0..f5a6b13ca1e 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -5233,6 +5233,7 @@ class TestSimplifyTemplate : public TestFixture { void getTemplateParametersInDeclaration() { ASSERT(getTemplateParametersInDeclarationHelper("template class Fred {};", std::vector{"T"})); ASSERT(getTemplateParametersInDeclarationHelper("template class Fred {};", std::vector{"T"})); + ASSERT(getTemplateParametersInDeclarationHelper("template class Fred {};", std::vector{"T","U"})); ASSERT(getTemplateParametersInDeclarationHelper("template class Fred {};", std::vector{"T","U"})); ASSERT(getTemplateParametersInDeclarationHelper("template class Fred {};", std::vector{"T","U"})); }