From 1eb2df34adcb39a402d3ee668f295284e081f41b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 23 Dec 2017 22:11:30 +0100 Subject: [PATCH] Revert improved scope handling in TemplateSimplifier --- lib/templatesimplifier.cpp | 293 +++++++++++++--------------------- lib/templatesimplifier.h | 41 ++--- test/testsimplifytemplate.cpp | 65 +------- 3 files changed, 134 insertions(+), 265 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 84dd2f20f..472c125c0 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -31,6 +31,38 @@ #include #include +#ifdef GDB_HELPERS + +static void printlist(const std::list &list) +{ + for (std::list::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 &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) { bool goback = false; @@ -423,54 +455,14 @@ std::set TemplateSimplifier::expandSpecialized(Token *tokens) return expandedtemplates; } -/// 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 &scopeInfo) +std::list TemplateSimplifier::getTemplateDeclarations(Token *tokens, bool &codeWithTemplates) { - std::string ret; - for (std::list::const_iterator it = scopeInfo.begin(); it != scopeInfo.end(); ++it) - ret += (ret.empty() ? "" : " :: ") + (it->name); - return ret; -} -static std::string getFullName(const std::list &scopeInfo, const std::string &name) -{ - const std::string &scopeName = getScopeName(scopeInfo); - return scopeName + (scopeName.empty() ? "" : " :: ") + name; -} - -static void setScopeInfo(const Token *tok, std::list *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::getTemplateDeclarations(Token *tokens, bool &codeWithTemplates) -{ - std::list scopeInfo; - std::list declarations; + std::list templates; for (Token *tok = tokens; tok; tok = tok->next()) { - setScopeInfo(tok, &scopeInfo); + // TODO: handle namespaces. Right now we don't instantiate templates that are defined in namespaces. + if (Token::Match(tok, "namespace %type% {")) + tok = tok->linkAt(2); + if (Token::simpleMatch(tok, "template <")) { // Some syntax checks, see #6865 if (!tok->tokAt(2)) @@ -480,35 +472,36 @@ std::list TemplateSimplifier::getTemplateDecla syntaxError(tok->next()); codeWithTemplates = true; Token *parmEnd = tok->next()->findClosingBracket(); + int indentlevel = 0; for (const Token *tok2 = parmEnd; tok2; tok2 = tok2->next()) { if (tok2->str() == "(") - tok2 = tok2->link(); + ++indentlevel; else if (tok2->str() == ")") - break; + --indentlevel; + + if (indentlevel) // In an argument list; move to the next token + continue; + // Just a declaration => ignore this - else if (tok2->str() == ";") + if (tok2->str() == ";") break; // Implementation => add to "templates" - else if (tok2->str() == "{") { - int namepos = getTemplateNamePosition(parmEnd); - if (namepos > 0) - declarations.push_back(TokenAndName(tok, getFullName(scopeInfo, parmEnd->strAt(namepos)))); + if (tok2->str() == "{") { + templates.push_back(tok); break; } } } } - return declarations; + return templates; } -std::list TemplateSimplifier::getTemplateInstantiations(Token *tokens) +std::list TemplateSimplifier::getTemplateInstantiations(Token *tokens) { - std::list instantiations; - std::list scopeList; + std::list used; for (Token *tok = tokens; tok; tok = tok->next()) { - setScopeInfo(tok, &scopeList); // template definition.. skip it if (Token::simpleMatch(tok, "template <")) { tok = tok->next()->findClosingBracket(); @@ -520,45 +513,36 @@ std::list TemplateSimplifier::getTemplateInsta const Token *tok2 = Token::findmatch(tok, "{|;"); if (tok2 && tok2->str() == "{") tok = tok2->link(); - } else if (Token::Match(tok->previous(), "[({};=] %name% ::|<") || - Token::Match(tok->previous(), "%type% %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; + } else if (Token::Match(tok->previous(), "[({};=] %name% <") || + Token::Match(tok->previous(), "%type% %name% <") || + Token::Match(tok->tokAt(-2), "[,:] private|protected|public %name% <")) { // Add inner template instantiations first => go to the ">" // and then parse backwards, adding all seen instantiations const Token *tok2 = tok->next()->findClosingBracket(); // parse backwards and add template instantiations - // TODO for (; tok2 && tok2 != tok; tok2 = tok2->previous()) { if (Token::Match(tok2, ", %name% <") && TemplateSimplifier::templateParameters(tok2->tokAt(2))) { - instantiations.push_back(TokenAndName(tok2->next(),getFullName(scopeList, tok2->strAt(1)))); + used.push_back(tok2->next()); } } // Add outer template.. if (TemplateSimplifier::templateParameters(tok->next())) - instantiations.push_back(TokenAndName(tok, scopeName + (scopeName.empty()?"":" :: ") + tok->str())); + used.push_back(tok); } } - return instantiations; + return used; } -void TemplateSimplifier::useDefaultArgumentValues(const std::list &templates, - std::list * const templateInstantiations) +void TemplateSimplifier::useDefaultArgumentValues(const std::list &templates, + std::list * const templateInstantiations) { - for (std::list::const_iterator iter1 = templates.begin(); iter1 != templates.end(); ++iter1) { + for (std::list::const_iterator iter1 = templates.begin(); iter1 != templates.end(); ++iter1) { // template parameters with default value has syntax such as: // x = y // this list will contain all the '=' tokens for such arguments @@ -576,7 +560,7 @@ void TemplateSimplifier::useDefaultArgumentValues(const std::list std::string classname; // Scan template declaration.. - for (Token *tok = iter1->token; tok; tok = tok->next()) { + for (Token *tok = *iter1; tok; tok = tok->next()) { if (Token::simpleMatch(tok, "template < >")) { // Ticket #5762: Skip specialization tokens tok = tok->tokAt(2); if (0 == templateParmDepth) @@ -621,8 +605,8 @@ void TemplateSimplifier::useDefaultArgumentValues(const std::list continue; // iterate through all template instantiations - for (std::list::const_iterator iter2 = templateInstantiations->begin(); iter2 != templateInstantiations->end(); ++iter2) { - Token *tok = iter2->token; + for (std::list::const_iterator iter2 = templateInstantiations->begin(); iter2 != templateInstantiations->end(); ++iter2) { + Token *tok = *iter2; if (!Token::simpleMatch(tok, (classname + " <").c_str())) continue; @@ -675,11 +659,9 @@ void TemplateSimplifier::useDefaultArgumentValues(const std::list if (Token::Match(tok2, "(|{|[")) tok2 = tok2->link(); else if (Token::Match(tok2, "%type% <") && templateParameters(tok2->next())) { - std::list::iterator ti; - for (ti = templateInstantiations->begin(); ti != templateInstantiations->end(); ++ti) { - if (ti->token == tok2) - break; - } + std::list::iterator ti = std::find(templateInstantiations->begin(), + templateInstantiations->end(), + tok2); if (ti != templateInstantiations->end()) templateInstantiations->erase(ti); ++indentlevel; @@ -701,10 +683,10 @@ void TemplateSimplifier::useDefaultArgumentValues(const std::list } } -bool TemplateSimplifier::instantiateMatch(const Token *instance, const std::size_t numberOfArguments, const char patternAfter[]) +bool TemplateSimplifier::instantiateMatch(const Token *instance, const std::string &name, const std::size_t numberOfArguments, const char patternAfter[]) { -// if (!Token::simpleMatch(instance, (name + " <").c_str())) -// return false; + if (!Token::simpleMatch(instance, (name + " <").c_str())) + return false; if (numberOfArguments != TemplateSimplifier::templateParameters(instance->next())) return false; @@ -784,42 +766,39 @@ int TemplateSimplifier::getTemplateNamePosition(const Token *tok) void TemplateSimplifier::expandTemplate( TokenList& tokenlist, - const Token *templateDeclarationToken, - const std::string &fullName, + const Token *tok, + const std::string &name, const std::vector &typeParametersInDeclaration, const std::string &newName, const std::vector &typesUsedInTemplateInstantiation, - std::list &templateInstantiations) + std::list &templateInstantiations) { - std::list scopeInfo; - bool inTemplateDefinition = false; + bool inTemplateDefinition=false; + std::vector localTypeParametersInDeclaration; for (const Token *tok3 = tokenlist.front(); tok3; tok3 = tok3 ? tok3->next() : nullptr) { - setScopeInfo(const_cast(tok3), &scopeInfo); if (tok3->str()=="template") { if (tok3->next() && tok3->next()->str()=="<") { - std::vector localTypeParametersInDeclaration; TemplateParametersInDeclaration(tok3->tokAt(2), localTypeParametersInDeclaration); if (localTypeParametersInDeclaration.size() != typeParametersInDeclaration.size()) inTemplateDefinition = false; // Partial specialization else inTemplateDefinition = true; - } else { + } else inTemplateDefinition = false; // Only template instantiation - } } - if (Token::Match(tok3, "(|[")) + if (Token::Match(tok3, "{|(|[")) tok3 = tok3->link(); + else if (Token::simpleMatch(tok3, "namespace {")) + tok3 = tok3->tokAt(2); // Start of template.. - if (tok3 == templateDeclarationToken) { + if (tok3 == tok) { tok3 = tok3->next(); } // member function implemented outside class definition else if (inTemplateDefinition && - Token::Match(tok3, "%name% <") && - fullName == getFullName(scopeInfo, tok3->str()) && - TemplateSimplifier::instantiateMatch(tok3, typeParametersInDeclaration.size(), ":: ~| %name% (")) { + TemplateSimplifier::instantiateMatch(tok3, name, typeParametersInDeclaration.size(), ":: ~| %name% (")) { tokenlist.addtoken(newName, tok3->linenr(), tok3->fileIndex()); while (tok3 && tok3->str() != "::") tok3 = tok3->next(); @@ -832,9 +811,6 @@ void TemplateSimplifier::expandTemplate( int indentlevel = 0; std::stack 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()) { if (tok3->isName()) { // search for this token in the type vector @@ -863,7 +839,7 @@ void TemplateSimplifier::expandTemplate( } // replace name.. - if (Token::Match(tok3, (lastName + " !!<").c_str())) { + if (Token::Match(tok3, (name + " !!<").c_str())) { if (Token::Match(tok3->tokAt(-2), "> :: %name% ( )")) { ; // Ticket #7942: Replacing for out-of-line constructors generates invalid syntax } else { @@ -874,26 +850,8 @@ void TemplateSimplifier::expandTemplate( // copy tokenlist.addtoken(tok3, tok3->linenr(), tok3->fileIndex()); - if (Token::Match(tok3, "%type% <") && Token::Match(tok3->next()->findClosingBracket(), ">|>>")) { - 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))); + if (Token::Match(tok3, "%type% <") && Token::Match(tok3->next()->findClosingBracket(), ">|>> !!&")) { + templateInstantiations.push_back(tokenlist.back()); } // link() newly tokens manually @@ -917,7 +875,6 @@ void TemplateSimplifier::expandTemplate( // the "}" token should only be added if indentlevel is 1 but I add it always intentionally // if indentlevel ever becomes 0, cppcheck will write: // ### Error: Invalid number of character { - inTemplateDefinition = false; break; } --indentlevel; @@ -1269,9 +1226,9 @@ bool TemplateSimplifier::simplifyTemplateInstantiations( TokenList& tokenlist, ErrorLogger* errorlogger, const Settings *_settings, - const TokenAndName &templateDeclaration, + const Token *tok, const std::time_t maxtime, - std::list &templateInstantiations, + std::list &templateInstantiations, std::set &expandedtemplates) { // this variable is not used at the moment. The intention was to @@ -1280,7 +1237,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations( // Contains tokens such as "T" std::vector typeParametersInDeclaration; - const Token * const tok = TemplateParametersInDeclaration(templateDeclaration.token->tokAt(2), typeParametersInDeclaration); + tok = TemplateParametersInDeclaration(tok->tokAt(2), typeParametersInDeclaration); // bail out if the end of the file was reached if (!tok) @@ -1310,7 +1267,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations( bool instantiated = false; - for (std::list::const_iterator iter2 = templateInstantiations.begin(); iter2 != templateInstantiations.end(); ++iter2) { + for (std::list::const_iterator iter2 = templateInstantiations.begin(); iter2 != templateInstantiations.end(); ++iter2) { if (numberOfTemplateInstantiations != templateInstantiations.size()) { numberOfTemplateInstantiations = templateInstantiations.size(); simplifyCalculations(tokenlist.front()); @@ -1320,11 +1277,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations( break; } } - - if (iter2->name != templateDeclaration.name) - continue; - - Token * const tok2 = iter2->token; + Token * const tok2 = *iter2; if (errorlogger && !tokenlist.getFiles().empty()) errorlogger->reportProgress(tokenlist.getFiles()[0], "TemplateSimplifier::simplifyTemplateInstantiations()", tok2->progressValue()); #ifdef MAXTIME @@ -1334,13 +1287,11 @@ bool TemplateSimplifier::simplifyTemplateInstantiations( (void)maxtime; #endif assert(tokenlist.validateToken(tok2)); // that assertion fails on examples from #6021 + if (tok2->str() != name) + continue; - const Token *startToken = tok2; - while (Token::Match(startToken->tokAt(-2), "%name% :: %name%")) - startToken = startToken->tokAt(-2); - - if (Token::Match(startToken->previous(), "[;{}=]") && - !TemplateSimplifier::instantiateMatch(tok2, typeParametersInDeclaration.size(), isfunc ? "(" : "*| %name%")) + if (Token::Match(tok2->previous(), "[;{}=]") && + !TemplateSimplifier::instantiateMatch(*iter2, name, typeParametersInDeclaration.size(), isfunc ? "(" : "*| %name%")) continue; // New type.. @@ -1384,13 +1335,13 @@ bool TemplateSimplifier::simplifyTemplateInstantiations( typeForNewName += tok3->str(); } } - const std::string templateParametersMatchPattern("< " + typeForPatternMatch + " >"); + std::string templateMatchPattern(name + " < " + typeForPatternMatch + " >"); if (typeForNewName.empty() || typeParametersInDeclaration.size() != typesUsedInTemplateInstantiation.size()) { if (printDebug && errorlogger) { std::list callstack(1, tok2); errorlogger->reportErr(ErrorLogger::ErrorMessage(callstack, &tokenlist, Severity::debug, "debug", - "Failed to instantiate template \"" + iter2->name + "\". The checking continues anyway.", false)); + "Failed to instantiate template \"" + name + "\". The checking continues anyway.", false)); } if (typeForNewName.empty()) continue; @@ -1398,16 +1349,16 @@ bool TemplateSimplifier::simplifyTemplateInstantiations( } // New classname/funcname.. - const std::string newName(templateDeclaration.name + " < " + typeForNewName + " >"); + const std::string newName(name + " < " + typeForNewName + " >"); if (expandedtemplates.find(newName) == expandedtemplates.end()) { expandedtemplates.insert(newName); - TemplateSimplifier::expandTemplate(tokenlist, tok, iter2->name, typeParametersInDeclaration, newName, typesUsedInTemplateInstantiation, templateInstantiations); + TemplateSimplifier::expandTemplate(tokenlist, tok,name,typeParametersInDeclaration,newName,typesUsedInTemplateInstantiation,templateInstantiations); instantiated = true; } // Replace all these template usages.. - replaceTemplateUsage(tok2, iter2->name, templateParametersMatchPattern, newName, typesUsedInTemplateInstantiation, templateInstantiations); + replaceTemplateUsage(tok2, templateMatchPattern, newName, typesUsedInTemplateInstantiation, templateInstantiations); } // Template has been instantiated .. then remove the template declaration @@ -1416,24 +1367,14 @@ bool TemplateSimplifier::simplifyTemplateInstantiations( void TemplateSimplifier::replaceTemplateUsage(Token * const instantiationToken, - const std::string &templateName, - const std::string &templateParametersMatchPattern, + const std::string &templateMatchPattern, const std::string &newName, const std::vector &typesUsedInTemplateInstantiation, - std::list &templateInstantiations) + std::list &templateInstantiations) { - std::list scopeInfo; std::list< std::pair > removeTokens; for (Token *nameTok = instantiationToken; nameTok; nameTok = nameTok->next()) { - 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()) + if (!Token::simpleMatch(nameTok, templateMatchPattern.c_str())) continue; // match parameters @@ -1472,20 +1413,10 @@ void TemplateSimplifier::replaceTemplateUsage(Token * const instantiationToken, // matching template usage => replace tokens.. // Foo < int > => Foo 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); - for (Token *tok = nameTok1->next(); tok != tok2; tok = tok->next()) { - if (tok->isName()) { - std::list::iterator ti; - for (ti = templateInstantiations.begin(); ti != templateInstantiations.end();) { - if (ti->token == tok) - templateInstantiations.erase(ti++); - else - ++ti; - } - } + for (Token *tok = nameTok->next(); tok != tok2; tok = tok->next()) { + if (tok->isName()) + templateInstantiations.remove(tok); } removeTokens.push_back(std::pair(nameTok, tok2->next())); } @@ -1526,10 +1457,10 @@ void TemplateSimplifier::simplifyTemplates( } } - std::list templates(TemplateSimplifier::getTemplateDeclarations(tokenlist.front(), _codeWithTemplates)); + std::list templates(TemplateSimplifier::getTemplateDeclarations(tokenlist.front(), _codeWithTemplates)); // Locate possible instantiations of templates.. - std::list templateInstantiations(TemplateSimplifier::getTemplateInstantiations(tokenlist.front())); + std::list templateInstantiations(TemplateSimplifier::getTemplateInstantiations(tokenlist.front())); // No template instantiations? Then return. if (templateInstantiations.empty()) @@ -1543,8 +1474,8 @@ void TemplateSimplifier::simplifyTemplates( //while (!done) { //done = true; - std::list templates2; - for (std::list::reverse_iterator iter1 = templates.rbegin(); iter1 != templates.rend(); ++iter1) { + std::list templates2; + for (std::list::reverse_iterator iter1 = templates.rbegin(); iter1 != templates.rend(); ++iter1) { bool instantiated = TemplateSimplifier::simplifyTemplateInstantiations(tokenlist, errorlogger, _settings, @@ -1556,15 +1487,11 @@ void TemplateSimplifier::simplifyTemplates( templates2.push_back(*iter1); } - for (std::list::const_iterator it = templates2.begin(); it != templates2.end(); ++it) { - std::list::iterator it1; - for (it1 = templates.begin(); it1 != templates.end(); ++it1) { - if (it1->token == it->token) - break; - } + for (std::list::const_iterator it = templates2.begin(); it != templates2.end(); ++it) { + std::list::iterator it1 = std::find(templates.begin(), templates.end(), *it); if (it1 != templates.end()) { templates.erase(it1); - removeTemplate(it->token); + removeTemplate(*it); } } } diff --git a/lib/templatesimplifier.h b/lib/templatesimplifier.h index 169f9502b..bf2be3f97 100644 --- a/lib/templatesimplifier.h +++ b/lib/templatesimplifier.h @@ -72,43 +72,35 @@ public: */ static std::set 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 * @return list of template declarations */ - static std::list getTemplateDeclarations(Token *tokens, bool &codeWithTemplates); + static std::list getTemplateDeclarations(Token *tokens, bool &codeWithTemplates); /** * Get template instantiations * @return list of template instantiations */ - static std::list getTemplateInstantiations(Token *tokens); + static std::list getTemplateInstantiations(Token *tokens); /** * simplify template instantiations (use default argument values) * @param templates list of template declarations * @param templateInstantiations list of template instantiations */ - static void useDefaultArgumentValues(const std::list &templates, - std::list *templateInstantiations); + static void useDefaultArgumentValues(const std::list &templates, + std::list *templateInstantiations); /** * Match template declaration/instantiation * @param instance template instantiation + * @param name name of template * @param numberOfArguments number of template arguments * @param patternAfter pattern that must match the tokens after the ">" * @return match => true */ - static bool instantiateMatch(const Token *instance, const std::size_t numberOfArguments, const char patternAfter[]); + static bool instantiateMatch(const Token *instance, const std::string &name, const std::size_t numberOfArguments, const char patternAfter[]); /** * Match template declaration/instantiation @@ -120,12 +112,12 @@ public: static void expandTemplate( TokenList& tokenlist, - const Token *templateDeclarationToken, - const std::string &fullName, + const Token *tok, + const std::string &name, const std::vector &typeParametersInDeclaration, const std::string &newName, const std::vector &typesUsedInTemplateInstantiation, - std::list &templateInstantiations); + std::list &templateInstantiations); /** * @brief TemplateParametersInDeclaration @@ -146,7 +138,7 @@ public: * @param tokenlist token list * @param errorlogger error logger * @param _settings settings - * @param templateDeclaration template declaration + * @param tok token where the template declaration begins * @param maxtime time when the simplification will stop * @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. @@ -156,26 +148,24 @@ public: TokenList& tokenlist, ErrorLogger* errorlogger, const Settings *_settings, - const TokenAndName &templateDeclaration, + const Token *tok, const std::time_t maxtime, - std::list &templateInstantiations, + std::list &templateInstantiations, std::set &expandedtemplates); /** * Replace all matching template usages 'Foo < int >' => 'Foo' * @param instantiationToken Template instantiation token - * @param templateName full template name with scope info - * @param templateParametersMatchPattern template parameters, Token::simpleMatch compatible pattern + * @param templateMatchPattern Pattern compatible with Token::simpleMatch * @param newName The new type name * @param typesUsedInTemplateInstantiation template instantiation parameters * @param templateInstantiations All seen instantiations */ static void replaceTemplateUsage(Token *const instantiationToken, - const std::string &templateName, - const std::string &templateParametersMatchPattern, + const std::string &templateMatchPattern, const std::string &newName, const std::vector &typesUsedInTemplateInstantiation, - std::list &templateInstantiations); + std::list &templateInstantiations); /** * Simplify templates @@ -210,6 +200,7 @@ public: static bool simplifyCalculations(Token *_tokens); private: + /** * Remove a specific "template < ..." template class/function */ diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 42fa80785..b51f5486b 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -105,10 +105,7 @@ private: TEST_CASE(template_constructor); // #3152 - template constructor is removed TEST_CASE(syntax_error_templates_1); TEST_CASE(template_member_ptr); // Ticket #5786 - crash upon valid code - TEST_CASE(template_namespace_1); - TEST_CASE(template_namespace_2); - TEST_CASE(template_namespace_3); - TEST_CASE(template_namespace_4); + TEST_CASE(template_namespace); // Test TemplateSimplifier::templateParameters TEST_CASE(templateParameters); @@ -1381,7 +1378,7 @@ private: "};"); } - void template_namespace_1() { + void template_namespace() { // #6570 const char code[] = "namespace {\n" " template void Fred(T value) { }\n" @@ -1392,52 +1389,6 @@ private: "void Fred < int > ( int value ) { }", tok(code)); } - void template_namespace_2() { - // #8283 - const char code[] = "namespace X {\n" - " template struct S { };\n" - "}\n" - "X::S s;"; - ASSERT_EQUALS("X :: S < int > s ; " - "struct X :: S < int > { } ;", tok(code)); - } - - void template_namespace_3() { - const char code[] = "namespace test16 {\n" - " template struct foo {\n" - " static void *bar();\n" - " };\n" - " void *test() { return foo::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 A { void dostuff() {} };\n" - " struct S : public A {\n" - " void f() {\n" - " A::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[]) { Tokenizer tokenizer(&settings, this); @@ -1526,29 +1477,29 @@ private: ASSERT_EQUALS("class A < int > : public B { } ;", tok("template<> class A : public B {};")); } - unsigned int instantiateMatch(const char code[], const std::size_t numberOfArguments, const char patternAfter[]) { + unsigned int instantiateMatch(const char code[], const std::string& name, const std::size_t numberOfArguments, const char patternAfter[]) { Tokenizer tokenizer(&settings, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp", ""); - return TemplateSimplifier::instantiateMatch(tokenizer.tokens(), numberOfArguments, patternAfter); + return TemplateSimplifier::instantiateMatch(tokenizer.tokens(), name, numberOfArguments, patternAfter); } void instantiateMatch() { // Ticket #8175 ASSERT_EQUALS(false, instantiateMatch("ConvertHelper < From, To > c ;", - 2, ":: %name% (")); + "ConvertHelper", 2, ":: %name% (")); ASSERT_EQUALS(true, instantiateMatch("ConvertHelper < From, To > :: Create ( ) ;", - 2, ":: %name% (")); + "ConvertHelper", 2, ":: %name% (")); ASSERT_EQUALS(false, instantiateMatch("integral_constant < bool, sizeof ( ConvertHelper < From, To > :: Create ( ) ) > ;", - 2, ":: %name% (")); + "integral_constant", 2, ":: %name% (")); ASSERT_EQUALS(false, instantiateMatch("integral_constant < bool, sizeof ( ns :: ConvertHelper < From, To > :: Create ( ) ) > ;", - 2, ":: %name% (")); + "integral_constant", 2, ":: %name% (")); } };