* Fix a template simplifier namespace bug in #7145 * Refactor template simplifier to only call getTemplateDeclarations once per loop.
This commit is contained in:
parent
1ffcc6b730
commit
69e6e11844
|
@ -485,10 +485,10 @@ static void setScopeInfo(const Token *tok, std::list<ScopeInfo2> *scopeInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<TemplateSimplifier::TokenAndName> TemplateSimplifier::getTemplateDeclarations(bool &codeWithTemplates, bool forward)
|
bool TemplateSimplifier::getTemplateDeclarations()
|
||||||
{
|
{
|
||||||
|
bool codeWithTemplates = false;
|
||||||
std::list<ScopeInfo2> scopeInfo;
|
std::list<ScopeInfo2> scopeInfo;
|
||||||
std::list<TokenAndName> declarations;
|
|
||||||
for (Token *tok = mTokenList.front(); tok; tok = tok->next()) {
|
for (Token *tok = mTokenList.front(); tok; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "}|namespace|class|struct|union")) {
|
if (Token::Match(tok, "}|namespace|class|struct|union")) {
|
||||||
setScopeInfo(tok, &scopeInfo);
|
setScopeInfo(tok, &scopeInfo);
|
||||||
|
@ -509,27 +509,23 @@ std::list<TemplateSimplifier::TokenAndName> TemplateSimplifier::getTemplateDecla
|
||||||
tok2 = tok2->link();
|
tok2 = tok2->link();
|
||||||
else if (tok2->str() == ")")
|
else if (tok2->str() == ")")
|
||||||
break;
|
break;
|
||||||
// Just a declaration => ignore this
|
// Declaration => add to mTemplateForwardDeclarations
|
||||||
else if (tok2->str() == ";") {
|
else if (tok2->str() == ";") {
|
||||||
if (forward) {
|
const int namepos = getTemplateNamePosition(parmEnd, true);
|
||||||
const int namepos = getTemplateNamePosition(parmEnd, forward);
|
if (namepos > 0)
|
||||||
if (namepos > 0)
|
mTemplateForwardDeclarations.emplace_back(tok, getScopeName(scopeInfo), parmEnd->strAt(namepos));
|
||||||
declarations.emplace_back(tok, getScopeName(scopeInfo), parmEnd->strAt(namepos));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Implementation => add to "templates"
|
// Implementation => add to mTemplateDeclarations
|
||||||
else if (tok2->str() == "{") {
|
else if (tok2->str() == "{") {
|
||||||
if (!forward) {
|
const int namepos = getTemplateNamePosition(parmEnd, false);
|
||||||
const int namepos = getTemplateNamePosition(parmEnd, forward);
|
if (namepos > 0)
|
||||||
if (namepos > 0)
|
mTemplateDeclarations.emplace_back(tok, getScopeName(scopeInfo), parmEnd->strAt(namepos));
|
||||||
declarations.emplace_back(tok, getScopeName(scopeInfo), parmEnd->strAt(namepos));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return declarations;
|
return codeWithTemplates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -961,15 +957,33 @@ int TemplateSimplifier::getTemplateNamePosition(const Token *tok, bool forward)
|
||||||
|
|
||||||
void TemplateSimplifier::addNamespace(const TokenAndName &templateDeclaration, const Token *tok)
|
void TemplateSimplifier::addNamespace(const TokenAndName &templateDeclaration, const Token *tok)
|
||||||
{
|
{
|
||||||
|
// find start of qualification
|
||||||
|
const Token * tokStart = tok;
|
||||||
|
int offset = 0;
|
||||||
|
while (Token::Match(tokStart->tokAt(-2), "%name% ::")) {
|
||||||
|
tokStart = tokStart->tokAt(-2);
|
||||||
|
offset -= 2;
|
||||||
|
}
|
||||||
|
// decide if namespace needs to be inserted in or appended to token list
|
||||||
|
const bool insert = tokStart != tok;
|
||||||
|
|
||||||
std::string::size_type start = 0;
|
std::string::size_type start = 0;
|
||||||
std::string::size_type end = 0;
|
std::string::size_type end = 0;
|
||||||
while ((end = templateDeclaration.scope.find(" ", start)) != std::string::npos) {
|
while ((end = templateDeclaration.scope.find(" ", start)) != std::string::npos) {
|
||||||
std::string token = templateDeclaration.scope.substr(start, end - start);
|
std::string token = templateDeclaration.scope.substr(start, end - start);
|
||||||
mTokenList.addtoken(token, tok->linenr(), tok->fileIndex());
|
if (insert)
|
||||||
|
mTokenList.back()->tokAt(offset)->insertToken(token, "");
|
||||||
|
else
|
||||||
|
mTokenList.addtoken(token, tok->linenr(), tok->fileIndex());
|
||||||
start = end + 1;
|
start = end + 1;
|
||||||
}
|
}
|
||||||
mTokenList.addtoken(templateDeclaration.scope.substr(start), tok->linenr(), tok->fileIndex());
|
if (insert) {
|
||||||
mTokenList.addtoken("::", tok->linenr(), tok->fileIndex());
|
mTokenList.back()->tokAt(offset)->insertToken(templateDeclaration.scope.substr(start), "");
|
||||||
|
mTokenList.back()->tokAt(offset)->insertToken("::", "");
|
||||||
|
} else {
|
||||||
|
mTokenList.addtoken(templateDeclaration.scope.substr(start), tok->linenr(), tok->fileIndex());
|
||||||
|
mTokenList.addtoken("::", tok->linenr(), tok->fileIndex());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TemplateSimplifier::alreadyHasNamespace(const TokenAndName &templateDeclaration, const Token *tok) const
|
bool TemplateSimplifier::alreadyHasNamespace(const TokenAndName &templateDeclaration, const Token *tok) const
|
||||||
|
@ -1961,12 +1975,8 @@ void TemplateSimplifier::replaceTemplateUsage(
|
||||||
|
|
||||||
void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues()
|
void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues()
|
||||||
{
|
{
|
||||||
// get all forward declarations
|
|
||||||
bool dummy;
|
|
||||||
std::list<TokenAndName> forwardTemplateDeclarations = getTemplateDeclarations(dummy, true);
|
|
||||||
|
|
||||||
// try to locate a matching declaration for each forward declaration
|
// try to locate a matching declaration for each forward declaration
|
||||||
for (const auto & forwardDecl : forwardTemplateDeclarations) {
|
for (const auto & forwardDecl : mTemplateForwardDeclarations) {
|
||||||
std::vector<const Token *> params1;
|
std::vector<const Token *> params1;
|
||||||
|
|
||||||
getTemplateParametersInDeclaration(forwardDecl.token, params1);
|
getTemplateParametersInDeclaration(forwardDecl.token, params1);
|
||||||
|
@ -1995,29 +2005,8 @@ void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues()
|
||||||
|
|
||||||
void TemplateSimplifier::simplifyTemplates(
|
void TemplateSimplifier::simplifyTemplates(
|
||||||
const std::time_t maxtime,
|
const std::time_t maxtime,
|
||||||
bool &codeWithTemplates
|
bool &codeWithTemplates)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
std::set<std::string> expandedtemplates;
|
|
||||||
|
|
||||||
if (getTemplateDeclarations(codeWithTemplates).empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// There are templates..
|
|
||||||
// Remove "typename" unless used in template arguments..
|
|
||||||
for (Token *tok = mTokenList.front(); tok; tok = tok->next()) {
|
|
||||||
if (tok->str() == "typename")
|
|
||||||
tok->deleteThis();
|
|
||||||
|
|
||||||
if (Token::simpleMatch(tok, "template <")) {
|
|
||||||
while (tok && tok->str() != ">")
|
|
||||||
tok = tok->next();
|
|
||||||
if (!tok)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// expand templates
|
|
||||||
// TODO: 2 is not the ideal number of loops.
|
// TODO: 2 is not the ideal number of loops.
|
||||||
// We should loop until the number of declarations is 0 but we can't
|
// We should loop until the number of declarations is 0 but we can't
|
||||||
// do that until we instantiate unintstantiated templates with their symbolic types.
|
// do that until we instantiate unintstantiated templates with their symbolic types.
|
||||||
|
@ -2027,12 +2016,36 @@ void TemplateSimplifier::simplifyTemplates(
|
||||||
// is fixed.
|
// is fixed.
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
if (i) {
|
if (i) {
|
||||||
expandedtemplates.clear();
|
mTemplateDeclarations.clear();
|
||||||
|
mTemplateForwardDeclarations.clear();
|
||||||
mTemplateInstantiations.clear();
|
mTemplateInstantiations.clear();
|
||||||
mInstantiatedTemplates.clear();
|
mInstantiatedTemplates.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
mTemplateDeclarations = getTemplateDeclarations(codeWithTemplates);
|
bool hasTemplates = getTemplateDeclarations();
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
codeWithTemplates = hasTemplates;
|
||||||
|
if (hasTemplates) {
|
||||||
|
// There are templates..
|
||||||
|
// Remove "typename" unless used in template arguments..
|
||||||
|
for (Token *tok = mTokenList.front(); tok; tok = tok->next()) {
|
||||||
|
if (tok->str() == "typename")
|
||||||
|
tok->deleteThis();
|
||||||
|
|
||||||
|
if (Token::simpleMatch(tok, "template <")) {
|
||||||
|
while (tok && tok->str() != ">")
|
||||||
|
tok = tok->next();
|
||||||
|
if (!tok)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure there is something to simplify.
|
||||||
|
if (mTemplateDeclarations.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
// Copy default argument values from forward declaration to declaration
|
// Copy default argument values from forward declaration to declaration
|
||||||
fixForwardDeclaredDefaultArgumentValues();
|
fixForwardDeclaredDefaultArgumentValues();
|
||||||
|
@ -2045,6 +2058,8 @@ void TemplateSimplifier::simplifyTemplates(
|
||||||
|
|
||||||
simplifyTemplateAliases();
|
simplifyTemplateAliases();
|
||||||
|
|
||||||
|
std::set<std::string> expandedtemplates;
|
||||||
|
|
||||||
for (std::list<TokenAndName>::reverse_iterator iter1 = mTemplateDeclarations.rbegin(); iter1 != mTemplateDeclarations.rend(); ++iter1) {
|
for (std::list<TokenAndName>::reverse_iterator iter1 = mTemplateDeclarations.rbegin(); iter1 != mTemplateDeclarations.rend(); ++iter1) {
|
||||||
// get specializations..
|
// get specializations..
|
||||||
std::list<const Token *> specializations;
|
std::list<const Token *> specializations;
|
||||||
|
|
|
@ -123,11 +123,9 @@ public:
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Get template declarations
|
* Get template declarations
|
||||||
* @param codeWithTemplates set to true if code has templates
|
* @return true if code has templates.
|
||||||
* @param forward declaration or forward declaration
|
|
||||||
* @return list of template declarations
|
|
||||||
*/
|
*/
|
||||||
std::list<TokenAndName> getTemplateDeclarations(bool &codeWithTemplates, bool forward = false);
|
bool getTemplateDeclarations();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get template instantiations
|
* Get template instantiations
|
||||||
|
@ -264,6 +262,7 @@ private:
|
||||||
ErrorLogger *mErrorLogger;
|
ErrorLogger *mErrorLogger;
|
||||||
|
|
||||||
std::list<TokenAndName> mTemplateDeclarations;
|
std::list<TokenAndName> mTemplateDeclarations;
|
||||||
|
std::list<TokenAndName> mTemplateForwardDeclarations;
|
||||||
std::list<TokenAndName> mTemplateInstantiations;
|
std::list<TokenAndName> mTemplateInstantiations;
|
||||||
std::list<TokenAndName> mInstantiatedTemplates;
|
std::list<TokenAndName> mInstantiatedTemplates;
|
||||||
std::list<TokenAndName> mMemberFunctionsToDelete;
|
std::list<TokenAndName> mMemberFunctionsToDelete;
|
||||||
|
|
|
@ -130,6 +130,7 @@ private:
|
||||||
TEST_CASE(template_namespace_8);
|
TEST_CASE(template_namespace_8);
|
||||||
TEST_CASE(template_namespace_9);
|
TEST_CASE(template_namespace_9);
|
||||||
TEST_CASE(template_namespace_10);
|
TEST_CASE(template_namespace_10);
|
||||||
|
TEST_CASE(template_namespace_11); // #7145
|
||||||
|
|
||||||
// Test TemplateSimplifier::templateParameters
|
// Test TemplateSimplifier::templateParameters
|
||||||
TEST_CASE(templateParameters);
|
TEST_CASE(templateParameters);
|
||||||
|
@ -1974,6 +1975,34 @@ private:
|
||||||
"} ;", tok(code));
|
"} ;", tok(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void template_namespace_11() {// #7145
|
||||||
|
const char code[] = "namespace MyNamespace {\n"
|
||||||
|
"class TestClass {\n"
|
||||||
|
"public:\n"
|
||||||
|
" TestClass() {\n"
|
||||||
|
" SomeFunction();\n"
|
||||||
|
" TemplatedMethod< int >();\n"
|
||||||
|
" }\n"
|
||||||
|
" void SomeFunction() { }\n"
|
||||||
|
"private:\n"
|
||||||
|
" template< typename T > void TemplatedMethod();\n"
|
||||||
|
"};\n"
|
||||||
|
"template< typename T > void TestClass::TemplatedMethod() { }\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS("namespace MyNamespace { "
|
||||||
|
"class TestClass { "
|
||||||
|
"public: "
|
||||||
|
"TestClass ( ) { "
|
||||||
|
"SomeFunction ( ) ; "
|
||||||
|
"TemplatedMethod<int> ( ) ; "
|
||||||
|
"} "
|
||||||
|
"void SomeFunction ( ) { } "
|
||||||
|
"private: "
|
||||||
|
"template < typename T > void TemplatedMethod ( ) ; "
|
||||||
|
"} ; "
|
||||||
|
"} void MyNamespace :: TestClass :: TemplatedMethod<int> ( ) { }", tok(code));
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int templateParameters(const char code[]) {
|
unsigned int templateParameters(const char code[]) {
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue