Skip to content

Commit 520314f

Browse files
committed
Ticket danmar#4335: Properly detect and handle template class specializations.
1 parent 40769c9 commit 520314f

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

lib/templatesimplifier.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -429,21 +429,21 @@ std::set<std::string> TemplateSimplifier::expandSpecialized(Token *tokens)
429429
ostr << " ";
430430
ostr << tok3->str();
431431
}
432-
if (!Token::simpleMatch(tok3, "> ("))
432+
if (!Token::Match(tok3, "> (|{"))
433433
continue;
434434
s = ostr.str();
435435
}
436436

437437
// save search pattern..
438-
const std::string pattern(s + " > (");
438+
const std::string pattern(s + " >");
439439

440440
// remove spaces to create new name
441441
s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
442442
const std::string name(s + ">");
443443
expandedtemplates.insert(name);
444444

445445
// Rename template..
446-
Token::eraseTokens(tok2, Token::findsimplematch(tok2, "("));
446+
Token::eraseTokens(tok2, Token::findsimplematch(tok2, "<")->findClosingBracket()->next());
447447
tok2->str(name);
448448

449449
// delete the "template < >"
@@ -452,7 +452,7 @@ std::set<std::string> TemplateSimplifier::expandSpecialized(Token *tokens)
452452

453453
// Use this special template in the code..
454454
while (nullptr != (tok2 = const_cast<Token *>(Token::findmatch(tok2, pattern.c_str())))) {
455-
Token::eraseTokens(tok2, Token::findsimplematch(tok2, "("));
455+
Token::eraseTokens(tok2, Token::findsimplematch(tok2, "<")->findClosingBracket()->next());
456456
tok2->str(name);
457457
}
458458
}
@@ -700,7 +700,7 @@ int TemplateSimplifier::getTemplateNamePosition(const Token *tok)
700700
{
701701
// get the position of the template name
702702
int namepos = 0, starAmpPossiblePosition = 0;
703-
if (Token::Match(tok, "> class|struct %type% {|:"))
703+
if (Token::Match(tok, "> class|struct %type% {|:|<"))
704704
namepos = 2;
705705
else if (Token::Match(tok, "> %type% *|&| %type% ("))
706706
namepos = 2;

test/testsimplifytemplate.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class TestSimplifyTemplate : public TestFixture {
8383
TEST_CASE(template50); // #4272 - simple partial specialization
8484
TEST_CASE(template51); // #6172 - crash upon valid code
8585
TEST_CASE(template52); // #6437 - crash upon valid code
86+
TEST_CASE(template53); // #4335 - bail out for valid code
8687
TEST_CASE(template_unhandled);
8788
TEST_CASE(template_default_parameter);
8889
TEST_CASE(template_default_type);
@@ -96,11 +97,12 @@ class TestSimplifyTemplate : public TestFixture {
9697
TEST_CASE(templateNamePosition);
9798
}
9899

99-
std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Unspecified) {
100+
std::string tok(const char code[], bool simplify = true, bool debugwarnings = false, Settings::PlatformType type = Settings::Unspecified) {
100101
errout.str("");
101102

102103
Settings settings;
103104
settings.addEnabled("portability");
105+
settings.debugwarnings = debugwarnings;
104106
settings.platform(type);
105107
Tokenizer tokenizer(&settings, this);
106108

@@ -938,6 +940,17 @@ class TestSimplifyTemplate : public TestFixture {
938940
"int value = calculate_value<1,1>();");
939941
}
940942

943+
void template53() { // #4335
944+
tok("template<int N> struct Factorial { "
945+
" enum { value = N * Factorial<N - 1>::value }; "
946+
"};"
947+
"template <> struct Factorial<0> { "
948+
" enum { value = 1 }; "
949+
"};"
950+
"const int x = Factorial<4>::value;", /*simplify=*/true, /*debugwarnings=*/true);
951+
ASSERT_EQUALS("", errout.str());
952+
}
953+
941954
void template_default_parameter() {
942955
{
943956
const char code[] = "template <class T, int n=3>\n"

0 commit comments

Comments
 (0)