From fe4964f22c0598d3561c13a39634ca72efc59310 Mon Sep 17 00:00:00 2001 From: IOBYTE Date: Thu, 4 Mar 2021 02:43:22 -0500 Subject: [PATCH] fix overloaded template instantiation (#3160) --- lib/templatesimplifier.cpp | 111 ++++++++++++++++++---------------- test/testsimplifytemplate.cpp | 97 +++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 53 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index f6c865f58..d22bbb7c9 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -1929,6 +1929,9 @@ void TemplateSimplifier::expandTemplate( brackets1.pop(); } back->isTemplateArg(true); + back->isUnsigned(typetok->isUnsigned()); + back->isSigned(typetok->isSigned()); + back->isLong(typetok->isLong()); added = true; break; } @@ -2914,6 +2917,12 @@ std::string TemplateSimplifier::getNewName( --indentlevel; const bool constconst = tok3->str() == "const" && tok3->strAt(1) == "const"; if (!constconst) { + if (tok3->isUnsigned()) + typeStringsUsedInTemplateInstantiation.push_back("unsigned"); + else if (tok3->isSigned()) + typeStringsUsedInTemplateInstantiation.push_back("signed"); + if (tok3->isLong()) + typeStringsUsedInTemplateInstantiation.push_back("long"); typeStringsUsedInTemplateInstantiation.push_back(tok3->str()); } // add additional type information @@ -3177,7 +3186,38 @@ static bool matchTemplateParameters(const Token *nameTok, const std::list::const_iterator it = strings.begin(); const Token *tok = nameTok->tokAt(2); - while (tok && it != strings.end() && *it == tok->str()) { + const Token *end = nameTok->next()->findClosingBracket(); + if (!end) + return false; + while (tok && tok != end && it != strings.end()) { + if (tok->isUnsigned()) { + if (*it != "unsigned") + return false; + else { + ++it; + if (it == strings.end()) + return false; + } + } else if (tok->isSigned()) { + if (*it != "signed") + return false; + else { + ++it; + if (it == strings.end()) + return false; + } + } + if (tok->isLong()) { + if (*it != "long") + return false; + else { + ++it; + if (it == strings.end()) + return false; + } + } + if (*it != tok->str()) + return false; tok = tok->next(); ++it; } @@ -3216,68 +3256,33 @@ void TemplateSimplifier::replaceTemplateUsage( if (!matchTemplateParameters(nameTok, typeStringsUsedInTemplateInstantiation)) continue; - // match parameters - Token * tok2 = nameTok->tokAt(2); - const Token * endToken = nameTok->next()->findClosingBracket(); - unsigned int typeCountInInstantiation = tok2->str() == ">" ? 0U : 1U; - const Token *typetok = (!mTypesUsedInTemplateInstantiation.empty()) ? mTypesUsedInTemplateInstantiation[0].token() : nullptr; - unsigned int indentlevel2 = 0; // indentlevel for tokgt - while (tok2 != endToken && (indentlevel2 > 0 || tok2->str() != ">")) { - if (tok2->str() == "<" && (tok2->strAt(1) == ">" || templateParameters(tok2))) - ++indentlevel2; - else if (tok2->str() == "(") - ++indentlevel2; - else if (tok2->str() == ")") - --indentlevel2; - else if (indentlevel2 > 0 && Token::Match(tok2, "> [,>]")) - --indentlevel2; - else if (indentlevel2 == 0) { - if (tok2->str() != ",") { - if (!typetok || - tok2->isUnsigned() != typetok->isUnsigned() || - tok2->isSigned() != typetok->isSigned() || - tok2->isLong() != typetok->isLong()) { - break; - } - - typetok = typetok->next(); - } else { - if (typeCountInInstantiation < mTypesUsedInTemplateInstantiation.size()) - typetok = mTypesUsedInTemplateInstantiation[typeCountInInstantiation++].token(); - else - typetok = nullptr; - } - } - tok2 = tok2->next(); - } + Token *tok2 = nameTok->next()->findClosingBracket(); if (!tok2) break; + const Token * const nameTok1 = nameTok; + nameTok->str(newName); + // matching template usage => replace tokens.. // Foo < int > => Foo - if (tok2->str() == ">" && typeCountInInstantiation == mTypesUsedInTemplateInstantiation.size()) { - const Token * const nameTok1 = nameTok; - nameTok->str(newName); - - for (Token *tok = nameTok1->next(); tok != tok2; tok = tok->next()) { - if (tok->isName() && tok->templateSimplifierPointers() && !tok->templateSimplifierPointers()->empty()) { - std::list::iterator ti; - for (ti = mTemplateInstantiations.begin(); ti != mTemplateInstantiations.end();) { - if (ti->token() == tok) { - mTemplateInstantiations.erase(ti++); - break; - } else { - ++ti; - } + for (Token *tok = nameTok1->next(); tok != tok2; tok = tok->next()) { + if (tok->isName() && tok->templateSimplifierPointers() && !tok->templateSimplifierPointers()->empty()) { + std::list::iterator ti; + for (ti = mTemplateInstantiations.begin(); ti != mTemplateInstantiations.end();) { + if (ti->token() == tok) { + mTemplateInstantiations.erase(ti++); + break; + } else { + ++ti; } } } - // Fix crash in #9007 - if (Token::simpleMatch(nameTok->previous(), ">")) - mTemplateNamePos.erase(nameTok->previous()); - removeTokens.emplace_back(nameTok, tok2->next()); } + // Fix crash in #9007 + if (Token::simpleMatch(nameTok->previous(), ">")) + mTemplateNamePos.erase(nameTok->previous()); + removeTokens.emplace_back(nameTok, tok2->next()); nameTok = tok2; } diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index ecd4d813c..a6afd8190 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -211,6 +211,7 @@ private: TEST_CASE(template166); // #10081 hang TEST_CASE(template167); TEST_CASE(template168); + TEST_CASE(template169); TEST_CASE(template_specialization_1); // #7868 - template specialization template struct S> {..}; TEST_CASE(template_specialization_2); // #7868 - template specialization template struct S> {..}; TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template) @@ -4264,6 +4265,102 @@ private: ASSERT_EQUALS(exp, tok(code)); } + void template169() { + const char code[] = "template < typename T> struct last { T t; };\n" + "template < typename T > struct CImgList { T t; };\n" + "CImgList < last < bool > > c1;\n" + "CImgList < last < signed char > > c2;\n" + "CImgList < last < unsigned char > > c3;\n" + "CImgList < last < char > > c4;\n" + "CImgList < last < unsigned short > > c5;\n" + "CImgList < last < short > > c6;\n" + "CImgList < last < unsigned int > > c7;\n" + "CImgList < last < int > > c8;\n" + "CImgList < last < unsigned long > > c9;\n" + "CImgList < last < long > > c10;\n" + "CImgList < last < unsigned long long > > c11;\n" + "CImgList < last < long long > > c12;\n" + "CImgList < last < float > > c13;\n" + "CImgList < last < double > > c14;\n" + "CImgList < last < long double > > c15;"; + const char exp[] = "struct last ; " + "struct last ; " + "struct last ; " + "struct last ; " + "struct last ; " + "struct last ; " + "struct last ; " + "struct last ; " + "struct last ; " + "struct last ; " + "struct last ; " + "struct last ; " + "struct last ; " + "struct last ; " + "struct last ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "struct CImgList> ; " + "CImgList> c1 ; " + "CImgList> c2 ; " + "CImgList> c3 ; " + "CImgList> c4 ; " + "CImgList> c5 ; " + "CImgList> c6 ; " + "CImgList> c7 ; " + "CImgList> c8 ; " + "CImgList> c9 ; " + "CImgList> c10 ; " + "CImgList> c11 ; " + "CImgList> c12 ; " + "CImgList> c13 ; " + "CImgList> c14 ; " + "CImgList> c15 ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct CImgList> { last t ; } ; " + "struct last { bool t ; } ; " + "struct last { signed char t ; } ; " + "struct last { unsigned char t ; } ; " + "struct last { char t ; } ; " + "struct last { unsigned short t ; } ; " + "struct last { short t ; } ; " + "struct last { unsigned int t ; } ; " + "struct last { int t ; } ; " + "struct last { unsigned long t ; } ; " + "struct last { long t ; } ; " + "struct last { unsigned long long t ; } ; " + "struct last { long long t ; } ; " + "struct last { float t ; } ; " + "struct last { double t ; } ; " + "struct last { long double t ; } ;"; + ASSERT_EQUALS(exp, tok(code)); + } + void template_specialization_1() { // #7868 - template specialization template struct S> {..}; const char code[] = "template struct C {};\n" "template struct S {a};\n"