fix overloaded template instantiation (#3160)
This commit is contained in:
parent
2a3e641645
commit
fe4964f22c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue