Templates: Fixed scope problem

This commit is contained in:
Daniel Marjamäki 2017-12-30 09:00:19 +01:00
parent 005bb7c747
commit a8f73055ad
3 changed files with 41 additions and 9 deletions

View File

@ -493,7 +493,7 @@ std::list<TemplateSimplifier::TokenAndName> TemplateSimplifier::getTemplateDecla
else if (tok2->str() == "{") { else if (tok2->str() == "{") {
int namepos = getTemplateNamePosition(parmEnd); int namepos = getTemplateNamePosition(parmEnd);
if (namepos > 0) if (namepos > 0)
declarations.push_back(TokenAndName(tok, getFullName(scopeInfo, parmEnd->strAt(namepos)))); declarations.push_back(TokenAndName(tok, getScopeName(scopeInfo), getFullName(scopeInfo, parmEnd->strAt(namepos))));
break; break;
} }
} }
@ -502,7 +502,7 @@ std::list<TemplateSimplifier::TokenAndName> TemplateSimplifier::getTemplateDecla
} }
std::list<TemplateSimplifier::TokenAndName> TemplateSimplifier::getTemplateInstantiations(Token *tokens) std::list<TemplateSimplifier::TokenAndName> TemplateSimplifier::getTemplateInstantiations(Token *tokens, const std::list<TokenAndName> &declarations)
{ {
std::list<TokenAndName> instantiations; std::list<TokenAndName> instantiations;
std::list<ScopeInfo2> scopeList; std::list<ScopeInfo2> scopeList;
@ -541,13 +541,35 @@ std::list<TemplateSimplifier::TokenAndName> TemplateSimplifier::getTemplateInsta
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))) {
instantiations.push_back(TokenAndName(tok2->next(),getFullName(scopeList, tok2->strAt(1)))); instantiations.push_back(TokenAndName(tok2->next(), getScopeName(scopeList), getFullName(scopeList, tok2->strAt(1))));
} }
} }
// Add outer template.. // Add outer template..
if (TemplateSimplifier::templateParameters(tok->next())) if (TemplateSimplifier::templateParameters(tok->next())) {
instantiations.push_back(TokenAndName(tok, scopeName + (scopeName.empty()?"":" :: ") + tok->str())); bool done = false;
const std::string scopeName1(scopeName);
while (!done) {
const std::string fullName = scopeName + (scopeName.empty()?"":" :: ") + tok->str();
for (std::list<TokenAndName>::const_iterator it = declarations.begin(); it != declarations.end(); ++it) {
if (it->name == fullName) {
instantiations.push_back(TokenAndName(tok, getScopeName(scopeList), fullName));
done = true;
break;
}
}
if (!done) {
if (scopeName.empty()) {
instantiations.push_back(TokenAndName(tok, getScopeName(scopeList), scopeName1 + (scopeName1.empty()?"":" :: ") + tok->str()));
break;
}
const std::string::size_type pos = scopeName.rfind(" :: ");
scopeName = (pos == std::string::npos) ? std::string() : scopeName.substr(0,pos);
}
}
}
} }
} }
@ -995,7 +1017,7 @@ void TemplateSimplifier::expandTemplate(
std::string name = tok3->str(); std::string name = tok3->str();
for (const Token *prev = tok3->tokAt(-2); Token::Match(prev, "%name% ::"); prev = prev->tokAt(-2)) for (const Token *prev = tok3->tokAt(-2); Token::Match(prev, "%name% ::"); prev = prev->tokAt(-2))
name = prev->str() + " :: " + name; name = prev->str() + " :: " + name;
templateInstantiations.push_back(TokenAndName(tokenlist.back(), getFullName(scopeInfo, name))); templateInstantiations.push_back(TokenAndName(tokenlist.back(), getScopeName(scopeInfo), getFullName(scopeInfo, name)));
} }
// link() newly tokens manually // link() newly tokens manually
@ -1636,7 +1658,7 @@ void TemplateSimplifier::simplifyTemplates(
std::list<TokenAndName> 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<TokenAndName> templateInstantiations(TemplateSimplifier::getTemplateInstantiations(tokenlist.front())); std::list<TokenAndName> templateInstantiations(TemplateSimplifier::getTemplateInstantiations(tokenlist.front(), templates));
// No template instantiations? Then return. // No template instantiations? Then return.
if (templateInstantiations.empty()) if (templateInstantiations.empty())

View File

@ -76,8 +76,9 @@ public:
* Token and its full scopename * Token and its full scopename
*/ */
struct TokenAndName { struct TokenAndName {
TokenAndName(Token *tok, const std::string &scopeName) : token(tok), name(scopeName) {} TokenAndName(Token *tok, const std::string &s, const std::string &n) : token(tok), scope(s), name(n) {}
Token *token; Token *token;
std::string scope;
std::string name; std::string name;
}; };
@ -89,9 +90,11 @@ public:
/** /**
* Get template instantiations * Get template instantiations
* @param tokens start of token list
* @param declarations template declarations, so names can be matched
* @return list of template instantiations * @return list of template instantiations
*/ */
static std::list<TokenAndName> getTemplateInstantiations(Token *tokens); static std::list<TokenAndName> getTemplateInstantiations(Token *tokens, const std::list<TokenAndName> &declarations);
/** /**
* simplify template instantiations (use default argument values) * simplify template instantiations (use default argument values)

View File

@ -110,6 +110,7 @@ private:
TEST_CASE(template_namespace_2); TEST_CASE(template_namespace_2);
TEST_CASE(template_namespace_3); TEST_CASE(template_namespace_3);
TEST_CASE(template_namespace_4); TEST_CASE(template_namespace_4);
TEST_CASE(template_namespace_5);
// Test TemplateSimplifier::templateParameters // Test TemplateSimplifier::templateParameters
TEST_CASE(templateParameters); TEST_CASE(templateParameters);
@ -1455,6 +1456,12 @@ private:
"class foo::A<int> { void dostuff ( ) { } } ;", tok(code)); "class foo::A<int> { void dostuff ( ) { } } ;", tok(code));
} }
void template_namespace_5() {
const char code[] = "template<class C> struct S {};\n"
"namespace X { S<int> s; }";
ASSERT_EQUALS("namespace X { S<int> s ; } struct S<int> { } ;", tok(code));
}
unsigned int templateParameters(const char code[]) { unsigned int templateParameters(const char code[]) {
Tokenizer tokenizer(&settings, this); Tokenizer tokenizer(&settings, this);