TemplateSimplifier: Fix in expandTemplate
This commit is contained in:
parent
1eb2df34ad
commit
a80760cb6f
|
@ -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();
|
||||||
|
|
|
@ -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)"
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue