Merge pull request #868 from simartin/ticket_7891

Ticket #7891: Do not remove spaces in the internal representation for template instantiations.
This commit is contained in:
amai2012 2017-02-05 20:08:34 +01:00 committed by GitHub
commit f3f3567f16
5 changed files with 165 additions and 146 deletions

View File

@ -435,11 +435,7 @@ std::set<std::string> TemplateSimplifier::expandSpecialized(Token *tokens)
s = ostr.str();
}
// save search pattern..
const std::string pattern(s + " >");
// remove spaces to create new name
s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
const std::string name(s + " >");
expandedtemplates.insert(name);
@ -452,7 +448,7 @@ std::set<std::string> TemplateSimplifier::expandSpecialized(Token *tokens)
tok->deleteThis();
// 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());
tok2->str(name);
}
@ -1264,7 +1260,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
// New type..
std::vector<const Token *> typesUsedInTemplateInstantiation;
std::string typeForNewName;
std::string templateMatchPattern(name + " < ");
std::string typeForPatternMatch;
unsigned int indentlevel = 0;
for (const Token *tok3 = tok2->tokAt(2); tok3 && (indentlevel > 0 || tok3->str() != ">"); tok3 = tok3->next()) {
// #2648 - unhandled parentheses => bail out
@ -1281,13 +1277,14 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
++indentlevel;
else if (indentlevel > 0 && Token::Match(tok3, "> [,>]"))
--indentlevel;
bool constconst = tok3->str() == "const" && tok3->strAt(1) == "const";
if (!constconst) {
templateMatchPattern += tok3->str();
templateMatchPattern += ' ';
}
if (indentlevel == 0 && Token::Match(tok3->previous(), "[<,]"))
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
if (!constconst && tok3->str() != "class") {
if (tok3->isUnsigned())
@ -1296,10 +1293,12 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
typeForNewName += "signed";
if (tok3->isLong())
typeForNewName += "long";
if (!typeForNewName.empty())
typeForNewName += ' ';
typeForNewName += tok3->str();
}
}
templateMatchPattern += ">";
std::string templateMatchPattern(name + " < " + typeForPatternMatch + " >");
if (typeForNewName.empty() || typeParametersInDeclaration.size() != typesUsedInTemplateInstantiation.size()) {
if (printDebug && errorlogger) {

View File

@ -89,6 +89,7 @@ private:
TEST_CASE(template54); // #6587 - memory corruption upon valid code
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(template57); // #7891
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
TEST_CASE(template_unhandled);
TEST_CASE(template_default_parameter);
@ -1022,6 +1023,14 @@ private:
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() {
const char code1[] = "template <class T>\n"
"struct Unconst {\n"
@ -1052,8 +1061,19 @@ private:
"{\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> { } ;";
ASSERT_EQUALS(expected1, tok(code1));
const char exp1[] = "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 < 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() {