TemplateSimplifier: Improved handling of scopes
This commit is contained in:
parent
5a642ac35e
commit
2c69f2b226
|
@ -31,38 +31,6 @@
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#ifdef GDB_HELPERS
|
|
||||||
|
|
||||||
static void printlist(const std::list<Token *> &list)
|
|
||||||
{
|
|
||||||
for (std::list<Token *>::const_iterator it = list.begin(); it != list.end(); ++it) {
|
|
||||||
const Token *token = *it;
|
|
||||||
std::cout << " ";
|
|
||||||
while (token && !Token::Match(token, "[{};]")) {
|
|
||||||
std::cout << " " << token->str();
|
|
||||||
token = token->next();
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void printvector(const std::vector<const Token *> &v)
|
|
||||||
{
|
|
||||||
for (std::size_t i = 0; i < v.size(); i++) {
|
|
||||||
const Token *token = v[i];
|
|
||||||
std::cout << " " << i << ":";
|
|
||||||
while (token && !Token::Match(token, "[{};]")) {
|
|
||||||
std::cout << " " << token->str();
|
|
||||||
token = token->next();
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void TemplateSimplifier::cleanupAfterSimplify(Token *tokens)
|
void TemplateSimplifier::cleanupAfterSimplify(Token *tokens)
|
||||||
{
|
{
|
||||||
bool goback = false;
|
bool goback = false;
|
||||||
|
@ -455,14 +423,54 @@ std::set<std::string> TemplateSimplifier::expandSpecialized(Token *tokens)
|
||||||
return expandedtemplates;
|
return expandedtemplates;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<Token *> TemplateSimplifier::getTemplateDeclarations(Token *tokens, bool &codeWithTemplates)
|
/// TODO: This is copy pasted from Tokenizer. We should reuse this code.
|
||||||
|
namespace {
|
||||||
|
struct ScopeInfo2 {
|
||||||
|
ScopeInfo2(const std::string &name_, const Token *classEnd_) : name(name_), classEnd(classEnd_) {}
|
||||||
|
const std::string name;
|
||||||
|
const Token * const classEnd;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static std::string getScopeName(const std::list<ScopeInfo2> &scopeInfo)
|
||||||
{
|
{
|
||||||
std::list<Token *> templates;
|
std::string ret;
|
||||||
for (Token *tok = tokens; tok; tok = tok->next()) {
|
for (std::list<ScopeInfo2>::const_iterator it = scopeInfo.begin(); it != scopeInfo.end(); ++it)
|
||||||
// TODO: handle namespaces. Right now we don't instantiate templates that are defined in namespaces.
|
ret += (ret.empty() ? "" : " :: ") + (it->name);
|
||||||
if (Token::Match(tok, "namespace %type% {"))
|
return ret;
|
||||||
tok = tok->linkAt(2);
|
}
|
||||||
|
static std::string getFullName(const std::list<ScopeInfo2> &scopeInfo, const std::string &name)
|
||||||
|
{
|
||||||
|
const std::string &scopeName = getScopeName(scopeInfo);
|
||||||
|
return scopeName + (scopeName.empty() ? "" : " :: ") + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setScopeInfo(const Token *tok, std::list<ScopeInfo2> *scopeInfo)
|
||||||
|
{
|
||||||
|
while (tok->str() == "}" && !scopeInfo->empty() && tok == scopeInfo->back().classEnd)
|
||||||
|
scopeInfo->pop_back();
|
||||||
|
if (!Token::Match(tok, "namespace|class|struct %name% {|:|::"))
|
||||||
|
return;
|
||||||
|
tok = tok->next();
|
||||||
|
std::string classname = tok->str();
|
||||||
|
while (Token::Match(tok, "%name% :: %name%")) {
|
||||||
|
tok = tok->tokAt(2);
|
||||||
|
classname += " :: " + tok->str();
|
||||||
|
}
|
||||||
|
tok = tok->next();
|
||||||
|
if (tok && tok->str() == ":") {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
if (tok && tok->str() == "{") {
|
||||||
|
scopeInfo->push_back(ScopeInfo2(classname,tok->link()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<TemplateSimplifier::TokenAndName> TemplateSimplifier::getTemplateDeclarations(Token *tokens, bool &codeWithTemplates)
|
||||||
|
{
|
||||||
|
std::list<ScopeInfo2> scopeInfo;
|
||||||
|
std::list<TokenAndName> declarations;
|
||||||
|
for (Token *tok = tokens; tok; tok = tok->next()) {
|
||||||
|
setScopeInfo(tok, &scopeInfo);
|
||||||
if (Token::simpleMatch(tok, "template <")) {
|
if (Token::simpleMatch(tok, "template <")) {
|
||||||
// Some syntax checks, see #6865
|
// Some syntax checks, see #6865
|
||||||
if (!tok->tokAt(2))
|
if (!tok->tokAt(2))
|
||||||
|
@ -472,36 +480,35 @@ std::list<Token *> TemplateSimplifier::getTemplateDeclarations(Token *tokens, bo
|
||||||
syntaxError(tok->next());
|
syntaxError(tok->next());
|
||||||
codeWithTemplates = true;
|
codeWithTemplates = true;
|
||||||
Token *parmEnd = tok->next()->findClosingBracket();
|
Token *parmEnd = tok->next()->findClosingBracket();
|
||||||
int indentlevel = 0;
|
|
||||||
for (const Token *tok2 = parmEnd; tok2; tok2 = tok2->next()) {
|
for (const Token *tok2 = parmEnd; tok2; tok2 = tok2->next()) {
|
||||||
if (tok2->str() == "(")
|
if (tok2->str() == "(")
|
||||||
++indentlevel;
|
tok2 = tok2->link();
|
||||||
else if (tok2->str() == ")")
|
else if (tok2->str() == ")")
|
||||||
--indentlevel;
|
break;
|
||||||
|
|
||||||
if (indentlevel) // In an argument list; move to the next token
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Just a declaration => ignore this
|
// Just a declaration => ignore this
|
||||||
if (tok2->str() == ";")
|
else if (tok2->str() == ";")
|
||||||
break;
|
break;
|
||||||
// Implementation => add to "templates"
|
// Implementation => add to "templates"
|
||||||
if (tok2->str() == "{") {
|
else if (tok2->str() == "{") {
|
||||||
templates.push_back(tok);
|
int namepos = getTemplateNamePosition(parmEnd);
|
||||||
|
if (namepos > 0)
|
||||||
|
declarations.push_back(TokenAndName(tok, getFullName(scopeInfo, parmEnd->strAt(namepos))));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return templates;
|
return declarations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::list<Token *> TemplateSimplifier::getTemplateInstantiations(Token *tokens)
|
std::list<TemplateSimplifier::TokenAndName> TemplateSimplifier::getTemplateInstantiations(Token *tokens)
|
||||||
{
|
{
|
||||||
std::list<Token *> used;
|
std::list<TokenAndName> instantiations;
|
||||||
|
std::list<ScopeInfo2> scopeList;
|
||||||
|
|
||||||
for (Token *tok = tokens; tok; tok = tok->next()) {
|
for (Token *tok = tokens; tok; tok = tok->next()) {
|
||||||
|
setScopeInfo(tok, &scopeList);
|
||||||
// template definition.. skip it
|
// template definition.. skip it
|
||||||
if (Token::simpleMatch(tok, "template <")) {
|
if (Token::simpleMatch(tok, "template <")) {
|
||||||
tok = tok->next()->findClosingBracket();
|
tok = tok->next()->findClosingBracket();
|
||||||
|
@ -513,36 +520,45 @@ std::list<Token *> TemplateSimplifier::getTemplateInstantiations(Token *tokens)
|
||||||
const Token *tok2 = Token::findmatch(tok, "{|;");
|
const Token *tok2 = Token::findmatch(tok, "{|;");
|
||||||
if (tok2 && tok2->str() == "{")
|
if (tok2 && tok2->str() == "{")
|
||||||
tok = tok2->link();
|
tok = tok2->link();
|
||||||
} else if (Token::Match(tok->previous(), "[({};=] %name% <") ||
|
} else if (Token::Match(tok->previous(), "[({};=] %name% ::|<") ||
|
||||||
Token::Match(tok->previous(), "%type% %name% <") ||
|
Token::Match(tok->previous(), "%type% %name% ::|<") ||
|
||||||
Token::Match(tok->tokAt(-2), "[,:] private|protected|public %name% <")) {
|
Token::Match(tok->tokAt(-2), "[,:] private|protected|public %name% ::|<")) {
|
||||||
|
|
||||||
|
std::string scopeName = getScopeName(scopeList);
|
||||||
|
while (Token::Match(tok, "%name% :: %name%")) {
|
||||||
|
scopeName += (scopeName.empty() ? "" : " :: ") + tok->str();
|
||||||
|
tok = tok->tokAt(2);
|
||||||
|
}
|
||||||
|
if (!Token::Match(tok, "%name% <"))
|
||||||
|
continue;
|
||||||
|
|
||||||
// Add inner template instantiations first => go to the ">"
|
// Add inner template instantiations first => go to the ">"
|
||||||
// and then parse backwards, adding all seen instantiations
|
// and then parse backwards, adding all seen instantiations
|
||||||
const Token *tok2 = tok->next()->findClosingBracket();
|
const Token *tok2 = tok->next()->findClosingBracket();
|
||||||
|
|
||||||
// parse backwards and add template instantiations
|
// parse backwards and add template instantiations
|
||||||
|
// TODO
|
||||||
for (; tok2 && tok2 != tok; tok2 = tok2->previous()) {
|
for (; tok2 && tok2 != tok; tok2 = tok2->previous()) {
|
||||||
if (Token::Match(tok2, ", %name% <") &&
|
if (Token::Match(tok2, ", %name% <") &&
|
||||||
TemplateSimplifier::templateParameters(tok2->tokAt(2))) {
|
TemplateSimplifier::templateParameters(tok2->tokAt(2))) {
|
||||||
used.push_back(tok2->next());
|
instantiations.push_back(TokenAndName(tok2->next(),getFullName(scopeList, tok2->strAt(1))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add outer template..
|
// Add outer template..
|
||||||
if (TemplateSimplifier::templateParameters(tok->next()))
|
if (TemplateSimplifier::templateParameters(tok->next()))
|
||||||
used.push_back(tok);
|
instantiations.push_back(TokenAndName(tok, scopeName + (scopeName.empty()?"":" :: ") + tok->str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return used;
|
return instantiations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TemplateSimplifier::useDefaultArgumentValues(const std::list<Token *> &templates,
|
void TemplateSimplifier::useDefaultArgumentValues(const std::list<TokenAndName> &templates,
|
||||||
std::list<Token *> * const templateInstantiations)
|
std::list<TokenAndName> * const templateInstantiations)
|
||||||
{
|
{
|
||||||
for (std::list<Token *>::const_iterator iter1 = templates.begin(); iter1 != templates.end(); ++iter1) {
|
for (std::list<TokenAndName>::const_iterator iter1 = templates.begin(); iter1 != templates.end(); ++iter1) {
|
||||||
// template parameters with default value has syntax such as:
|
// template parameters with default value has syntax such as:
|
||||||
// x = y
|
// x = y
|
||||||
// this list will contain all the '=' tokens for such arguments
|
// this list will contain all the '=' tokens for such arguments
|
||||||
|
@ -560,7 +576,7 @@ void TemplateSimplifier::useDefaultArgumentValues(const std::list<Token *> &temp
|
||||||
std::string classname;
|
std::string classname;
|
||||||
|
|
||||||
// Scan template declaration..
|
// Scan template declaration..
|
||||||
for (Token *tok = *iter1; tok; tok = tok->next()) {
|
for (Token *tok = iter1->token; tok; tok = tok->next()) {
|
||||||
if (Token::simpleMatch(tok, "template < >")) { // Ticket #5762: Skip specialization tokens
|
if (Token::simpleMatch(tok, "template < >")) { // Ticket #5762: Skip specialization tokens
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
if (0 == templateParmDepth)
|
if (0 == templateParmDepth)
|
||||||
|
@ -605,8 +621,8 @@ void TemplateSimplifier::useDefaultArgumentValues(const std::list<Token *> &temp
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// iterate through all template instantiations
|
// iterate through all template instantiations
|
||||||
for (std::list<Token *>::const_iterator iter2 = templateInstantiations->begin(); iter2 != templateInstantiations->end(); ++iter2) {
|
for (std::list<TokenAndName>::const_iterator iter2 = templateInstantiations->begin(); iter2 != templateInstantiations->end(); ++iter2) {
|
||||||
Token *tok = *iter2;
|
Token *tok = iter2->token;
|
||||||
|
|
||||||
if (!Token::simpleMatch(tok, (classname + " <").c_str()))
|
if (!Token::simpleMatch(tok, (classname + " <").c_str()))
|
||||||
continue;
|
continue;
|
||||||
|
@ -659,9 +675,11 @@ void TemplateSimplifier::useDefaultArgumentValues(const std::list<Token *> &temp
|
||||||
if (Token::Match(tok2, "(|{|["))
|
if (Token::Match(tok2, "(|{|["))
|
||||||
tok2 = tok2->link();
|
tok2 = tok2->link();
|
||||||
else if (Token::Match(tok2, "%type% <") && templateParameters(tok2->next())) {
|
else if (Token::Match(tok2, "%type% <") && templateParameters(tok2->next())) {
|
||||||
std::list<Token*>::iterator ti = std::find(templateInstantiations->begin(),
|
std::list<TokenAndName>::iterator ti;
|
||||||
templateInstantiations->end(),
|
for (ti = templateInstantiations->begin(); ti != templateInstantiations->end(); ++ti) {
|
||||||
tok2);
|
if (ti->token == tok2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (ti != templateInstantiations->end())
|
if (ti != templateInstantiations->end())
|
||||||
templateInstantiations->erase(ti);
|
templateInstantiations->erase(ti);
|
||||||
++indentlevel;
|
++indentlevel;
|
||||||
|
@ -683,10 +701,10 @@ void TemplateSimplifier::useDefaultArgumentValues(const std::list<Token *> &temp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TemplateSimplifier::instantiateMatch(const Token *instance, const std::string &name, const std::size_t numberOfArguments, const char patternAfter[])
|
bool TemplateSimplifier::instantiateMatch(const Token *instance, const std::size_t numberOfArguments, const char patternAfter[])
|
||||||
{
|
{
|
||||||
if (!Token::simpleMatch(instance, (name + " <").c_str()))
|
// if (!Token::simpleMatch(instance, (name + " <").c_str()))
|
||||||
return false;
|
// return false;
|
||||||
|
|
||||||
if (numberOfArguments != TemplateSimplifier::templateParameters(instance->next()))
|
if (numberOfArguments != TemplateSimplifier::templateParameters(instance->next()))
|
||||||
return false;
|
return false;
|
||||||
|
@ -766,17 +784,18 @@ int TemplateSimplifier::getTemplateNamePosition(const Token *tok)
|
||||||
|
|
||||||
void TemplateSimplifier::expandTemplate(
|
void TemplateSimplifier::expandTemplate(
|
||||||
TokenList& tokenlist,
|
TokenList& tokenlist,
|
||||||
const Token *tok,
|
const Token *templateDeclarationToken,
|
||||||
const std::string &name,
|
const std::string &fullName,
|
||||||
const std::vector<const Token *> &typeParametersInDeclaration,
|
const std::vector<const Token *> &typeParametersInDeclaration,
|
||||||
const std::string &newName,
|
const std::string &newName,
|
||||||
const std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
const std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
||||||
std::list<Token *> &templateInstantiations)
|
std::list<TemplateSimplifier::TokenAndName> &templateInstantiations)
|
||||||
{
|
{
|
||||||
bool inTemplateDefinition=false;
|
std::list<ScopeInfo2> scopeInfo;
|
||||||
|
bool inTemplateDefinition = false;
|
||||||
const Token *endOfTemplateDefinition = nullptr;
|
const Token *endOfTemplateDefinition = nullptr;
|
||||||
std::vector<const Token *> localTypeParametersInDeclaration;
|
|
||||||
for (const Token *tok3 = tokenlist.front(); tok3; tok3 = tok3 ? tok3->next() : nullptr) {
|
for (const Token *tok3 = tokenlist.front(); tok3; tok3 = tok3 ? tok3->next() : nullptr) {
|
||||||
|
setScopeInfo(const_cast<Token *>(tok3), &scopeInfo);
|
||||||
if (inTemplateDefinition) {
|
if (inTemplateDefinition) {
|
||||||
if (!endOfTemplateDefinition && tok3->str() == "{")
|
if (!endOfTemplateDefinition && tok3->str() == "{")
|
||||||
endOfTemplateDefinition = tok3->link();
|
endOfTemplateDefinition = tok3->link();
|
||||||
|
@ -786,31 +805,33 @@ void TemplateSimplifier::expandTemplate(
|
||||||
|
|
||||||
if (tok3->str()=="template") {
|
if (tok3->str()=="template") {
|
||||||
if (tok3->next() && tok3->next()->str()=="<") {
|
if (tok3->next() && tok3->next()->str()=="<") {
|
||||||
|
std::vector<const Token *> localTypeParametersInDeclaration;
|
||||||
TemplateParametersInDeclaration(tok3->tokAt(2), localTypeParametersInDeclaration);
|
TemplateParametersInDeclaration(tok3->tokAt(2), localTypeParametersInDeclaration);
|
||||||
if (localTypeParametersInDeclaration.size() != typeParametersInDeclaration.size())
|
if (localTypeParametersInDeclaration.size() != typeParametersInDeclaration.size())
|
||||||
inTemplateDefinition = false; // Partial specialization
|
inTemplateDefinition = false; // Partial specialization
|
||||||
else
|
else
|
||||||
inTemplateDefinition = true;
|
inTemplateDefinition = true;
|
||||||
} else
|
} else {
|
||||||
inTemplateDefinition = false; // Only template instantiation
|
inTemplateDefinition = false; // Only template instantiation
|
||||||
}
|
}
|
||||||
if (Token::Match(tok3, "{|(|["))
|
}
|
||||||
|
if (Token::Match(tok3, "(|["))
|
||||||
tok3 = tok3->link();
|
tok3 = tok3->link();
|
||||||
else if (Token::simpleMatch(tok3, "namespace {"))
|
|
||||||
tok3 = tok3->tokAt(2);
|
|
||||||
|
|
||||||
// Start of template..
|
// Start of template..
|
||||||
if (tok3 == tok) {
|
if (tok3 == templateDeclarationToken) {
|
||||||
tok3 = tok3->next();
|
tok3 = tok3->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// member function implemented outside class definition
|
// member function implemented outside class definition
|
||||||
else if (inTemplateDefinition &&
|
else if (inTemplateDefinition &&
|
||||||
TemplateSimplifier::instantiateMatch(tok3, name, typeParametersInDeclaration.size(), ":: ~| %name% (")) {
|
Token::Match(tok3, "%name% <") &&
|
||||||
|
fullName == getFullName(scopeInfo, tok3->str()) &&
|
||||||
|
TemplateSimplifier::instantiateMatch(tok3, typeParametersInDeclaration.size(), ":: ~| %name% (")) {
|
||||||
const Token *tok4 = tok3->next()->findClosingBracket();
|
const Token *tok4 = tok3->next()->findClosingBracket();
|
||||||
while (tok4 && tok4->str() != "(")
|
while (tok4 && tok4->str() != "(")
|
||||||
tok4 = tok4->next();
|
tok4 = tok4->next();
|
||||||
if (!Tokenizer::isFunctionHead(tok4, "{:", true))
|
if (!Tokenizer::isFunctionHead(tok4, ":{", true))
|
||||||
continue;
|
continue;
|
||||||
tokenlist.addtoken(newName, tok3->linenr(), tok3->fileIndex());
|
tokenlist.addtoken(newName, tok3->linenr(), tok3->fileIndex());
|
||||||
while (tok3 && tok3->str() != "::")
|
while (tok3 && tok3->str() != "::")
|
||||||
|
@ -824,6 +845,9 @@ void TemplateSimplifier::expandTemplate(
|
||||||
int indentlevel = 0;
|
int indentlevel = 0;
|
||||||
std::stack<Token *> brackets; // holds "(", "[" and "{" tokens
|
std::stack<Token *> brackets; // holds "(", "[" and "{" tokens
|
||||||
|
|
||||||
|
// FIXME use full name matching somehow
|
||||||
|
const std::string lastName = (fullName.find(" ") != std::string::npos) ? fullName.substr(fullName.rfind(" ")+1) : fullName;
|
||||||
|
|
||||||
for (; tok3; tok3 = tok3->next()) {
|
for (; tok3; tok3 = tok3->next()) {
|
||||||
if (tok3->isName()) {
|
if (tok3->isName()) {
|
||||||
// search for this token in the type vector
|
// search for this token in the type vector
|
||||||
|
@ -852,7 +876,7 @@ void TemplateSimplifier::expandTemplate(
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace name..
|
// replace name..
|
||||||
if (Token::Match(tok3, (name + " !!<").c_str())) {
|
if (Token::Match(tok3, (lastName + " !!<").c_str())) {
|
||||||
if (Token::Match(tok3->tokAt(-2), "> :: %name% ( )")) {
|
if (Token::Match(tok3->tokAt(-2), "> :: %name% ( )")) {
|
||||||
; // Ticket #7942: Replacing for out-of-line constructors generates invalid syntax
|
; // Ticket #7942: Replacing for out-of-line constructors generates invalid syntax
|
||||||
} else {
|
} else {
|
||||||
|
@ -863,8 +887,26 @@ void TemplateSimplifier::expandTemplate(
|
||||||
|
|
||||||
// copy
|
// copy
|
||||||
tokenlist.addtoken(tok3, tok3->linenr(), tok3->fileIndex());
|
tokenlist.addtoken(tok3, tok3->linenr(), tok3->fileIndex());
|
||||||
if (Token::Match(tok3, "%type% <") && Token::Match(tok3->next()->findClosingBracket(), ">|>> !!&")) {
|
if (Token::Match(tok3, "%type% <") && Token::Match(tok3->next()->findClosingBracket(), ">|>>")) {
|
||||||
templateInstantiations.push_back(tokenlist.back());
|
const Token *closingBracket = tok3->next()->findClosingBracket();
|
||||||
|
if (Token::simpleMatch(closingBracket->next(), "&")) {
|
||||||
|
int num = 0;
|
||||||
|
const Token *par = tok3->next();
|
||||||
|
while (num < typeParametersInDeclaration.size() && par != closingBracket) {
|
||||||
|
const std::string pattern("[<,] " + typeParametersInDeclaration[num]->str() + " [,>]");
|
||||||
|
if (!Token::Match(par, pattern.c_str()))
|
||||||
|
break;
|
||||||
|
++num;
|
||||||
|
par = par->tokAt(2);
|
||||||
|
}
|
||||||
|
if (num < typeParametersInDeclaration.size() || par != closingBracket)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name = tok3->str();
|
||||||
|
for (const Token *prev = tok3->tokAt(-2); Token::Match(prev, "%name% ::"); prev = prev->tokAt(-2))
|
||||||
|
name = prev->str() + " :: " + name;
|
||||||
|
templateInstantiations.push_back(TokenAndName(tokenlist.back(), getFullName(scopeInfo, name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// link() newly tokens manually
|
// link() newly tokens manually
|
||||||
|
@ -888,6 +930,7 @@ void TemplateSimplifier::expandTemplate(
|
||||||
// the "}" token should only be added if indentlevel is 1 but I add it always intentionally
|
// the "}" token should only be added if indentlevel is 1 but I add it always intentionally
|
||||||
// if indentlevel ever becomes 0, cppcheck will write:
|
// if indentlevel ever becomes 0, cppcheck will write:
|
||||||
// ### Error: Invalid number of character {
|
// ### Error: Invalid number of character {
|
||||||
|
inTemplateDefinition = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
--indentlevel;
|
--indentlevel;
|
||||||
|
@ -1239,9 +1282,9 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
TokenList& tokenlist,
|
TokenList& tokenlist,
|
||||||
ErrorLogger* errorlogger,
|
ErrorLogger* errorlogger,
|
||||||
const Settings *_settings,
|
const Settings *_settings,
|
||||||
const Token *tok,
|
const TokenAndName &templateDeclaration,
|
||||||
const std::time_t maxtime,
|
const std::time_t maxtime,
|
||||||
std::list<Token *> &templateInstantiations,
|
std::list<TokenAndName> &templateInstantiations,
|
||||||
std::set<std::string> &expandedtemplates)
|
std::set<std::string> &expandedtemplates)
|
||||||
{
|
{
|
||||||
// this variable is not used at the moment. The intention was to
|
// this variable is not used at the moment. The intention was to
|
||||||
|
@ -1250,7 +1293,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
|
|
||||||
// Contains tokens such as "T"
|
// Contains tokens such as "T"
|
||||||
std::vector<const Token *> typeParametersInDeclaration;
|
std::vector<const Token *> typeParametersInDeclaration;
|
||||||
tok = TemplateParametersInDeclaration(tok->tokAt(2), typeParametersInDeclaration);
|
const Token * const tok = TemplateParametersInDeclaration(templateDeclaration.token->tokAt(2), typeParametersInDeclaration);
|
||||||
|
|
||||||
// bail out if the end of the file was reached
|
// bail out if the end of the file was reached
|
||||||
if (!tok)
|
if (!tok)
|
||||||
|
@ -1280,7 +1323,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
|
|
||||||
bool instantiated = false;
|
bool instantiated = false;
|
||||||
|
|
||||||
for (std::list<Token *>::const_iterator iter2 = templateInstantiations.begin(); iter2 != templateInstantiations.end(); ++iter2) {
|
for (std::list<TokenAndName>::const_iterator iter2 = templateInstantiations.begin(); iter2 != templateInstantiations.end(); ++iter2) {
|
||||||
if (numberOfTemplateInstantiations != templateInstantiations.size()) {
|
if (numberOfTemplateInstantiations != templateInstantiations.size()) {
|
||||||
numberOfTemplateInstantiations = templateInstantiations.size();
|
numberOfTemplateInstantiations = templateInstantiations.size();
|
||||||
simplifyCalculations(tokenlist.front());
|
simplifyCalculations(tokenlist.front());
|
||||||
|
@ -1290,7 +1333,11 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Token * const tok2 = *iter2;
|
|
||||||
|
if (iter2->name != templateDeclaration.name)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Token * const tok2 = iter2->token;
|
||||||
if (errorlogger && !tokenlist.getFiles().empty())
|
if (errorlogger && !tokenlist.getFiles().empty())
|
||||||
errorlogger->reportProgress(tokenlist.getFiles()[0], "TemplateSimplifier::simplifyTemplateInstantiations()", tok2->progressValue());
|
errorlogger->reportProgress(tokenlist.getFiles()[0], "TemplateSimplifier::simplifyTemplateInstantiations()", tok2->progressValue());
|
||||||
#ifdef MAXTIME
|
#ifdef MAXTIME
|
||||||
|
@ -1300,11 +1347,13 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
(void)maxtime;
|
(void)maxtime;
|
||||||
#endif
|
#endif
|
||||||
assert(tokenlist.validateToken(tok2)); // that assertion fails on examples from #6021
|
assert(tokenlist.validateToken(tok2)); // that assertion fails on examples from #6021
|
||||||
if (tok2->str() != name)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Token::Match(tok2->previous(), "[;{}=]") &&
|
const Token *startToken = tok2;
|
||||||
!TemplateSimplifier::instantiateMatch(*iter2, name, typeParametersInDeclaration.size(), isfunc ? "(" : "*| %name%"))
|
while (Token::Match(startToken->tokAt(-2), "%name% :: %name%"))
|
||||||
|
startToken = startToken->tokAt(-2);
|
||||||
|
|
||||||
|
if (Token::Match(startToken->previous(), "[;{}=]") &&
|
||||||
|
!TemplateSimplifier::instantiateMatch(tok2, typeParametersInDeclaration.size(), isfunc ? "(" : "*| %name%"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// New type..
|
// New type..
|
||||||
|
@ -1348,13 +1397,13 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
typeForNewName += tok3->str();
|
typeForNewName += tok3->str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string templateMatchPattern(name + " < " + typeForPatternMatch + " >");
|
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) {
|
||||||
std::list<const Token *> callstack(1, tok2);
|
std::list<const Token *> callstack(1, tok2);
|
||||||
errorlogger->reportErr(ErrorLogger::ErrorMessage(callstack, &tokenlist, Severity::debug, "debug",
|
errorlogger->reportErr(ErrorLogger::ErrorMessage(callstack, &tokenlist, Severity::debug, "debug",
|
||||||
"Failed to instantiate template \"" + name + "\". The checking continues anyway.", false));
|
"Failed to instantiate template \"" + iter2->name + "\". The checking continues anyway.", false));
|
||||||
}
|
}
|
||||||
if (typeForNewName.empty())
|
if (typeForNewName.empty())
|
||||||
continue;
|
continue;
|
||||||
|
@ -1362,16 +1411,16 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
}
|
}
|
||||||
|
|
||||||
// New classname/funcname..
|
// New classname/funcname..
|
||||||
const std::string newName(name + " < " + typeForNewName + " >");
|
const std::string newName(templateDeclaration.name + " < " + typeForNewName + " >");
|
||||||
|
|
||||||
if (expandedtemplates.find(newName) == expandedtemplates.end()) {
|
if (expandedtemplates.find(newName) == expandedtemplates.end()) {
|
||||||
expandedtemplates.insert(newName);
|
expandedtemplates.insert(newName);
|
||||||
TemplateSimplifier::expandTemplate(tokenlist, tok,name,typeParametersInDeclaration,newName,typesUsedInTemplateInstantiation,templateInstantiations);
|
TemplateSimplifier::expandTemplate(tokenlist, tok, iter2->name, typeParametersInDeclaration, newName, typesUsedInTemplateInstantiation, templateInstantiations);
|
||||||
instantiated = true;
|
instantiated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace all these template usages..
|
// Replace all these template usages..
|
||||||
replaceTemplateUsage(tok2, templateMatchPattern, newName, typesUsedInTemplateInstantiation, templateInstantiations);
|
replaceTemplateUsage(tok2, iter2->name, templateParametersMatchPattern, newName, typesUsedInTemplateInstantiation, templateInstantiations);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Template has been instantiated .. then remove the template declaration
|
// Template has been instantiated .. then remove the template declaration
|
||||||
|
@ -1380,14 +1429,24 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
|
|
||||||
|
|
||||||
void TemplateSimplifier::replaceTemplateUsage(Token * const instantiationToken,
|
void TemplateSimplifier::replaceTemplateUsage(Token * const instantiationToken,
|
||||||
const std::string &templateMatchPattern,
|
const std::string &templateName,
|
||||||
|
const std::string &templateParametersMatchPattern,
|
||||||
const std::string &newName,
|
const std::string &newName,
|
||||||
const std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
const std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
||||||
std::list<Token *> &templateInstantiations)
|
std::list<TokenAndName> &templateInstantiations)
|
||||||
{
|
{
|
||||||
|
std::list<ScopeInfo2> scopeInfo;
|
||||||
std::list< std::pair<Token *, Token *> > removeTokens;
|
std::list< std::pair<Token *, Token *> > removeTokens;
|
||||||
for (Token *nameTok = instantiationToken; nameTok; nameTok = nameTok->next()) {
|
for (Token *nameTok = instantiationToken; nameTok; nameTok = nameTok->next()) {
|
||||||
if (!Token::simpleMatch(nameTok, templateMatchPattern.c_str()))
|
setScopeInfo(nameTok, &scopeInfo);
|
||||||
|
if (!Token::Match(nameTok, "%name% <"))
|
||||||
|
continue;
|
||||||
|
if (!Token::simpleMatch(nameTok->next(), templateParametersMatchPattern.c_str()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// FIXME Proper name matching
|
||||||
|
const std::string lastName(templateName.find(" ") == std::string::npos ? templateName : templateName.substr(templateName.rfind(" ") + 1));
|
||||||
|
if (lastName != nameTok->str())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// match parameters
|
// match parameters
|
||||||
|
@ -1426,10 +1485,24 @@ void TemplateSimplifier::replaceTemplateUsage(Token * const instantiationToken,
|
||||||
// matching template usage => replace tokens..
|
// matching template usage => replace tokens..
|
||||||
// Foo < int > => Foo<int>
|
// Foo < int > => Foo<int>
|
||||||
if (tok2->str() == ">" && typeCountInInstantiation == typesUsedInTemplateInstantiation.size()) {
|
if (tok2->str() == ">" && typeCountInInstantiation == typesUsedInTemplateInstantiation.size()) {
|
||||||
|
Token * const nameTok1 = nameTok;
|
||||||
|
while (Token::Match(nameTok->tokAt(-2), "%name% :: %name%"))
|
||||||
|
nameTok = nameTok->tokAt(-2);
|
||||||
nameTok->str(newName);
|
nameTok->str(newName);
|
||||||
for (Token *tok = nameTok->next(); tok != tok2; tok = tok->next()) {
|
for (std::list<TokenAndName>::iterator it = templateInstantiations.begin(); it != templateInstantiations.end(); ++it) {
|
||||||
if (tok->isName())
|
if (it->token == nameTok1)
|
||||||
templateInstantiations.remove(tok);
|
it->token = nameTok;
|
||||||
|
}
|
||||||
|
for (Token *tok = nameTok1->next(); tok != tok2; tok = tok->next()) {
|
||||||
|
if (tok->isName()) {
|
||||||
|
std::list<TokenAndName>::iterator ti;
|
||||||
|
for (ti = templateInstantiations.begin(); ti != templateInstantiations.end();) {
|
||||||
|
if (ti->token == tok)
|
||||||
|
templateInstantiations.erase(ti++);
|
||||||
|
else
|
||||||
|
++ti;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
removeTokens.push_back(std::pair<Token*,Token*>(nameTok, tok2->next()));
|
removeTokens.push_back(std::pair<Token*,Token*>(nameTok, tok2->next()));
|
||||||
}
|
}
|
||||||
|
@ -1470,10 +1543,10 @@ void TemplateSimplifier::simplifyTemplates(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<Token *> templates(TemplateSimplifier::getTemplateDeclarations(tokenlist.front(), _codeWithTemplates));
|
std::list<TokenAndName> templates(TemplateSimplifier::getTemplateDeclarations(tokenlist.front(), _codeWithTemplates));
|
||||||
|
|
||||||
// Locate possible instantiations of templates..
|
// Locate possible instantiations of templates..
|
||||||
std::list<Token *> templateInstantiations(TemplateSimplifier::getTemplateInstantiations(tokenlist.front()));
|
std::list<TokenAndName> templateInstantiations(TemplateSimplifier::getTemplateInstantiations(tokenlist.front()));
|
||||||
|
|
||||||
// No template instantiations? Then return.
|
// No template instantiations? Then return.
|
||||||
if (templateInstantiations.empty())
|
if (templateInstantiations.empty())
|
||||||
|
@ -1487,8 +1560,8 @@ void TemplateSimplifier::simplifyTemplates(
|
||||||
//while (!done)
|
//while (!done)
|
||||||
{
|
{
|
||||||
//done = true;
|
//done = true;
|
||||||
std::list<Token *> templates2;
|
std::list<TokenAndName> templates2;
|
||||||
for (std::list<Token *>::reverse_iterator iter1 = templates.rbegin(); iter1 != templates.rend(); ++iter1) {
|
for (std::list<TokenAndName>::reverse_iterator iter1 = templates.rbegin(); iter1 != templates.rend(); ++iter1) {
|
||||||
bool instantiated = TemplateSimplifier::simplifyTemplateInstantiations(tokenlist,
|
bool instantiated = TemplateSimplifier::simplifyTemplateInstantiations(tokenlist,
|
||||||
errorlogger,
|
errorlogger,
|
||||||
_settings,
|
_settings,
|
||||||
|
@ -1500,11 +1573,15 @@ void TemplateSimplifier::simplifyTemplates(
|
||||||
templates2.push_back(*iter1);
|
templates2.push_back(*iter1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::list<Token *>::const_iterator it = templates2.begin(); it != templates2.end(); ++it) {
|
for (std::list<TokenAndName>::const_iterator it = templates2.begin(); it != templates2.end(); ++it) {
|
||||||
std::list<Token *>::iterator it1 = std::find(templates.begin(), templates.end(), *it);
|
std::list<TokenAndName>::iterator it1;
|
||||||
|
for (it1 = templates.begin(); it1 != templates.end(); ++it1) {
|
||||||
|
if (it1->token == it->token)
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (it1 != templates.end()) {
|
if (it1 != templates.end()) {
|
||||||
templates.erase(it1);
|
templates.erase(it1);
|
||||||
removeTemplate(*it);
|
removeTemplate(it->token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,35 +72,43 @@ public:
|
||||||
*/
|
*/
|
||||||
static std::set<std::string> expandSpecialized(Token *tokens);
|
static std::set<std::string> expandSpecialized(Token *tokens);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token and its full scopename
|
||||||
|
*/
|
||||||
|
struct TokenAndName {
|
||||||
|
TokenAndName(Token *tok, const std::string &scopeName) : token(tok), name(scopeName) {}
|
||||||
|
Token *token;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get template declarations
|
* Get template declarations
|
||||||
* @return list of template declarations
|
* @return list of template declarations
|
||||||
*/
|
*/
|
||||||
static std::list<Token *> getTemplateDeclarations(Token *tokens, bool &codeWithTemplates);
|
static std::list<TokenAndName> getTemplateDeclarations(Token *tokens, bool &codeWithTemplates);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get template instantiations
|
* Get template instantiations
|
||||||
* @return list of template instantiations
|
* @return list of template instantiations
|
||||||
*/
|
*/
|
||||||
static std::list<Token *> getTemplateInstantiations(Token *tokens);
|
static std::list<TokenAndName> getTemplateInstantiations(Token *tokens);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* simplify template instantiations (use default argument values)
|
* simplify template instantiations (use default argument values)
|
||||||
* @param templates list of template declarations
|
* @param templates list of template declarations
|
||||||
* @param templateInstantiations list of template instantiations
|
* @param templateInstantiations list of template instantiations
|
||||||
*/
|
*/
|
||||||
static void useDefaultArgumentValues(const std::list<Token *> &templates,
|
static void useDefaultArgumentValues(const std::list<TokenAndName> &templates,
|
||||||
std::list<Token *> *templateInstantiations);
|
std::list<TokenAndName> *templateInstantiations);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Match template declaration/instantiation
|
* Match template declaration/instantiation
|
||||||
* @param instance template instantiation
|
* @param instance template instantiation
|
||||||
* @param name name of template
|
|
||||||
* @param numberOfArguments number of template arguments
|
* @param numberOfArguments number of template arguments
|
||||||
* @param patternAfter pattern that must match the tokens after the ">"
|
* @param patternAfter pattern that must match the tokens after the ">"
|
||||||
* @return match => true
|
* @return match => true
|
||||||
*/
|
*/
|
||||||
static bool instantiateMatch(const Token *instance, const std::string &name, const std::size_t numberOfArguments, const char patternAfter[]);
|
static bool instantiateMatch(const Token *instance, const std::size_t numberOfArguments, const char patternAfter[]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Match template declaration/instantiation
|
* Match template declaration/instantiation
|
||||||
|
@ -112,12 +120,12 @@ public:
|
||||||
|
|
||||||
static void expandTemplate(
|
static void expandTemplate(
|
||||||
TokenList& tokenlist,
|
TokenList& tokenlist,
|
||||||
const Token *tok,
|
const Token *templateDeclarationToken,
|
||||||
const std::string &name,
|
const std::string &fullName,
|
||||||
const std::vector<const Token *> &typeParametersInDeclaration,
|
const std::vector<const Token *> &typeParametersInDeclaration,
|
||||||
const std::string &newName,
|
const std::string &newName,
|
||||||
const std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
const std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
||||||
std::list<Token *> &templateInstantiations);
|
std::list<TokenAndName> &templateInstantiations);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief TemplateParametersInDeclaration
|
* @brief TemplateParametersInDeclaration
|
||||||
|
@ -138,7 +146,7 @@ public:
|
||||||
* @param tokenlist token list
|
* @param tokenlist token list
|
||||||
* @param errorlogger error logger
|
* @param errorlogger error logger
|
||||||
* @param _settings settings
|
* @param _settings settings
|
||||||
* @param tok token where the template declaration begins
|
* @param templateDeclaration template declaration
|
||||||
* @param maxtime time when the simplification will stop
|
* @param maxtime time when the simplification will stop
|
||||||
* @param templateInstantiations a list of template usages (not necessarily just for this template)
|
* @param templateInstantiations a list of template usages (not necessarily just for this template)
|
||||||
* @param expandedtemplates all templates that has been expanded so far. The full names are stored.
|
* @param expandedtemplates all templates that has been expanded so far. The full names are stored.
|
||||||
|
@ -148,24 +156,26 @@ public:
|
||||||
TokenList& tokenlist,
|
TokenList& tokenlist,
|
||||||
ErrorLogger* errorlogger,
|
ErrorLogger* errorlogger,
|
||||||
const Settings *_settings,
|
const Settings *_settings,
|
||||||
const Token *tok,
|
const TokenAndName &templateDeclaration,
|
||||||
const std::time_t maxtime,
|
const std::time_t maxtime,
|
||||||
std::list<Token *> &templateInstantiations,
|
std::list<TokenAndName> &templateInstantiations,
|
||||||
std::set<std::string> &expandedtemplates);
|
std::set<std::string> &expandedtemplates);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 templateMatchPattern Pattern compatible with Token::simpleMatch
|
* @param templateName full template name with scope info
|
||||||
|
* @param templateParametersMatchPattern template parameters, Token::simpleMatch compatible pattern
|
||||||
* @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 &templateMatchPattern,
|
const std::string &templateName,
|
||||||
|
const std::string &templateParametersMatchPattern,
|
||||||
const std::string &newName,
|
const std::string &newName,
|
||||||
const std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
const std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
||||||
std::list<Token *> &templateInstantiations);
|
std::list<TokenAndName> &templateInstantiations);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplify templates
|
* Simplify templates
|
||||||
|
@ -200,7 +210,6 @@ public:
|
||||||
static bool simplifyCalculations(Token *_tokens);
|
static bool simplifyCalculations(Token *_tokens);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a specific "template < ..." template class/function
|
* Remove a specific "template < ..." template class/function
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -106,7 +106,10 @@ private:
|
||||||
TEST_CASE(template_constructor); // #3152 - template constructor is removed
|
TEST_CASE(template_constructor); // #3152 - template constructor is removed
|
||||||
TEST_CASE(syntax_error_templates_1);
|
TEST_CASE(syntax_error_templates_1);
|
||||||
TEST_CASE(template_member_ptr); // Ticket #5786 - crash upon valid code
|
TEST_CASE(template_member_ptr); // Ticket #5786 - crash upon valid code
|
||||||
TEST_CASE(template_namespace);
|
TEST_CASE(template_namespace_1);
|
||||||
|
TEST_CASE(template_namespace_2);
|
||||||
|
TEST_CASE(template_namespace_3);
|
||||||
|
TEST_CASE(template_namespace_4);
|
||||||
|
|
||||||
// Test TemplateSimplifier::templateParameters
|
// Test TemplateSimplifier::templateParameters
|
||||||
TEST_CASE(templateParameters);
|
TEST_CASE(templateParameters);
|
||||||
|
@ -1392,7 +1395,7 @@ private:
|
||||||
"};");
|
"};");
|
||||||
}
|
}
|
||||||
|
|
||||||
void template_namespace() {
|
void template_namespace_1() {
|
||||||
// #6570
|
// #6570
|
||||||
const char code[] = "namespace {\n"
|
const char code[] = "namespace {\n"
|
||||||
" template<class T> void Fred(T value) { }\n"
|
" template<class T> void Fred(T value) { }\n"
|
||||||
|
@ -1403,6 +1406,52 @@ private:
|
||||||
"void Fred<int> ( int value ) { }", tok(code));
|
"void Fred<int> ( int value ) { }", tok(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void template_namespace_2() {
|
||||||
|
// #8283
|
||||||
|
const char code[] = "namespace X {\n"
|
||||||
|
" template<class T> struct S { };\n"
|
||||||
|
"}\n"
|
||||||
|
"X::S<int> s;";
|
||||||
|
ASSERT_EQUALS("X::S<int> s ; "
|
||||||
|
"struct X::S<int> { } ;", tok(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
void template_namespace_3() {
|
||||||
|
const char code[] = "namespace test16 {\n"
|
||||||
|
" template <class T> struct foo {\n"
|
||||||
|
" static void *bar();\n"
|
||||||
|
" };\n"
|
||||||
|
" void *test() { return foo<int>::bar(); }\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS("namespace test16 {"
|
||||||
|
" void * test ( ) {"
|
||||||
|
" return test16::foo<int> :: bar ( ) ;"
|
||||||
|
" } "
|
||||||
|
"} "
|
||||||
|
"struct test16::foo<int> {"
|
||||||
|
" static void * bar ( ) ; "
|
||||||
|
"} ;", tok(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
void template_namespace_4() {
|
||||||
|
const char code[] = "namespace foo {\n"
|
||||||
|
" template<class T> class A { void dostuff() {} };\n"
|
||||||
|
" struct S : public A<int> {\n"
|
||||||
|
" void f() {\n"
|
||||||
|
" A<int>::dostuff();\n"
|
||||||
|
" }\n"
|
||||||
|
" };\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS("namespace foo {"
|
||||||
|
" struct S : public foo::A<int> {"
|
||||||
|
" void f ( ) {"
|
||||||
|
" foo::A<int> :: dostuff ( ) ;"
|
||||||
|
" }"
|
||||||
|
" } ; "
|
||||||
|
"} "
|
||||||
|
"class foo::A<int> { void dostuff ( ) { } } ;", tok(code));
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int templateParameters(const char code[]) {
|
unsigned int templateParameters(const char code[]) {
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
|
||||||
|
@ -1491,29 +1540,29 @@ private:
|
||||||
ASSERT_EQUALS("class A<int> : public B { } ;", tok("template<> class A<int> : public B {};"));
|
ASSERT_EQUALS("class A<int> : public B { } ;", tok("template<> class A<int> : public B {};"));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int instantiateMatch(const char code[], const std::string& name, const std::size_t numberOfArguments, const char patternAfter[]) {
|
unsigned int instantiateMatch(const char code[], const std::size_t numberOfArguments, const char patternAfter[]) {
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize(istr, "test.cpp", "");
|
tokenizer.tokenize(istr, "test.cpp", "");
|
||||||
|
|
||||||
return TemplateSimplifier::instantiateMatch(tokenizer.tokens(), name, numberOfArguments, patternAfter);
|
return TemplateSimplifier::instantiateMatch(tokenizer.tokens(), numberOfArguments, patternAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void instantiateMatch() {
|
void instantiateMatch() {
|
||||||
// Ticket #8175
|
// Ticket #8175
|
||||||
ASSERT_EQUALS(false,
|
ASSERT_EQUALS(false,
|
||||||
instantiateMatch("ConvertHelper < From, To > c ;",
|
instantiateMatch("ConvertHelper < From, To > c ;",
|
||||||
"ConvertHelper", 2, ":: %name% ("));
|
2, ":: %name% ("));
|
||||||
ASSERT_EQUALS(true,
|
ASSERT_EQUALS(true,
|
||||||
instantiateMatch("ConvertHelper < From, To > :: Create ( ) ;",
|
instantiateMatch("ConvertHelper < From, To > :: Create ( ) ;",
|
||||||
"ConvertHelper", 2, ":: %name% ("));
|
2, ":: %name% ("));
|
||||||
ASSERT_EQUALS(false,
|
ASSERT_EQUALS(false,
|
||||||
instantiateMatch("integral_constant < bool, sizeof ( ConvertHelper < From, To > :: Create ( ) ) > ;",
|
instantiateMatch("integral_constant < bool, sizeof ( ConvertHelper < From, To > :: Create ( ) ) > ;",
|
||||||
"integral_constant", 2, ":: %name% ("));
|
2, ":: %name% ("));
|
||||||
ASSERT_EQUALS(false,
|
ASSERT_EQUALS(false,
|
||||||
instantiateMatch("integral_constant < bool, sizeof ( ns :: ConvertHelper < From, To > :: Create ( ) ) > ;",
|
instantiateMatch("integral_constant < bool, sizeof ( ns :: ConvertHelper < From, To > :: Create ( ) ) > ;",
|
||||||
"integral_constant", 2, ":: %name% ("));
|
2, ":: %name% ("));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue