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

View File

@ -83,6 +83,7 @@ private:
TEST_CASE(template50); // #4272 - simple partial specialization TEST_CASE(template50); // #4272 - simple partial specialization
TEST_CASE(template51); // #6172 - crash upon valid code TEST_CASE(template51); // #6172 - crash upon valid code
TEST_CASE(template52); // #6437 - 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_unhandled);
TEST_CASE(template_default_parameter); TEST_CASE(template_default_parameter);
TEST_CASE(template_default_type); TEST_CASE(template_default_type);
@ -96,11 +97,12 @@ private:
TEST_CASE(templateNamePosition); 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(""); errout.str("");
Settings settings; Settings settings;
settings.addEnabled("portability"); settings.addEnabled("portability");
settings.debugwarnings = debugwarnings;
settings.platform(type); settings.platform(type);
Tokenizer tokenizer(&settings, this); Tokenizer tokenizer(&settings, this);
@ -938,6 +940,17 @@ private:
"int value = calculate_value<1,1>();"); "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() { void template_default_parameter() {
{ {
const char code[] = "template <class T, int n=3>\n" const char code[] = "template <class T, int n=3>\n"