diff --git a/src/tokenize.cpp b/src/tokenize.cpp index 3443c36a8..aa4e91a87 100644 --- a/src/tokenize.cpp +++ b/src/tokenize.cpp @@ -483,6 +483,62 @@ void Tokenizer::tokenize(std::istream &code, const char FileName[]) } } + // Handle templates.. + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (!Token::Match(tok, "template < %type% %var% > %type% %var% (")) + continue; + + // type and function name.. + const std::string type(tok->strAt(3)); + const std::string funcname(tok->strAt(6)); + + // locate template usage.. + const std::string pattern(funcname + " < %type% > ("); + for (Token *tok2 = _tokens; tok2; tok2 = tok2->next()) + { + if (!Token::Match(tok2, pattern.c_str())) + continue; + + // New type.. + const std::string type2(tok2->strAt(2)); + + // New funcname.. + const std::string funcname2(funcname + "<" + type2 + ">"); + + // Create copy of template.. + const Token *tok3 = tok->tokAt(5); + addtoken(((tok3->str()==type)?type2:tok3->str()).c_str(), tok3->linenr(), tok3->fileIndex()); + addtoken(funcname2.c_str(), tok3->linenr(), tok3->fileIndex()); + int indentlevel = 0; + for (tok3 = tok3->tokAt(2); tok3; tok3 = tok3->next()) + { + addtoken(((tok3->str()==type)?type2:tok3->str()).c_str(), tok3->linenr(), tok3->fileIndex()); + + if (tok3->str() == "{") + ++indentlevel; + + else if (tok3->str() == "}") + { + if (indentlevel <= 1) + break; + --indentlevel; + } + } + + // Replace all these template usages.. + for (Token *tok4 = tok2; tok4; tok4 = tok4->next()) + { + if (Token::simpleMatch(tok4, (funcname + " < " + type2 + " >").c_str())) + { + tok4->str(funcname2.c_str()); + tok4->deleteNext(); + tok4->deleteNext(); + tok4->deleteNext(); + } + } + } + } } //--------------------------------------------------------------------------- diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 4a9895a06..1492e5814 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -76,6 +76,8 @@ private: TEST_CASE(sizeof5); TEST_CASE(sizeof6); TEST_CASE(casting); + + TEST_CASE(template1); } std::string tok(const char code[]) @@ -441,10 +443,25 @@ private: "for (int i = 0; i < static_cast(3); ++i) {}\n" "}\n"; - std::ostringstream expected; - expected << " void f ( ) { for ( int i = 0 ; i < 3 ; ++ i ) { } }"; + const std::string expected(" void f ( ) { for ( int i = 0 ; i < 3 ; ++ i ) { } }"); - ASSERT_EQUALS(expected.str(), sizeof_(code)); + ASSERT_EQUALS(expected, sizeof_(code)); + } + + + + + void template1() + { + const char code[] = "template void f(T val) { T a; }\n" + "f(10);"; + + const std::string expected(" " + "template < classname T > void f ( T val ) { T a ; } " + "f ( 10 ) ; " + "void f ( int val ) { int a ; }"); + + ASSERT_EQUALS(expected, sizeof_(code)); } };