Fix Ticket 180 (Templates: Expanding member functions that are not implemented inline)

This commit is contained in:
Daniel Marjamäki 2009-03-15 20:03:29 +01:00
parent 9b06b22053
commit a6ad972aad
2 changed files with 63 additions and 25 deletions

View File

@ -512,10 +512,10 @@ void Tokenizer::tokenize(std::istream &code, const char FileName[])
s += ","; s += ",";
s += " %any% "; s += " %any% ";
} }
const std::string pattern(s + "> " + (isfunc ? "(" : "%var%")); const std::string pattern(s + "> ");
for (Token *tok2 = _tokens; tok2; tok2 = tok2->next()) 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; continue;
// New type.. // New type..
@ -532,34 +532,55 @@ void Tokenizer::tokenize(std::istream &code, const char FileName[])
// New classname/funcname.. // New classname/funcname..
const std::string name2(name + "<" + type2 + ">"); const std::string name2(name + "<" + type2 + ">");
// Create copy of template.. // Copy template..
int indentlevel = 0; for (const Token *tok3 = _tokens; tok3; tok3 = tok3->next())
for (const Token *tok3 = tok->next(); tok3; tok3 = tok3->next())
{ {
for (unsigned int i = 0; i <= type.size(); ++i) // Start of template..
if (tok3 == tok)
{ {
if (i == type.size()) tok3 = tok3->next();
{
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() == "{") // member function implemented outside class definition
++indentlevel; else if (Token::Match(tok3, (pattern + " :: %var% (").c_str()))
else if (tok3->str() == "}")
{ {
if (indentlevel <= 1) addtoken(name2.c_str(), tok3->linenr(), tok3->fileIndex());
break; while (tok3->str() != "::")
--indentlevel; 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;
}
} }
} }

View File

@ -81,6 +81,7 @@ private:
TEST_CASE(template2); TEST_CASE(template2);
TEST_CASE(template3); TEST_CASE(template3);
TEST_CASE(template4); TEST_CASE(template4);
TEST_CASE(template5);
TEST_CASE(namespaces); TEST_CASE(namespaces);
} }
@ -508,6 +509,22 @@ private:
ASSERT_EQUALS(expected, sizeof_(code)); ASSERT_EQUALS(expected, sizeof_(code));
} }
void template5()
{
const char code[] = "template <classname T> class Fred { };\n"
"template <classname T> Fred<T>::Fred() { }\n"
"Fred<float> fred;";
const std::string expected(" "
"template < classname T > class Fred { } ; "
"template < classname T > Fred < T > :: Fred ( ) { } "
"Fred<float> fred ; "
"class Fred<float> { } "
"Fred<float> :: Fred<float> ( ) { }");
ASSERT_EQUALS(expected, sizeof_(code));
}
void namespaces() void namespaces()
{ {