diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index eab9cf743..cbeb8aaa8 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -4374,6 +4374,9 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) if (isCPP()) mTemplateSimplifier->fixAngleBrackets(); + // Remove extra "template" tokens that are not used by cppcheck + removeExtraTemplateKeywords(); + // Bail out if code is garbage if (mTimerResults) { Timer t("Tokenizer::tokenize::findGarbageCode", mSettings->showtime, mTimerResults); @@ -5152,6 +5155,16 @@ void Tokenizer::simplifyHeadersAndUnusedTemplates() } } +void Tokenizer::removeExtraTemplateKeywords() +{ + if (isCPP()) { + for (Token *tok = list.front(); tok; tok = tok->next()) { + if (Token::Match(tok, "%name% .|:: template %name%")) + tok->next()->deleteNext(); + } + } +} + void Tokenizer::removeMacrosInGlobalScope() { for (Token *tok = list.front(); tok; tok = tok->next()) { diff --git a/lib/tokenize.h b/lib/tokenize.h index c54ed82c9..ae369d280 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -171,6 +171,11 @@ public: */ void simplifyHeadersAndUnusedTemplates(); + /** + * Remove extra "template" keywords that are not used by Cppcheck + */ + void removeExtraTemplateKeywords(); + /** * Deletes dead code between 'begin' and 'end'. * In general not everything can be erased, such as: diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index f0b24aaba..d810b25d5 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -516,6 +516,8 @@ private: TEST_CASE(cppcast); TEST_CASE(checkHeader1); + + TEST_CASE(removeExtraTemplateKeywords); } std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Native, const char* filename = "test.cpp", bool cpp11 = true) { @@ -6469,7 +6471,7 @@ private: ASSERT_EQUALS("template < typename T > void g ( S < & T :: operatorint > ) { }", tokenizeAndStringify(code3)); const char code4[] = "template void g(S<&T::template operator- >) {}"; - ASSERT_EQUALS("template < typename T > void g ( S < & T :: template operator- < double > > ) { }", tokenizeAndStringify(code4)); + ASSERT_EQUALS("template < typename T > void g ( S < & T :: operator- < double > > ) { }", tokenizeAndStringify(code4)); } void simplifyOperatorName12() { // #9110 @@ -8709,6 +8711,16 @@ private: "5: ;\n", checkHeaders(code, false)); } + + void removeExtraTemplateKeywords() { + const char code1[] = "typename GridView::template Codim<0>::Iterator iterator;"; + const char expected1[] = "GridView :: Codim < 0 > :: Iterator iterator ;"; + ASSERT_EQUALS(expected1, tokenizeAndStringify(code1, false)); + + const char code2[] = "typename GridView::template Codim<0>::Iterator it = gv.template begin<0>();"; + const char expected2[] = "GridView :: Codim < 0 > :: Iterator it ; it = gv . begin < 0 > ( ) ;"; + ASSERT_EQUALS(expected2, tokenizeAndStringify(code2, false)); + } }; REGISTER_TEST(TestTokenizer)