Skip to content

Commit fe4964f

Browse files
authored
fix overloaded template instantiation (#3160)
1 parent 2a3e641 commit fe4964f

2 files changed

Lines changed: 155 additions & 53 deletions

File tree

lib/templatesimplifier.cpp

Lines changed: 58 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,6 +1929,9 @@ void TemplateSimplifier::expandTemplate(
19291929
brackets1.pop();
19301930
}
19311931
back->isTemplateArg(true);
1932+
back->isUnsigned(typetok->isUnsigned());
1933+
back->isSigned(typetok->isSigned());
1934+
back->isLong(typetok->isLong());
19321935
added = true;
19331936
break;
19341937
}
@@ -2914,6 +2917,12 @@ std::string TemplateSimplifier::getNewName(
29142917
--indentlevel;
29152918
const bool constconst = tok3->str() == "const" && tok3->strAt(1) == "const";
29162919
if (!constconst) {
2920+
if (tok3->isUnsigned())
2921+
typeStringsUsedInTemplateInstantiation.push_back("unsigned");
2922+
else if (tok3->isSigned())
2923+
typeStringsUsedInTemplateInstantiation.push_back("signed");
2924+
if (tok3->isLong())
2925+
typeStringsUsedInTemplateInstantiation.push_back("long");
29172926
typeStringsUsedInTemplateInstantiation.push_back(tok3->str());
29182927
}
29192928
// add additional type information
@@ -3177,7 +3186,38 @@ static bool matchTemplateParameters(const Token *nameTok, const std::list<std::s
31773186
{
31783187
std::list<std::string>::const_iterator it = strings.begin();
31793188
const Token *tok = nameTok->tokAt(2);
3180-
while (tok && it != strings.end() && *it == tok->str()) {
3189+
const Token *end = nameTok->next()->findClosingBracket();
3190+
if (!end)
3191+
return false;
3192+
while (tok && tok != end && it != strings.end()) {
3193+
if (tok->isUnsigned()) {
3194+
if (*it != "unsigned")
3195+
return false;
3196+
else {
3197+
++it;
3198+
if (it == strings.end())
3199+
return false;
3200+
}
3201+
} else if (tok->isSigned()) {
3202+
if (*it != "signed")
3203+
return false;
3204+
else {
3205+
++it;
3206+
if (it == strings.end())
3207+
return false;
3208+
}
3209+
}
3210+
if (tok->isLong()) {
3211+
if (*it != "long")
3212+
return false;
3213+
else {
3214+
++it;
3215+
if (it == strings.end())
3216+
return false;
3217+
}
3218+
}
3219+
if (*it != tok->str())
3220+
return false;
31813221
tok = tok->next();
31823222
++it;
31833223
}
@@ -3216,68 +3256,33 @@ void TemplateSimplifier::replaceTemplateUsage(
32163256
if (!matchTemplateParameters(nameTok, typeStringsUsedInTemplateInstantiation))
32173257
continue;
32183258

3219-
// match parameters
3220-
Token * tok2 = nameTok->tokAt(2);
3221-
const Token * endToken = nameTok->next()->findClosingBracket();
3222-
unsigned int typeCountInInstantiation = tok2->str() == ">" ? 0U : 1U;
3223-
const Token *typetok = (!mTypesUsedInTemplateInstantiation.empty()) ? mTypesUsedInTemplateInstantiation[0].token() : nullptr;
3224-
unsigned int indentlevel2 = 0; // indentlevel for tokgt
3225-
while (tok2 != endToken && (indentlevel2 > 0 || tok2->str() != ">")) {
3226-
if (tok2->str() == "<" && (tok2->strAt(1) == ">" || templateParameters(tok2)))
3227-
++indentlevel2;
3228-
else if (tok2->str() == "(")
3229-
++indentlevel2;
3230-
else if (tok2->str() == ")")
3231-
--indentlevel2;
3232-
else if (indentlevel2 > 0 && Token::Match(tok2, "> [,>]"))
3233-
--indentlevel2;
3234-
else if (indentlevel2 == 0) {
3235-
if (tok2->str() != ",") {
3236-
if (!typetok ||
3237-
tok2->isUnsigned() != typetok->isUnsigned() ||
3238-
tok2->isSigned() != typetok->isSigned() ||
3239-
tok2->isLong() != typetok->isLong()) {
3240-
break;
3241-
}
3242-
3243-
typetok = typetok->next();
3244-
} else {
3245-
if (typeCountInInstantiation < mTypesUsedInTemplateInstantiation.size())
3246-
typetok = mTypesUsedInTemplateInstantiation[typeCountInInstantiation++].token();
3247-
else
3248-
typetok = nullptr;
3249-
}
3250-
}
3251-
tok2 = tok2->next();
3252-
}
3259+
Token *tok2 = nameTok->next()->findClosingBracket();
32533260

32543261
if (!tok2)
32553262
break;
32563263

3264+
const Token * const nameTok1 = nameTok;
3265+
nameTok->str(newName);
3266+
32573267
// matching template usage => replace tokens..
32583268
// Foo < int > => Foo<int>
3259-
if (tok2->str() == ">" && typeCountInInstantiation == mTypesUsedInTemplateInstantiation.size()) {
3260-
const Token * const nameTok1 = nameTok;
3261-
nameTok->str(newName);
3262-
3263-
for (Token *tok = nameTok1->next(); tok != tok2; tok = tok->next()) {
3264-
if (tok->isName() && tok->templateSimplifierPointers() && !tok->templateSimplifierPointers()->empty()) {
3265-
std::list<TokenAndName>::iterator ti;
3266-
for (ti = mTemplateInstantiations.begin(); ti != mTemplateInstantiations.end();) {
3267-
if (ti->token() == tok) {
3268-
mTemplateInstantiations.erase(ti++);
3269-
break;
3270-
} else {
3271-
++ti;
3272-
}
3269+
for (Token *tok = nameTok1->next(); tok != tok2; tok = tok->next()) {
3270+
if (tok->isName() && tok->templateSimplifierPointers() && !tok->templateSimplifierPointers()->empty()) {
3271+
std::list<TokenAndName>::iterator ti;
3272+
for (ti = mTemplateInstantiations.begin(); ti != mTemplateInstantiations.end();) {
3273+
if (ti->token() == tok) {
3274+
mTemplateInstantiations.erase(ti++);
3275+
break;
3276+
} else {
3277+
++ti;
32733278
}
32743279
}
32753280
}
3276-
// Fix crash in #9007
3277-
if (Token::simpleMatch(nameTok->previous(), ">"))
3278-
mTemplateNamePos.erase(nameTok->previous());
3279-
removeTokens.emplace_back(nameTok, tok2->next());
32803281
}
3282+
// Fix crash in #9007
3283+
if (Token::simpleMatch(nameTok->previous(), ">"))
3284+
mTemplateNamePos.erase(nameTok->previous());
3285+
removeTokens.emplace_back(nameTok, tok2->next());
32813286

32823287
nameTok = tok2;
32833288
}

test/testsimplifytemplate.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ class TestSimplifyTemplate : public TestFixture {
211211
TEST_CASE(template166); // #10081 hang
212212
TEST_CASE(template167);
213213
TEST_CASE(template168);
214+
TEST_CASE(template169);
214215
TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
215216
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
216217
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
@@ -4264,6 +4265,102 @@ class TestSimplifyTemplate : public TestFixture {
42644265
ASSERT_EQUALS(exp, tok(code));
42654266
}
42664267

4268+
void template169() {
4269+
const char code[] = "template < typename T> struct last { T t; };\n"
4270+
"template < typename T > struct CImgList { T t; };\n"
4271+
"CImgList < last < bool > > c1;\n"
4272+
"CImgList < last < signed char > > c2;\n"
4273+
"CImgList < last < unsigned char > > c3;\n"
4274+
"CImgList < last < char > > c4;\n"
4275+
"CImgList < last < unsigned short > > c5;\n"
4276+
"CImgList < last < short > > c6;\n"
4277+
"CImgList < last < unsigned int > > c7;\n"
4278+
"CImgList < last < int > > c8;\n"
4279+
"CImgList < last < unsigned long > > c9;\n"
4280+
"CImgList < last < long > > c10;\n"
4281+
"CImgList < last < unsigned long long > > c11;\n"
4282+
"CImgList < last < long long > > c12;\n"
4283+
"CImgList < last < float > > c13;\n"
4284+
"CImgList < last < double > > c14;\n"
4285+
"CImgList < last < long double > > c15;";
4286+
const char exp[] = "struct last<bool> ; "
4287+
"struct last<signedchar> ; "
4288+
"struct last<unsignedchar> ; "
4289+
"struct last<char> ; "
4290+
"struct last<unsignedshort> ; "
4291+
"struct last<short> ; "
4292+
"struct last<unsignedint> ; "
4293+
"struct last<int> ; "
4294+
"struct last<unsignedlong> ; "
4295+
"struct last<long> ; "
4296+
"struct last<unsignedlonglong> ; "
4297+
"struct last<longlong> ; "
4298+
"struct last<float> ; "
4299+
"struct last<double> ; "
4300+
"struct last<longdouble> ; "
4301+
"struct CImgList<last<bool>> ; "
4302+
"struct CImgList<last<signedchar>> ; "
4303+
"struct CImgList<last<unsignedchar>> ; "
4304+
"struct CImgList<last<char>> ; "
4305+
"struct CImgList<last<unsignedshort>> ; "
4306+
"struct CImgList<last<short>> ; "
4307+
"struct CImgList<last<unsignedint>> ; "
4308+
"struct CImgList<last<int>> ; "
4309+
"struct CImgList<last<unsignedlong>> ; "
4310+
"struct CImgList<last<long>> ; "
4311+
"struct CImgList<last<unsignedlonglong>> ; "
4312+
"struct CImgList<last<longlong>> ; "
4313+
"struct CImgList<last<float>> ; "
4314+
"struct CImgList<last<double>> ; "
4315+
"struct CImgList<last<longdouble>> ; "
4316+
"CImgList<last<bool>> c1 ; "
4317+
"CImgList<last<signedchar>> c2 ; "
4318+
"CImgList<last<unsignedchar>> c3 ; "
4319+
"CImgList<last<char>> c4 ; "
4320+
"CImgList<last<unsignedshort>> c5 ; "
4321+
"CImgList<last<short>> c6 ; "
4322+
"CImgList<last<unsignedint>> c7 ; "
4323+
"CImgList<last<int>> c8 ; "
4324+
"CImgList<last<unsignedlong>> c9 ; "
4325+
"CImgList<last<long>> c10 ; "
4326+
"CImgList<last<unsignedlonglong>> c11 ; "
4327+
"CImgList<last<longlong>> c12 ; "
4328+
"CImgList<last<float>> c13 ; "
4329+
"CImgList<last<double>> c14 ; "
4330+
"CImgList<last<longdouble>> c15 ; "
4331+
"struct CImgList<last<bool>> { last<bool> t ; } ; "
4332+
"struct CImgList<last<signedchar>> { last<signedchar> t ; } ; "
4333+
"struct CImgList<last<unsignedchar>> { last<unsignedchar> t ; } ; "
4334+
"struct CImgList<last<char>> { last<char> t ; } ; "
4335+
"struct CImgList<last<unsignedshort>> { last<unsignedshort> t ; } ; "
4336+
"struct CImgList<last<short>> { last<short> t ; } ; "
4337+
"struct CImgList<last<unsignedint>> { last<unsignedint> t ; } ; "
4338+
"struct CImgList<last<int>> { last<int> t ; } ; "
4339+
"struct CImgList<last<unsignedlong>> { last<unsignedlong> t ; } ; "
4340+
"struct CImgList<last<long>> { last<long> t ; } ; "
4341+
"struct CImgList<last<unsignedlonglong>> { last<unsignedlonglong> t ; } ; "
4342+
"struct CImgList<last<longlong>> { last<longlong> t ; } ; "
4343+
"struct CImgList<last<float>> { last<float> t ; } ; "
4344+
"struct CImgList<last<double>> { last<double> t ; } ; "
4345+
"struct CImgList<last<longdouble>> { last<longdouble> t ; } ; "
4346+
"struct last<bool> { bool t ; } ; "
4347+
"struct last<signedchar> { signed char t ; } ; "
4348+
"struct last<unsignedchar> { unsigned char t ; } ; "
4349+
"struct last<char> { char t ; } ; "
4350+
"struct last<unsignedshort> { unsigned short t ; } ; "
4351+
"struct last<short> { short t ; } ; "
4352+
"struct last<unsignedint> { unsigned int t ; } ; "
4353+
"struct last<int> { int t ; } ; "
4354+
"struct last<unsignedlong> { unsigned long t ; } ; "
4355+
"struct last<long> { long t ; } ; "
4356+
"struct last<unsignedlonglong> { unsigned long long t ; } ; "
4357+
"struct last<longlong> { long long t ; } ; "
4358+
"struct last<float> { float t ; } ; "
4359+
"struct last<double> { double t ; } ; "
4360+
"struct last<longdouble> { long double t ; } ;";
4361+
ASSERT_EQUALS(exp, tok(code));
4362+
}
4363+
42674364
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
42684365
const char code[] = "template <typename T> struct C {};\n"
42694366
"template <typename T> struct S {a};\n"

0 commit comments

Comments
 (0)