Ticket #4335: Properly detect and handle template class specializations.
This commit is contained in:
parent
40769c9a59
commit
520314f9a0
|
@ -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;
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue