fix overloaded template instantiation (#3160)

This commit is contained in:
IOBYTE 2021-03-04 02:43:22 -05:00 committed by GitHub
parent 2a3e641645
commit fe4964f22c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 155 additions and 53 deletions

View File

@ -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<std::s
{
std::list<std::string>::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<int>
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<TokenAndName>::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<TokenAndName>::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;
}

View File

@ -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 <typename T> struct S<C<T>> {..};
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
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<bool> ; "
"struct last<signedchar> ; "
"struct last<unsignedchar> ; "
"struct last<char> ; "
"struct last<unsignedshort> ; "
"struct last<short> ; "
"struct last<unsignedint> ; "
"struct last<int> ; "
"struct last<unsignedlong> ; "
"struct last<long> ; "
"struct last<unsignedlonglong> ; "
"struct last<longlong> ; "
"struct last<float> ; "
"struct last<double> ; "
"struct last<longdouble> ; "
"struct CImgList<last<bool>> ; "
"struct CImgList<last<signedchar>> ; "
"struct CImgList<last<unsignedchar>> ; "
"struct CImgList<last<char>> ; "
"struct CImgList<last<unsignedshort>> ; "
"struct CImgList<last<short>> ; "
"struct CImgList<last<unsignedint>> ; "
"struct CImgList<last<int>> ; "
"struct CImgList<last<unsignedlong>> ; "
"struct CImgList<last<long>> ; "
"struct CImgList<last<unsignedlonglong>> ; "
"struct CImgList<last<longlong>> ; "
"struct CImgList<last<float>> ; "
"struct CImgList<last<double>> ; "
"struct CImgList<last<longdouble>> ; "
"CImgList<last<bool>> c1 ; "
"CImgList<last<signedchar>> c2 ; "
"CImgList<last<unsignedchar>> c3 ; "
"CImgList<last<char>> c4 ; "
"CImgList<last<unsignedshort>> c5 ; "
"CImgList<last<short>> c6 ; "
"CImgList<last<unsignedint>> c7 ; "
"CImgList<last<int>> c8 ; "
"CImgList<last<unsignedlong>> c9 ; "
"CImgList<last<long>> c10 ; "
"CImgList<last<unsignedlonglong>> c11 ; "
"CImgList<last<longlong>> c12 ; "
"CImgList<last<float>> c13 ; "
"CImgList<last<double>> c14 ; "
"CImgList<last<longdouble>> c15 ; "
"struct CImgList<last<bool>> { last<bool> t ; } ; "
"struct CImgList<last<signedchar>> { last<signedchar> t ; } ; "
"struct CImgList<last<unsignedchar>> { last<unsignedchar> t ; } ; "
"struct CImgList<last<char>> { last<char> t ; } ; "
"struct CImgList<last<unsignedshort>> { last<unsignedshort> t ; } ; "
"struct CImgList<last<short>> { last<short> t ; } ; "
"struct CImgList<last<unsignedint>> { last<unsignedint> t ; } ; "
"struct CImgList<last<int>> { last<int> t ; } ; "
"struct CImgList<last<unsignedlong>> { last<unsignedlong> t ; } ; "
"struct CImgList<last<long>> { last<long> t ; } ; "
"struct CImgList<last<unsignedlonglong>> { last<unsignedlonglong> t ; } ; "
"struct CImgList<last<longlong>> { last<longlong> t ; } ; "
"struct CImgList<last<float>> { last<float> t ; } ; "
"struct CImgList<last<double>> { last<double> t ; } ; "
"struct CImgList<last<longdouble>> { last<longdouble> t ; } ; "
"struct last<bool> { bool t ; } ; "
"struct last<signedchar> { signed char t ; } ; "
"struct last<unsignedchar> { unsigned char t ; } ; "
"struct last<char> { char t ; } ; "
"struct last<unsignedshort> { unsigned short t ; } ; "
"struct last<short> { short t ; } ; "
"struct last<unsignedint> { unsigned int t ; } ; "
"struct last<int> { int t ; } ; "
"struct last<unsignedlong> { unsigned long t ; } ; "
"struct last<long> { long t ; } ; "
"struct last<unsignedlonglong> { unsigned long long t ; } ; "
"struct last<longlong> { long long t ; } ; "
"struct last<float> { float t ; } ; "
"struct last<double> { double t ; } ; "
"struct last<longdouble> { long double t ; } ;";
ASSERT_EQUALS(exp, tok(code));
}
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
const char code[] = "template <typename T> struct C {};\n"
"template <typename T> struct S {a};\n"