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() == "{") {
int namepos = getTemplateNamePosition(parmEnd);
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;
}
}
@ -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<ScopeInfo2> scopeList;
@ -541,13 +541,35 @@ std::list<TemplateSimplifier::TokenAndName> TemplateSimplifier::getTemplateInsta
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))));
instantiations.push_back(TokenAndName(tok2->next(), getScopeName(scopeList), getFullName(scopeList, tok2->strAt(1))));
}
}
// Add outer template..
if (TemplateSimplifier::templateParameters(tok->next()))
instantiations.push_back(TokenAndName(tok, scopeName + (scopeName.empty()?"":" :: ") + tok->str()));
if (TemplateSimplifier::templateParameters(tok->next())) {
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();
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)));
templateInstantiations.push_back(TokenAndName(tokenlist.back(), getScopeName(scopeInfo), getFullName(scopeInfo, name)));
}
// link() newly tokens manually
@ -1636,7 +1658,7 @@ void TemplateSimplifier::simplifyTemplates(
std::list<TokenAndName> templates(TemplateSimplifier::getTemplateDeclarations(tokenlist.front(), _codeWithTemplates));
// 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.
if (templateInstantiations.empty())

View File

@ -76,8 +76,9 @@ public:
* Token and its full scopename
*/
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;
std::string scope;
std::string name;
};
@ -89,9 +90,11 @@ public:
/**
* Get template instantiations
* @param tokens start of token list
* @param declarations template declarations, so names can be matched
* @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)

View File

@ -110,6 +110,7 @@ private:
TEST_CASE(template_namespace_2);
TEST_CASE(template_namespace_3);
TEST_CASE(template_namespace_4);
TEST_CASE(template_namespace_5);
// Test TemplateSimplifier::templateParameters
TEST_CASE(templateParameters);
@ -1455,6 +1456,12 @@ private:
"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[]) {
Tokenizer tokenizer(&settings, this);