From 8cca41774d867db8af738ee50132f4228115a001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 21 Nov 2013 20:27:24 +0100 Subject: [PATCH] Fixed #4446 (Crash on complex C++ template) --- lib/templatesimplifier.cpp | 26 +++++++++++++++++++++----- lib/templatesimplifier.h | 2 +- test/testsimplifytokens.cpp | 8 ++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 555c2e395..b8b5114ec 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -499,7 +499,7 @@ std::list TemplateSimplifier::getTemplateInstantiations(Token *tokens) void TemplateSimplifier::useDefaultArgumentValues(const std::list &templates, - const std::list &templateInstantiations) + std::list * const templateInstantiations) { for (std::list::const_iterator iter1 = templates.begin(); iter1 != templates.end(); ++iter1) { // template parameters with default value has syntax such as: @@ -534,7 +534,7 @@ void TemplateSimplifier::useDefaultArgumentValues(const std::list &temp continue; // iterate through all template instantiations - for (std::list::const_iterator iter2 = templateInstantiations.begin(); iter2 != templateInstantiations.end(); ++iter2) { + for (std::list::const_iterator iter2 = templateInstantiations->begin(); iter2 != templateInstantiations->end(); ++iter2) { Token *tok = *iter2; if (!Token::Match(tok, (classname + " < %any%").c_str())) @@ -580,11 +580,27 @@ void TemplateSimplifier::useDefaultArgumentValues(const std::list &temp for (std::list::iterator it = eq.begin(); it != eq.end(); ++it) { Token * const eqtok = *it; - const Token *tok2; + Token *tok2; + int indentlevel = 0; for (tok2 = eqtok->next(); tok2; tok2 = tok2->next()) { if (tok2->str() == "(") tok2 = tok2->link(); - else if (tok2->str() == "," || tok2->str() == ">") + else if (Token::Match(tok2, "%type% <") && templateParameters(tok2->next())) { + std::list::iterator ti = std::find(templateInstantiations->begin(), + templateInstantiations->end(), + tok2); + if (ti != templateInstantiations->end()) + templateInstantiations->erase(ti); + ++indentlevel; + } else if (indentlevel > 0 && tok2->str() == ">") + --indentlevel; + else if (indentlevel > 0 && tok2->str() == ">>") { + indentlevel -= 2; + if (indentlevel < 0) + tok2->str(">"); + } else if (indentlevel == 0 && Token::Match(tok2, ",|>|>>")) + break; + if (indentlevel < 0) break; } Token::eraseTokens(eqtok, tok2); @@ -1263,7 +1279,7 @@ void TemplateSimplifier::simplifyTemplates( return; // Template arguments with default values - TemplateSimplifier::useDefaultArgumentValues(templates, templateInstantiations); + TemplateSimplifier::useDefaultArgumentValues(templates, &templateInstantiations); // expand templates //bool done = false; diff --git a/lib/templatesimplifier.h b/lib/templatesimplifier.h index b2129a338..cfdfa6c0a 100644 --- a/lib/templatesimplifier.h +++ b/lib/templatesimplifier.h @@ -88,7 +88,7 @@ public: * @param templateInstantiations list of template instantiations */ static void useDefaultArgumentValues(const std::list &templates, - const std::list &templateInstantiations); + std::list *templateInstantiations); /** * Match template declaration/instantiation diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 34ccb74de..b41681f50 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -2429,6 +2429,14 @@ private: ); TODO_ASSERT_EQUALS(wanted, current, tok(code)); } + { + const char code[] = "template> class B {};\n" + "template> class C;\n" + "template class D { };\n"; + ASSERT_EQUALS("template < class T , class T2 > class B { } ; " + "template < class B , typename C > class C ; " + "template < class B , typename C > class D { } ;", tok(code)); + } } void template_default_type() {