From a6ad972aad532e7fea23139e3f9311df21b77e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 15 Mar 2009 20:03:29 +0100 Subject: [PATCH] Fix Ticket 180 (Templates: Expanding member functions that are not implemented inline) --- src/tokenize.cpp | 71 ++++++++++++++++++++++++------------- test/testsimplifytokens.cpp | 17 +++++++++ 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/src/tokenize.cpp b/src/tokenize.cpp index 5d05bd836..bf181596a 100644 --- a/src/tokenize.cpp +++ b/src/tokenize.cpp @@ -512,10 +512,10 @@ void Tokenizer::tokenize(std::istream &code, const char FileName[]) s += ","; s += " %any% "; } - const std::string pattern(s + "> " + (isfunc ? "(" : "%var%")); + const std::string pattern(s + "> "); for (Token *tok2 = _tokens; tok2; tok2 = tok2->next()) { - if (!Token::Match(tok2, pattern.c_str())) + if (!Token::Match(tok2, (pattern + (isfunc ? "(" : "%var%")).c_str())) continue; // New type.. @@ -532,34 +532,55 @@ void Tokenizer::tokenize(std::istream &code, const char FileName[]) // New classname/funcname.. const std::string name2(name + "<" + type2 + ">"); - // Create copy of template.. - int indentlevel = 0; - for (const Token *tok3 = tok->next(); tok3; tok3 = tok3->next()) + // Copy template.. + for (const Token *tok3 = _tokens; tok3; tok3 = tok3->next()) { - for (unsigned int i = 0; i <= type.size(); ++i) + // Start of template.. + if (tok3 == tok) { - if (i == type.size()) - { - if (tok3->str() == name) - addtoken(name2.c_str(), tok3->linenr(), tok3->fileIndex()); - else - addtoken(tok3->str().c_str(), tok3->linenr(), tok3->fileIndex()); - } - else if (tok3->str() == type[i]) - { - addtoken(types2[i].c_str(), tok3->linenr(), tok3->fileIndex()); - break; - } + tok3 = tok3->next(); } - if (tok3->str() == "{") - ++indentlevel; - - else if (tok3->str() == "}") + // member function implemented outside class definition + else if (Token::Match(tok3, (pattern + " :: %var% (").c_str())) { - if (indentlevel <= 1) - break; - --indentlevel; + addtoken(name2.c_str(), tok3->linenr(), tok3->fileIndex()); + while (tok3->str() != "::") + tok3 = tok3->next(); + } + + // not part of template.. go on to next token + else + continue; + + int indentlevel = 0; + for (; tok3; tok3 = tok3->next()) + { + for (unsigned int i = 0; i <= type.size(); ++i) + { + if (i == type.size()) + { + if (tok3->str() == name) + addtoken(name2.c_str(), tok3->linenr(), tok3->fileIndex()); + else + addtoken(tok3->str().c_str(), tok3->linenr(), tok3->fileIndex()); + } + else if (tok3->str() == type[i]) + { + addtoken(types2[i].c_str(), tok3->linenr(), tok3->fileIndex()); + break; + } + } + + if (tok3->str() == "{") + ++indentlevel; + + else if (tok3->str() == "}") + { + if (indentlevel <= 1) + break; + --indentlevel; + } } } diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 065a6b67c..03e80f6b9 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -81,6 +81,7 @@ private: TEST_CASE(template2); TEST_CASE(template3); TEST_CASE(template4); + TEST_CASE(template5); TEST_CASE(namespaces); } @@ -508,6 +509,22 @@ private: ASSERT_EQUALS(expected, sizeof_(code)); } + void template5() + { + const char code[] = "template class Fred { };\n" + "template Fred::Fred() { }\n" + "Fred fred;"; + + const std::string expected(" " + "template < classname T > class Fred { } ; " + "template < classname T > Fred < T > :: Fred ( ) { } " + "Fred fred ; " + "class Fred { } " + "Fred :: Fred ( ) { }"); + + ASSERT_EQUALS(expected, sizeof_(code)); + } + void namespaces() {