TemplateSimplifier: Fix instantiations when template parameter is a template
This commit is contained in:
parent
4a7f923fca
commit
469cb7e6df
|
@ -1352,7 +1352,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
// New type..
|
// New type..
|
||||||
std::vector<const Token *> typesUsedInTemplateInstantiation;
|
std::vector<const Token *> typesUsedInTemplateInstantiation;
|
||||||
std::string typeForNewName;
|
std::string typeForNewName;
|
||||||
std::string typeForPatternMatch;
|
std::list<std::string> typeStringsUsedInTemplateInstantiation;
|
||||||
unsigned int indentlevel = 0;
|
unsigned int indentlevel = 0;
|
||||||
for (const Token *tok3 = tok2->tokAt(2); tok3 && (indentlevel > 0 || tok3->str() != ">"); tok3 = tok3->next()) {
|
for (const Token *tok3 = tok2->tokAt(2); tok3 && (indentlevel > 0 || tok3->str() != ">"); tok3 = tok3->next()) {
|
||||||
// #2648 - unhandled parentheses => bail out
|
// #2648 - unhandled parentheses => bail out
|
||||||
|
@ -1373,9 +1373,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
typesUsedInTemplateInstantiation.push_back(tok3);
|
typesUsedInTemplateInstantiation.push_back(tok3);
|
||||||
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 (!typeForPatternMatch.empty())
|
typeStringsUsedInTemplateInstantiation.push_back(tok3->str());
|
||||||
typeForPatternMatch += ' ';
|
|
||||||
typeForPatternMatch += tok3->str();
|
|
||||||
}
|
}
|
||||||
// add additional type information
|
// add additional type information
|
||||||
if (!constconst && !Token::Match(tok3, "class|struct|enum")) {
|
if (!constconst && !Token::Match(tok3, "class|struct|enum")) {
|
||||||
|
@ -1390,7 +1388,6 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
typeForNewName += tok3->str();
|
typeForNewName += tok3->str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const std::string templateParametersMatchPattern("< " + typeForPatternMatch + " >");
|
|
||||||
|
|
||||||
if (typeForNewName.empty() || typeParametersInDeclaration.size() != typesUsedInTemplateInstantiation.size()) {
|
if (typeForNewName.empty() || typeParametersInDeclaration.size() != typesUsedInTemplateInstantiation.size()) {
|
||||||
if (printDebug && errorlogger) {
|
if (printDebug && errorlogger) {
|
||||||
|
@ -1413,17 +1410,27 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace all these template usages..
|
// Replace all these template usages..
|
||||||
replaceTemplateUsage(tok2, iter2->name, templateParametersMatchPattern, newName, typesUsedInTemplateInstantiation, templateInstantiations);
|
replaceTemplateUsage(tok2, iter2->name, typeStringsUsedInTemplateInstantiation, newName, typesUsedInTemplateInstantiation, templateInstantiations);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Template has been instantiated .. then remove the template declaration
|
// Template has been instantiated .. then remove the template declaration
|
||||||
return instantiated;
|
return instantiated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool matchTemplateParameters(const Token *nameTok, const std::list<std::string> &strings)
|
||||||
|
{
|
||||||
|
std::list<std::string>::const_iterator it = strings.begin();
|
||||||
|
const Token *tok = nameTok->tokAt(2);
|
||||||
|
while (tok && it != strings.end() && *it == tok->str()) {
|
||||||
|
tok = tok->next();
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
return it == strings.end() && tok && tok->str() == ">";
|
||||||
|
}
|
||||||
|
|
||||||
void TemplateSimplifier::replaceTemplateUsage(Token * const instantiationToken,
|
void TemplateSimplifier::replaceTemplateUsage(Token * const instantiationToken,
|
||||||
const std::string &templateName,
|
const std::string &templateName,
|
||||||
const std::string &templateParametersMatchPattern,
|
const std::list<std::string> &typeStringsUsedInTemplateInstantiation,
|
||||||
const std::string &newName,
|
const std::string &newName,
|
||||||
const std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
const std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
||||||
std::list<TokenAndName> &templateInstantiations)
|
std::list<TokenAndName> &templateInstantiations)
|
||||||
|
@ -1434,7 +1441,7 @@ void TemplateSimplifier::replaceTemplateUsage(Token * const instantiationToken,
|
||||||
setScopeInfo(nameTok, &scopeInfo);
|
setScopeInfo(nameTok, &scopeInfo);
|
||||||
if (!Token::Match(nameTok, "%name% <"))
|
if (!Token::Match(nameTok, "%name% <"))
|
||||||
continue;
|
continue;
|
||||||
if (!Token::simpleMatch(nameTok->next(), templateParametersMatchPattern.c_str()))
|
if (!matchTemplateParameters(nameTok, typeStringsUsedInTemplateInstantiation))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// FIXME Proper name matching
|
// FIXME Proper name matching
|
||||||
|
|
|
@ -118,6 +118,16 @@ public:
|
||||||
*/
|
*/
|
||||||
static int getTemplateNamePosition(const Token *tok);
|
static int getTemplateNamePosition(const Token *tok);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand a template. Create "expanded" class/function at end of tokenlist.
|
||||||
|
* @param tokenlist The tokenlist that is changed
|
||||||
|
* @param templateDeclarationToken The template declaration token for the template that will be "expanded"
|
||||||
|
* @param fullName Full name of template
|
||||||
|
* @param typeParametersInDeclaration The type parameters of the template
|
||||||
|
* @param newName New name of class/function.
|
||||||
|
* @param typesUsedInTemplateInstantiation Type parameters in instantiation
|
||||||
|
* @param templateInstantiations List of template instantiations.
|
||||||
|
*/
|
||||||
static void expandTemplate(
|
static void expandTemplate(
|
||||||
TokenList& tokenlist,
|
TokenList& tokenlist,
|
||||||
const Token *templateDeclarationToken,
|
const Token *templateDeclarationToken,
|
||||||
|
@ -165,14 +175,14 @@ public:
|
||||||
* Replace all matching template usages 'Foo < int >' => 'Foo<int>'
|
* Replace all matching template usages 'Foo < int >' => 'Foo<int>'
|
||||||
* @param instantiationToken Template instantiation token
|
* @param instantiationToken Template instantiation token
|
||||||
* @param templateName full template name with scope info
|
* @param templateName full template name with scope info
|
||||||
* @param templateParametersMatchPattern template parameters, Token::simpleMatch compatible pattern
|
* @param typeStringsUsedInTemplateInstantiation template parameters. list of token strings.
|
||||||
* @param newName The new type name
|
* @param newName The new type name
|
||||||
* @param typesUsedInTemplateInstantiation template instantiation parameters
|
* @param typesUsedInTemplateInstantiation template instantiation parameters
|
||||||
* @param templateInstantiations All seen instantiations
|
* @param templateInstantiations All seen instantiations
|
||||||
*/
|
*/
|
||||||
static void replaceTemplateUsage(Token *const instantiationToken,
|
static void replaceTemplateUsage(Token *const instantiationToken,
|
||||||
const std::string &templateName,
|
const std::string &templateName,
|
||||||
const std::string &templateParametersMatchPattern,
|
const std::list<std::string> &typeStringsUsedInTemplateInstantiation,
|
||||||
const std::string &newName,
|
const std::string &newName,
|
||||||
const std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
const std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
||||||
std::list<TokenAndName> &templateInstantiations);
|
std::list<TokenAndName> &templateInstantiations);
|
||||||
|
|
|
@ -690,7 +690,7 @@ private:
|
||||||
// #3226 - inner template
|
// #3226 - inner template
|
||||||
const char code[] = "template<class A, class B> class Fred {};\n"
|
const char code[] = "template<class A, class B> class Fred {};\n"
|
||||||
"Fred<int,Fred<int,int> > x;\n";
|
"Fred<int,Fred<int,int> > x;\n";
|
||||||
ASSERT_EQUALS("Fred < int , Fred<int,int> > x ; class Fred<int,int> { } ; class Fred<int,Fred<int,int>> { } ;", tok(code));
|
ASSERT_EQUALS("Fred<int,Fred<int,int>> x ; class Fred<int,int> { } ; class Fred<int,Fred<int,int>> { } ;", tok(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
void template30() {
|
void template30() {
|
||||||
|
@ -734,7 +734,7 @@ private:
|
||||||
"template<class T> struct C { A<B<X<T> > > ab; };\n"
|
"template<class T> struct C { A<B<X<T> > > ab; };\n"
|
||||||
"C<int> c;";
|
"C<int> c;";
|
||||||
ASSERT_EQUALS("C<int> c ; "
|
ASSERT_EQUALS("C<int> c ; "
|
||||||
"struct C<int> { A < B<X<int>> > ab ; } ; "
|
"struct C<int> { A<B<X<int>>> ab ; } ; "
|
||||||
"struct B<X<int>> { } ; " // <- redundant.. but nevermind
|
"struct B<X<int>> { } ; " // <- redundant.. but nevermind
|
||||||
"struct A<B<X<int>>> { } ;", tok(code));
|
"struct A<B<X<int>>> { } ;", tok(code));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue