Ticket #7891: Do not remove spaces in the internal representation for template instantiations.
This commit is contained in:
parent
beb72c2583
commit
0943b2145b
|
@ -435,11 +435,7 @@ std::set<std::string> TemplateSimplifier::expandSpecialized(Token *tokens)
|
||||||
s = ostr.str();
|
s = ostr.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// save search pattern..
|
|
||||||
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());
|
|
||||||
const std::string name(s + " >");
|
const std::string name(s + " >");
|
||||||
expandedtemplates.insert(name);
|
expandedtemplates.insert(name);
|
||||||
|
|
||||||
|
@ -452,7 +448,7 @@ std::set<std::string> TemplateSimplifier::expandSpecialized(Token *tokens)
|
||||||
tok->deleteThis();
|
tok->deleteThis();
|
||||||
|
|
||||||
// Use this special template in the code..
|
// Use this special template in the code..
|
||||||
while (nullptr != (tok2 = const_cast<Token *>(Token::findsimplematch(tok2, pattern.c_str())))) {
|
while (nullptr != (tok2 = const_cast<Token *>(Token::findsimplematch(tok2, name.c_str())))) {
|
||||||
Token::eraseTokens(tok2, Token::findsimplematch(tok2, "<")->findClosingBracket()->next());
|
Token::eraseTokens(tok2, Token::findsimplematch(tok2, "<")->findClosingBracket()->next());
|
||||||
tok2->str(name);
|
tok2->str(name);
|
||||||
}
|
}
|
||||||
|
@ -1264,7 +1260,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
// New type..
|
// New type..
|
||||||
std::vector<const Token *> typesUsedInTemplateInstantiation;
|
std::vector<const Token *> typesUsedInTemplateInstantiation;
|
||||||
std::string typeForNewName;
|
std::string typeForNewName;
|
||||||
std::string templateMatchPattern(name + " < ");
|
std::string typeForPatternMatch;
|
||||||
unsigned int indentlevel = 0;
|
unsigned int indentlevel = 0;
|
||||||
for (const Token *tok3 = tok2->tokAt(2); tok3 && (indentlevel > 0 || tok3->str() != ">"); tok3 = tok3->next()) {
|
for (const Token *tok3 = tok2->tokAt(2); tok3 && (indentlevel > 0 || tok3->str() != ">"); tok3 = tok3->next()) {
|
||||||
// #2648 - unhandled parentheses => bail out
|
// #2648 - unhandled parentheses => bail out
|
||||||
|
@ -1281,13 +1277,14 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
++indentlevel;
|
++indentlevel;
|
||||||
else if (indentlevel > 0 && Token::Match(tok3, "> [,>]"))
|
else if (indentlevel > 0 && Token::Match(tok3, "> [,>]"))
|
||||||
--indentlevel;
|
--indentlevel;
|
||||||
bool constconst = tok3->str() == "const" && tok3->strAt(1) == "const";
|
|
||||||
if (!constconst) {
|
|
||||||
templateMatchPattern += tok3->str();
|
|
||||||
templateMatchPattern += ' ';
|
|
||||||
}
|
|
||||||
if (indentlevel == 0 && Token::Match(tok3->previous(), "[<,]"))
|
if (indentlevel == 0 && Token::Match(tok3->previous(), "[<,]"))
|
||||||
typesUsedInTemplateInstantiation.push_back(tok3);
|
typesUsedInTemplateInstantiation.push_back(tok3);
|
||||||
|
const bool constconst = tok3->str() == "const" && tok3->strAt(1) == "const";
|
||||||
|
if (!constconst) {
|
||||||
|
if (!typeForPatternMatch.empty())
|
||||||
|
typeForPatternMatch += ' ';
|
||||||
|
typeForPatternMatch += tok3->str();
|
||||||
|
}
|
||||||
// add additional type information
|
// add additional type information
|
||||||
if (!constconst && tok3->str() != "class") {
|
if (!constconst && tok3->str() != "class") {
|
||||||
if (tok3->isUnsigned())
|
if (tok3->isUnsigned())
|
||||||
|
@ -1296,10 +1293,12 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
typeForNewName += "signed";
|
typeForNewName += "signed";
|
||||||
if (tok3->isLong())
|
if (tok3->isLong())
|
||||||
typeForNewName += "long";
|
typeForNewName += "long";
|
||||||
|
if (!typeForNewName.empty())
|
||||||
|
typeForNewName += ' ';
|
||||||
typeForNewName += tok3->str();
|
typeForNewName += tok3->str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templateMatchPattern += ">";
|
std::string templateMatchPattern(name + " < " + typeForPatternMatch + " >");
|
||||||
|
|
||||||
if (typeForNewName.empty() || typeParametersInDeclaration.size() != typesUsedInTemplateInstantiation.size()) {
|
if (typeForNewName.empty() || typeParametersInDeclaration.size() != typesUsedInTemplateInstantiation.size()) {
|
||||||
if (printDebug && errorlogger) {
|
if (printDebug && errorlogger) {
|
||||||
|
|
|
@ -89,6 +89,7 @@ private:
|
||||||
TEST_CASE(template54); // #6587 - memory corruption upon valid code
|
TEST_CASE(template54); // #6587 - memory corruption upon valid code
|
||||||
TEST_CASE(template55); // #6604 - simplify "const const" to "const" in template instantiations
|
TEST_CASE(template55); // #6604 - simplify "const const" to "const" in template instantiations
|
||||||
TEST_CASE(template56); // #7117 - const ternary operator simplification as template parameter
|
TEST_CASE(template56); // #7117 - const ternary operator simplification as template parameter
|
||||||
|
TEST_CASE(template57); // #7891
|
||||||
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
|
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
|
||||||
TEST_CASE(template_unhandled);
|
TEST_CASE(template_unhandled);
|
||||||
TEST_CASE(template_default_parameter);
|
TEST_CASE(template_default_parameter);
|
||||||
|
@ -1022,6 +1023,14 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void template57() { // #7891
|
||||||
|
const char code[] = "template<class T> struct Test { Test(T); };\n"
|
||||||
|
"Test<unsigned long> test( 0 );";
|
||||||
|
const char exp [] = "Test < unsigned long > test ( 0 ) ; "
|
||||||
|
"struct Test < unsigned long > { Test < unsigned long > ( long ) ; } ;";
|
||||||
|
ASSERT_EQUALS(exp, tok(code));
|
||||||
|
}
|
||||||
|
|
||||||
void template_enum() {
|
void template_enum() {
|
||||||
const char code1[] = "template <class T>\n"
|
const char code1[] = "template <class T>\n"
|
||||||
"struct Unconst {\n"
|
"struct Unconst {\n"
|
||||||
|
@ -1052,8 +1061,19 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" enum {value = !type_equal<T, typename Unconst<T>::type>::value };\n"
|
" enum {value = !type_equal<T, typename Unconst<T>::type>::value };\n"
|
||||||
"};";
|
"};";
|
||||||
const char expected1[]="template < class T > struct Unconst { } ; template < class T > struct type_equal<T,T> { enum Anonymous1 { value = 1 } ; } ; template < class T > struct template_is_const { enum Anonymous2 { value = ! type_equal < T , Unconst < T > :: type > :: value } ; } ; struct type_equal<T,T> { enum Anonymous0 { value = 0 } ; } ; struct Unconst<constT*const> { } ; struct Unconst<constT&*const> { } ; struct Unconst<T*const*const> { } ; struct Unconst<T*const> { } ; struct Unconst<T*const> { } ; struct Unconst<T*const> { } ; struct Unconst<constT&><};template<T> { } ; struct Unconst<constT><};template<T> { } ;";
|
const char exp1[] = "template < class T > struct Unconst { } ; "
|
||||||
ASSERT_EQUALS(expected1, tok(code1));
|
"template < class T > struct type_equal < T , T > { enum Anonymous1 { value = 1 } ; } ; "
|
||||||
|
"template < class T > struct template_is_const { enum Anonymous2 { value = ! type_equal < T , Unconst < T > :: type > :: value } ; } ; "
|
||||||
|
"struct type_equal < T , T > { enum Anonymous0 { value = 0 } ; } ; "
|
||||||
|
"struct Unconst < const T * const > { } ; "
|
||||||
|
"struct Unconst < const T & * const > { } ; "
|
||||||
|
"struct Unconst < T * const * const > { } ; "
|
||||||
|
"struct Unconst < T * const > { } ; "
|
||||||
|
"struct Unconst < T * const > { } ; "
|
||||||
|
"struct Unconst < T * const > { } ; "
|
||||||
|
"struct Unconst < const T & > { } ; "
|
||||||
|
"struct Unconst < const T > { } ;";
|
||||||
|
ASSERT_EQUALS(exp1, tok(code1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void template_default_parameter() {
|
void template_default_parameter() {
|
||||||
|
|
Loading…
Reference in New Issue