TemplateSimplifier: Fix in expandTemplate

This commit is contained in:
Daniel Marjamäki 2017-12-25 08:19:46 +01:00
parent 1eb2df34ad
commit a80760cb6f
3 changed files with 29 additions and 2 deletions

View File

@ -774,8 +774,16 @@ void TemplateSimplifier::expandTemplate(
std::list<Token *> &templateInstantiations) std::list<Token *> &templateInstantiations)
{ {
bool inTemplateDefinition=false; bool inTemplateDefinition=false;
const Token *endOfTemplateDefinition = nullptr;
std::vector<const Token *> localTypeParametersInDeclaration; std::vector<const Token *> localTypeParametersInDeclaration;
for (const Token *tok3 = tokenlist.front(); tok3; tok3 = tok3 ? tok3->next() : nullptr) { for (const Token *tok3 = tokenlist.front(); tok3; tok3 = tok3 ? tok3->next() : nullptr) {
if (inTemplateDefinition) {
if (!endOfTemplateDefinition && tok3->str() == "{")
endOfTemplateDefinition = tok3->link();
if (tok3 == endOfTemplateDefinition)
inTemplateDefinition = false;
}
if (tok3->str()=="template") { if (tok3->str()=="template") {
if (tok3->next() && tok3->next()->str()=="<") { if (tok3->next() && tok3->next()->str()=="<") {
TemplateParametersInDeclaration(tok3->tokAt(2), localTypeParametersInDeclaration); TemplateParametersInDeclaration(tok3->tokAt(2), localTypeParametersInDeclaration);
@ -799,6 +807,11 @@ void TemplateSimplifier::expandTemplate(
// member function implemented outside class definition // member function implemented outside class definition
else if (inTemplateDefinition && else if (inTemplateDefinition &&
TemplateSimplifier::instantiateMatch(tok3, name, typeParametersInDeclaration.size(), ":: ~| %name% (")) { TemplateSimplifier::instantiateMatch(tok3, name, typeParametersInDeclaration.size(), ":: ~| %name% (")) {
const Token *tok4 = tok3->next()->findClosingBracket();
while (tok4 && tok4->str() != "(")
tok4 = tok4->next();
if (!Tokenizer::isFunctionHead(tok4, "{:", true))
continue;
tokenlist.addtoken(newName, tok3->linenr(), tok3->fileIndex()); tokenlist.addtoken(newName, tok3->linenr(), tok3->fileIndex());
while (tok3 && tok3->str() != "::") while (tok3 && tok3->str() != "::")
tok3 = tok3->next(); tok3 = tok3->next();

View File

@ -504,8 +504,6 @@ public:
*/ */
const Token * isFunctionHead(const Token *tok, const std::string &endsWith) const; const Token * isFunctionHead(const Token *tok, const std::string &endsWith) const;
private:
/** /**
* is token pointing at function head? * is token pointing at function head?
* @param tok A '(' or ')' token in a possible function head * @param tok A '(' or ')' token in a possible function head
@ -515,6 +513,8 @@ private:
*/ */
static const Token * isFunctionHead(const Token *tok, const std::string &endsWith, bool cpp); static const Token * isFunctionHead(const Token *tok, const std::string &endsWith, bool cpp);
private:
/** /**
* simplify "while (0)" * simplify "while (0)"
*/ */

View File

@ -97,6 +97,7 @@ private:
TEST_CASE(template57); // #7891 TEST_CASE(template57); // #7891
TEST_CASE(template58); // #6021 - use after free (deleted tokens in simplifyCalculations) TEST_CASE(template58); // #6021 - use after free (deleted tokens in simplifyCalculations)
TEST_CASE(template59); // #8051 - TemplateSimplifier::simplifyTemplateInstantiation failure TEST_CASE(template59); // #8051 - TemplateSimplifier::simplifyTemplateInstantiation failure
TEST_CASE(template60); // handling of methods outside template definition
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template) TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
TEST_CASE(template_unhandled); TEST_CASE(template_unhandled);
TEST_CASE(template_default_parameter); TEST_CASE(template_default_parameter);
@ -1096,6 +1097,19 @@ private:
ASSERT_EQUALS(exp, tok(code)); ASSERT_EQUALS(exp, tok(code));
} }
void template60() { // Extracted from Clang testfile
const char code[] = "template <typename T> struct S { typedef int type; };\n"
"template <typename T> void f() {}\n"
"template <typename T> void h() { f<typename S<T>::type(0)>(); }\n"
"\n"
"void j() { h<int>(); }";
const char exp[] = "template < typename T > void f ( ) { } " // <- TODO: This template is not expanded
"void j ( ) { h < int > ( ) ; } "
"void h < int > ( ) { f < S < int > :: type ( 0 ) > ( ) ; } "
"struct S < int > { } ;";
ASSERT_EQUALS(exp, tok(code));
}
void template_enum() { void template_enum() {
const char code1[] = "template <class T>\n" const char code1[] = "template <class T>\n"
"struct Unconst {\n" "struct Unconst {\n"