Ticket #4335: Properly detect and handle template class specializations.

This commit is contained in:
Simon Martin 2015-03-15 00:28:33 +01:00
parent 40769c9a59
commit 520314f9a0
2 changed files with 19 additions and 6 deletions

View File

@ -429,13 +429,13 @@ std::set<std::string> TemplateSimplifier::expandSpecialized(Token *tokens)
ostr << " ";
ostr << tok3->str();
}
if (!Token::simpleMatch(tok3, "> ("))
if (!Token::Match(tok3, "> (|{"))
continue;
s = ostr.str();
}
// save search pattern..
const std::string pattern(s + " > (");
const std::string pattern(s + " >");
// remove spaces to create new name
s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
@ -443,7 +443,7 @@ std::set<std::string> TemplateSimplifier::expandSpecialized(Token *tokens)
expandedtemplates.insert(name);
// Rename template..
Token::eraseTokens(tok2, Token::findsimplematch(tok2, "("));
Token::eraseTokens(tok2, Token::findsimplematch(tok2, "<")->findClosingBracket()->next());
tok2->str(name);
// delete the "template < >"
@ -452,7 +452,7 @@ std::set<std::string> TemplateSimplifier::expandSpecialized(Token *tokens)
// Use this special template in the code..
while (nullptr != (tok2 = const_cast<Token *>(Token::findmatch(tok2, pattern.c_str())))) {
Token::eraseTokens(tok2, Token::findsimplematch(tok2, "("));
Token::eraseTokens(tok2, Token::findsimplematch(tok2, "<")->findClosingBracket()->next());
tok2->str(name);
}
}
@ -700,7 +700,7 @@ int TemplateSimplifier::getTemplateNamePosition(const Token *tok)
{
// get the position of the template name
int namepos = 0, starAmpPossiblePosition = 0;
if (Token::Match(tok, "> class|struct %type% {|:"))
if (Token::Match(tok, "> class|struct %type% {|:|<"))
namepos = 2;
else if (Token::Match(tok, "> %type% *|&| %type% ("))
namepos = 2;

View File

@ -83,6 +83,7 @@ private:
TEST_CASE(template50); // #4272 - simple partial specialization
TEST_CASE(template51); // #6172 - crash upon valid code
TEST_CASE(template52); // #6437 - crash upon valid code
TEST_CASE(template53); // #4335 - bail out for valid code
TEST_CASE(template_unhandled);
TEST_CASE(template_default_parameter);
TEST_CASE(template_default_type);
@ -96,11 +97,12 @@ private:
TEST_CASE(templateNamePosition);
}
std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Unspecified) {
std::string tok(const char code[], bool simplify = true, bool debugwarnings = false, Settings::PlatformType type = Settings::Unspecified) {
errout.str("");
Settings settings;
settings.addEnabled("portability");
settings.debugwarnings = debugwarnings;
settings.platform(type);
Tokenizer tokenizer(&settings, this);
@ -938,6 +940,17 @@ private:
"int value = calculate_value<1,1>();");
}
void template53() { // #4335
tok("template<int N> struct Factorial { "
" enum { value = N * Factorial<N - 1>::value }; "
"};"
"template <> struct Factorial<0> { "
" enum { value = 1 }; "
"};"
"const int x = Factorial<4>::value;", /*simplify=*/true, /*debugwarnings=*/true);
ASSERT_EQUALS("", errout.str());
}
void template_default_parameter() {
{
const char code[] = "template <class T, int n=3>\n"