This commit is contained in:
parent
fe468ac142
commit
0e4c508d7b
|
@ -721,7 +721,19 @@ void TemplateSimplifier::expandTemplate(
|
|||
std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
||||
std::list<Token *> &templateInstantiations)
|
||||
{
|
||||
bool inTemplateDefinition=false;
|
||||
std::vector<const Token *> localTypeParametersInDeclaration;
|
||||
for (const Token *tok3 = tokenlist.front(); tok3; tok3 = tok3 ? tok3->next() : nullptr) {
|
||||
if (tok3->str()=="template") {
|
||||
if (tok3->next() && tok3->next()->str()=="<") {
|
||||
TemplateParametersInDeclaration(tok3->tokAt(2), localTypeParametersInDeclaration);
|
||||
if (localTypeParametersInDeclaration.size() != typeParametersInDeclaration.size())
|
||||
inTemplateDefinition = false; // Partial specialization
|
||||
else
|
||||
inTemplateDefinition = true;
|
||||
} else
|
||||
inTemplateDefinition = false; // Only template instantiation
|
||||
}
|
||||
if (Token::Match(tok3, "{|(|["))
|
||||
tok3 = tok3->link();
|
||||
|
||||
|
@ -731,7 +743,8 @@ void TemplateSimplifier::expandTemplate(
|
|||
}
|
||||
|
||||
// member function implemented outside class definition
|
||||
else if (TemplateSimplifier::instantiateMatch(tok3, name, typeParametersInDeclaration.size(), ":: ~| %var% (")) {
|
||||
else if (inTemplateDefinition &&
|
||||
TemplateSimplifier::instantiateMatch(tok3, name, typeParametersInDeclaration.size(), ":: ~| %var% (")) {
|
||||
tokenlist.addtoken(newName, tok3->linenr(), tok3->fileIndex());
|
||||
while (tok3 && tok3->str() != "::")
|
||||
tok3 = tok3->next();
|
||||
|
@ -1150,6 +1163,17 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
|
|||
return ret;
|
||||
}
|
||||
|
||||
const Token * TemplateSimplifier::TemplateParametersInDeclaration(
|
||||
const Token * tok,
|
||||
std::vector<const Token *> & typeParametersInDeclaration)
|
||||
{
|
||||
typeParametersInDeclaration.clear();
|
||||
for (; tok && tok->str() != ">"; tok = tok->next()) {
|
||||
if (Token::Match(tok, "%var% ,|>"))
|
||||
typeParametersInDeclaration.push_back(tok);
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
||||
bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||
TokenList& tokenlist,
|
||||
|
@ -1165,10 +1189,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
|||
|
||||
// Contains tokens such as "T"
|
||||
std::vector<const Token *> typeParametersInDeclaration;
|
||||
for (tok = tok->tokAt(2); tok && tok->str() != ">"; tok = tok->next()) {
|
||||
if (Token::Match(tok, "%var% ,|>"))
|
||||
typeParametersInDeclaration.push_back(tok);
|
||||
}
|
||||
tok = TemplateParametersInDeclaration(tok->tokAt(2), typeParametersInDeclaration);
|
||||
|
||||
// bail out if the end of the file was reached
|
||||
if (!tok)
|
||||
|
|
|
@ -117,6 +117,19 @@ public:
|
|||
std::vector<const Token *> &typesUsedInTemplateInstantiation,
|
||||
std::list<Token *> &templateInstantiations);
|
||||
|
||||
/**
|
||||
* @brief TemplateParametersInDeclaration
|
||||
* @param tok template < typename T, typename S >
|
||||
* ^ tok
|
||||
* @param typeParametersInDeclaration template < typename T, typename S >
|
||||
* ^ [0] ^ [1]
|
||||
* @return template < typename T, typename S >
|
||||
* ^ return
|
||||
*/
|
||||
static const Token * TemplateParametersInDeclaration(
|
||||
const Token * tok,
|
||||
std::vector<const Token *> & typeParametersInDeclaration);
|
||||
|
||||
/**
|
||||
* Simplify templates : expand all instantiations for a template
|
||||
* @todo It seems that inner templates should be instantiated recursively
|
||||
|
|
|
@ -83,6 +83,8 @@ private:
|
|||
TEST_CASE(template46); // #5816 - syntax error reported for valid code
|
||||
TEST_CASE(template47); // #6023 - syntax error reported for valid code
|
||||
TEST_CASE(template48); // #6134 - 100% CPU upon invalid code
|
||||
TEST_CASE(template49); // #6237 - template instantiation
|
||||
TEST_CASE(template50); // #4272 - simple partial specialization
|
||||
TEST_CASE(template_unhandled);
|
||||
TEST_CASE(template_default_parameter);
|
||||
TEST_CASE(template_default_type);
|
||||
|
@ -878,6 +880,45 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void template49() { // #6237
|
||||
const char code[] = "template <classname T> class Fred { void f(); void g(); };\n"
|
||||
"template <classname T> void Fred<T>::f() { }\n"
|
||||
"template <classname T> void Fred<T>::g() { }\n"
|
||||
"template void Fred<float>::f();\n"
|
||||
"template void Fred<int>::g();\n";
|
||||
|
||||
const std::string expected("template < classname T > void Fred<T> :: f ( ) { } "
|
||||
"template < classname T > void Fred<T> :: g ( ) { } "
|
||||
"template void Fred<float> :: f ( ) ; "
|
||||
"template void Fred<int> :: g ( ) ; "
|
||||
"class Fred<T> { void f ( ) ; void g ( ) ; } ; "
|
||||
"Fred<T> :: f ( ) { } "
|
||||
"Fred<T> :: g ( ) { } "
|
||||
"class Fred<float> { void f ( ) ; void g ( ) ; } ; "
|
||||
"class Fred<int> { void f ( ) ; void g ( ) ; } ;");
|
||||
|
||||
ASSERT_EQUALS(expected, tok(code));
|
||||
}
|
||||
|
||||
void template50() { // #4272
|
||||
const char code[] = "template <classname T> class Fred { void f(); };\n"
|
||||
"template <classname T> void Fred<T>::f() { }\n"
|
||||
"template<> void Fred<float>::f() { }\n"
|
||||
"template<> void Fred<int>::g() { }\n";
|
||||
|
||||
const std::string expected("template < classname T > void Fred<T> :: f ( ) { } "
|
||||
"template < > void Fred<float> :: f ( ) { } "
|
||||
"template < > void Fred<int> :: g ( ) { } "
|
||||
"class Fred<T> { void f ( ) ; } ; "
|
||||
"Fred<T> :: f ( ) { } "
|
||||
"class Fred<float> { void f ( ) ; } ; "
|
||||
"class Fred<int> { void f ( ) ; } ;");
|
||||
|
||||
ASSERT_EQUALS(expected, tok(code));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void template_default_parameter() {
|
||||
{
|
||||
const char code[] = "template <class T, int n=3>\n"
|
||||
|
|
Loading…
Reference in New Issue