fix overloaded template instantiation (#3160)
This commit is contained in:
parent
2a3e641645
commit
fe4964f22c
|
@ -1929,6 +1929,9 @@ void TemplateSimplifier::expandTemplate(
|
||||||
brackets1.pop();
|
brackets1.pop();
|
||||||
}
|
}
|
||||||
back->isTemplateArg(true);
|
back->isTemplateArg(true);
|
||||||
|
back->isUnsigned(typetok->isUnsigned());
|
||||||
|
back->isSigned(typetok->isSigned());
|
||||||
|
back->isLong(typetok->isLong());
|
||||||
added = true;
|
added = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2914,6 +2917,12 @@ std::string TemplateSimplifier::getNewName(
|
||||||
--indentlevel;
|
--indentlevel;
|
||||||
const bool constconst = tok3->str() == "const" && tok3->strAt(1) == "const";
|
const bool constconst = tok3->str() == "const" && tok3->strAt(1) == "const";
|
||||||
if (!constconst) {
|
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());
|
typeStringsUsedInTemplateInstantiation.push_back(tok3->str());
|
||||||
}
|
}
|
||||||
// add additional type information
|
// 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();
|
std::list<std::string>::const_iterator it = strings.begin();
|
||||||
const Token *tok = nameTok->tokAt(2);
|
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();
|
tok = tok->next();
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
@ -3216,68 +3256,33 @@ void TemplateSimplifier::replaceTemplateUsage(
|
||||||
if (!matchTemplateParameters(nameTok, typeStringsUsedInTemplateInstantiation))
|
if (!matchTemplateParameters(nameTok, typeStringsUsedInTemplateInstantiation))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// match parameters
|
Token *tok2 = nameTok->next()->findClosingBracket();
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tok2)
|
if (!tok2)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
const Token * const nameTok1 = nameTok;
|
||||||
|
nameTok->str(newName);
|
||||||
|
|
||||||
// matching template usage => replace tokens..
|
// matching template usage => replace tokens..
|
||||||
// Foo < int > => Foo<int>
|
// Foo < int > => Foo<int>
|
||||||
if (tok2->str() == ">" && typeCountInInstantiation == mTypesUsedInTemplateInstantiation.size()) {
|
for (Token *tok = nameTok1->next(); tok != tok2; tok = tok->next()) {
|
||||||
const Token * const nameTok1 = nameTok;
|
if (tok->isName() && tok->templateSimplifierPointers() && !tok->templateSimplifierPointers()->empty()) {
|
||||||
nameTok->str(newName);
|
std::list<TokenAndName>::iterator ti;
|
||||||
|
for (ti = mTemplateInstantiations.begin(); ti != mTemplateInstantiations.end();) {
|
||||||
for (Token *tok = nameTok1->next(); tok != tok2; tok = tok->next()) {
|
if (ti->token() == tok) {
|
||||||
if (tok->isName() && tok->templateSimplifierPointers() && !tok->templateSimplifierPointers()->empty()) {
|
mTemplateInstantiations.erase(ti++);
|
||||||
std::list<TokenAndName>::iterator ti;
|
break;
|
||||||
for (ti = mTemplateInstantiations.begin(); ti != mTemplateInstantiations.end();) {
|
} else {
|
||||||
if (ti->token() == tok) {
|
++ti;
|
||||||
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;
|
nameTok = tok2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,6 +211,7 @@ private:
|
||||||
TEST_CASE(template166); // #10081 hang
|
TEST_CASE(template166); // #10081 hang
|
||||||
TEST_CASE(template167);
|
TEST_CASE(template167);
|
||||||
TEST_CASE(template168);
|
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_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_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)
|
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
|
||||||
|
@ -4264,6 +4265,102 @@ private:
|
||||||
ASSERT_EQUALS(exp, tok(code));
|
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>> {..};
|
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||||
const char code[] = "template <typename T> struct C {};\n"
|
const char code[] = "template <typename T> struct C {};\n"
|
||||||
"template <typename T> struct S {a};\n"
|
"template <typename T> struct S {a};\n"
|
||||||
|
|
Loading…
Reference in New Issue