From 520314f9a097fbd2b8cc6dc5ea7acd9424290be2 Mon Sep 17 00:00:00 2001 From: Simon Martin Date: Sun, 15 Mar 2015 00:28:33 +0100 Subject: [PATCH] Ticket #4335: Properly detect and handle template class specializations. --- lib/templatesimplifier.cpp | 10 +++++----- test/testsimplifytemplate.cpp | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 09d17c843..b10cd8257 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -429,13 +429,13 @@ std::set 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 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 TemplateSimplifier::expandSpecialized(Token *tokens) // Use this special template in the code.. while (nullptr != (tok2 = const_cast(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; diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 51cd017b0..22b44c4ce 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -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 struct Factorial { " + " enum { value = N * Factorial::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 \n"