parent
54d6625ffb
commit
7875555b03
|
@ -497,6 +497,9 @@ bool TemplateSimplifier::getTemplateDeclarations()
|
||||||
tok2 = tok2->link();
|
tok2 = tok2->link();
|
||||||
else if (tok2->str() == ")")
|
else if (tok2->str() == ")")
|
||||||
break;
|
break;
|
||||||
|
// skip decltype(...)
|
||||||
|
else if (Token::Match(tok2, "decltype ("))
|
||||||
|
tok2 = tok2->linkAt(1);
|
||||||
// Declaration => add to mTemplateForwardDeclarations
|
// Declaration => add to mTemplateForwardDeclarations
|
||||||
else if (tok2->str() == ";") {
|
else if (tok2->str() == ";") {
|
||||||
const int namepos = getTemplateNamePosition(parmEnd, true);
|
const int namepos = getTemplateNamePosition(parmEnd, true);
|
||||||
|
@ -891,7 +894,14 @@ bool TemplateSimplifier::getTemplateNamePositionTemplateFunction(const Token *to
|
||||||
while (tok && tok->next()) {
|
while (tok && tok->next()) {
|
||||||
if (Token::Match(tok->next(), ";|{"))
|
if (Token::Match(tok->next(), ";|{"))
|
||||||
return false;
|
return false;
|
||||||
else if (Token::Match(tok->next(), "%type% <")) {
|
// skip decltype(...)
|
||||||
|
else if (Token::Match(tok, "decltype (")) {
|
||||||
|
const Token * end = tok->linkAt(1);
|
||||||
|
while (tok && tok != end) {
|
||||||
|
tok = tok->next();
|
||||||
|
namepos++;
|
||||||
|
}
|
||||||
|
} else if (Token::Match(tok->next(), "%type% <")) {
|
||||||
const Token *closing = tok->tokAt(2)->findClosingBracket();
|
const Token *closing = tok->tokAt(2)->findClosingBracket();
|
||||||
if (closing) {
|
if (closing) {
|
||||||
if (closing->strAt(1) == "(" && mTokenizer->isFunctionHead(closing->tokAt(2), ";|{|:"))
|
if (closing->strAt(1) == "(" && mTokenizer->isFunctionHead(closing->tokAt(2), ";|{|:"))
|
||||||
|
@ -984,15 +994,19 @@ void TemplateSimplifier::expandTemplate(
|
||||||
const Token *endOfTemplateDefinition = nullptr;
|
const Token *endOfTemplateDefinition = nullptr;
|
||||||
const Token * const templateDeclarationNameToken = templateDeclarationToken->tokAt(getTemplateNamePosition(templateDeclarationToken));
|
const Token * const templateDeclarationNameToken = templateDeclarationToken->tokAt(getTemplateNamePosition(templateDeclarationToken));
|
||||||
const bool isClass = Token::Match(templateDeclarationToken->next(), "class|struct|union %name% <|{|:");
|
const bool isClass = Token::Match(templateDeclarationToken->next(), "class|struct|union %name% <|{|:");
|
||||||
const bool isFunction = templateDeclarationNameToken->strAt(1) == "(";
|
const bool isFunction = templateDeclarationNameToken->strAt(1) == "(" ||
|
||||||
|
(templateDeclarationNameToken->strAt(1) == "<" && templateDeclarationNameToken->next()->findClosingBracket()->strAt(1) == "(");
|
||||||
|
const bool isSpecialization = Token::Match(templateDeclaration.token, "template < >");
|
||||||
|
|
||||||
// add forward declarations
|
// add forward declarations
|
||||||
if (copy && isClass) {
|
if (copy && isClass) {
|
||||||
templateDeclaration.token->insertToken(templateDeclarationToken->strAt(1), "", true);
|
templateDeclaration.token->insertToken(templateDeclarationToken->strAt(1), "", true);
|
||||||
templateDeclaration.token->insertToken(newName, "", true);
|
templateDeclaration.token->insertToken(newName, "", true);
|
||||||
templateDeclaration.token->insertToken(";", "", true);
|
templateDeclaration.token->insertToken(";", "", true);
|
||||||
} else if (copy && isFunction) {
|
} else if (isFunction && (copy || (!copy && isSpecialization))) {
|
||||||
Token * dst = templateDeclaration.token;
|
Token * dst = templateDeclaration.token;
|
||||||
|
bool isStatic = false;
|
||||||
|
std::string scope;
|
||||||
Token * start;
|
Token * start;
|
||||||
Token * end;
|
Token * end;
|
||||||
auto it = mTemplateForwardDeclarationsMap.find(dst);
|
auto it = mTemplateForwardDeclarationsMap.find(dst);
|
||||||
|
@ -1003,8 +1017,21 @@ void TemplateSimplifier::expandTemplate(
|
||||||
start = temp1->next();
|
start = temp1->next();
|
||||||
end = temp2->linkAt(1)->next();
|
end = temp2->linkAt(1)->next();
|
||||||
} else {
|
} else {
|
||||||
|
auto it2 = mTemplateUserSpecializationMap.find(dst);
|
||||||
|
if (it2 != mTemplateUserSpecializationMap.end()) {
|
||||||
|
dst = it2->second;
|
||||||
|
isStatic = dst->next()->findClosingBracket()->strAt(1) == "static";
|
||||||
|
const Token * temp = templateDeclarationNameToken;
|
||||||
|
while (Token::Match(temp->tokAt(-2), "%name% ::")) {
|
||||||
|
scope.insert(0, temp->strAt(-2) + " :: ");
|
||||||
|
temp = temp->tokAt(-2);
|
||||||
|
}
|
||||||
|
}
|
||||||
start = templateDeclarationToken->next();
|
start = templateDeclarationToken->next();
|
||||||
end = templateDeclarationNameToken->linkAt(1)->next();
|
if (templateDeclarationNameToken->strAt(1) == "(")
|
||||||
|
end = templateDeclarationNameToken->linkAt(1)->next();
|
||||||
|
else
|
||||||
|
end = templateDeclarationNameToken->next()->findClosingBracket()->linkAt(1)->next();
|
||||||
}
|
}
|
||||||
unsigned int typeindentlevel = 0;
|
unsigned int typeindentlevel = 0;
|
||||||
while (!(typeindentlevel == 0 && Token::Match(end, ";|{|:"))) {
|
while (!(typeindentlevel == 0 && Token::Match(end, ";|{|:"))) {
|
||||||
|
@ -1015,6 +1042,9 @@ void TemplateSimplifier::expandTemplate(
|
||||||
end = end->next();
|
end = end->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isStatic)
|
||||||
|
dst->insertToken("static", "", true);
|
||||||
|
|
||||||
std::map<const Token *, Token *> links;
|
std::map<const Token *, Token *> links;
|
||||||
while (start && start != end) {
|
while (start && start != end) {
|
||||||
unsigned int itype = 0;
|
unsigned int itype = 0;
|
||||||
|
@ -1041,7 +1071,11 @@ void TemplateSimplifier::expandTemplate(
|
||||||
dst->previous()->isLong(typetok->isLong());
|
dst->previous()->isLong(typetok->isLong());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (start->str() == templateDeclarationNameToken->str()) {
|
if (isSpecialization && !copy && !scope.empty() && Token::Match(start, (scope + templateDeclarationNameToken->str()).c_str())) {
|
||||||
|
// skip scope
|
||||||
|
while (start->strAt(1) != templateDeclarationNameToken->str())
|
||||||
|
start = start->next();
|
||||||
|
} else if (start->str() == templateDeclarationNameToken->str()) {
|
||||||
dst->insertToken(newName, "", true);
|
dst->insertToken(newName, "", true);
|
||||||
if (start->strAt(1) == "<")
|
if (start->strAt(1) == "<")
|
||||||
start = start->next()->findClosingBracket();
|
start = start->next()->findClosingBracket();
|
||||||
|
@ -1133,6 +1167,8 @@ void TemplateSimplifier::expandTemplate(
|
||||||
// Start of template..
|
// Start of template..
|
||||||
if (tok3 == templateDeclarationToken) {
|
if (tok3 == templateDeclarationToken) {
|
||||||
tok3 = tok3->next();
|
tok3 = tok3->next();
|
||||||
|
if (tok3->str() == "static")
|
||||||
|
tok3 = tok3->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// member function implemented outside class definition
|
// member function implemented outside class definition
|
||||||
|
@ -1907,23 +1943,12 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// already simplified
|
// already simplified
|
||||||
if (!Token::Match(startToken, "%name% <"))
|
if (!Token::Match(tok2, "%name% <"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (templateDeclaration.scope.empty()) {
|
if (!matchSpecialization(tok->tokAt(namepos), tok2, specializations))
|
||||||
if (startToken->str() != templateDeclaration.name)
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
std::string name = templateDeclaration.scope + " :: " + startToken->str();
|
|
||||||
if (name != templateDeclaration.name)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!matchSpecialization(tok->tokAt(namepos), startToken, specializations))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
tok2 = startToken;
|
|
||||||
|
|
||||||
// New type..
|
// New type..
|
||||||
mTypesUsedInTemplateInstantiation.clear();
|
mTypesUsedInTemplateInstantiation.clear();
|
||||||
std::list<std::string> typeStringsUsedInTemplateInstantiation;
|
std::list<std::string> typeStringsUsedInTemplateInstantiation;
|
||||||
|
@ -2051,6 +2076,61 @@ void TemplateSimplifier::replaceTemplateUsage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string getPathName(const TemplateSimplifier::TokenAndName & decl)
|
||||||
|
{
|
||||||
|
std::string name = decl.scope;
|
||||||
|
if (!name.empty())
|
||||||
|
name += " :: ";
|
||||||
|
if (decl.nameToken->strAt(-1) == "::") {
|
||||||
|
const Token * start = decl.nameToken;
|
||||||
|
|
||||||
|
while (Token::Match(start->tokAt(-2), "%name% ::"))
|
||||||
|
start = start->tokAt(-2);
|
||||||
|
|
||||||
|
while (start != decl.nameToken) {
|
||||||
|
name += (start->str() + " ");
|
||||||
|
start = start->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name += decl.name;
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TemplateSimplifier::getUserDefinedSpecializations()
|
||||||
|
{
|
||||||
|
// try to locate a matching declaration for each user defined specialization
|
||||||
|
for (auto & spec : mTemplateDeclarations) {
|
||||||
|
if (Token::Match(spec.token, "template < >")) {
|
||||||
|
std::string specName = getPathName(spec);
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (auto & decl : mTemplateDeclarations) {
|
||||||
|
if (Token::Match(decl.token, "template < >"))
|
||||||
|
continue;
|
||||||
|
std::string declName = getPathName(decl);
|
||||||
|
|
||||||
|
// make sure the scopes and names match
|
||||||
|
if (specName == declName) {
|
||||||
|
// @todo make sure function parameters also match
|
||||||
|
mTemplateUserSpecializationMap[spec.token] = decl.token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
for (auto & decl : mTemplateForwardDeclarations) {
|
||||||
|
std::string declName = getPathName(decl);
|
||||||
|
|
||||||
|
// make sure the scopes and names match
|
||||||
|
if (specName == declName) {
|
||||||
|
// @todo make sure function parameters also match
|
||||||
|
mTemplateUserSpecializationMap[spec.token] = decl.token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues()
|
void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues()
|
||||||
{
|
{
|
||||||
// try to locate a matching declaration for each forward declaration
|
// try to locate a matching declaration for each forward declaration
|
||||||
|
@ -2066,26 +2146,8 @@ void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues()
|
||||||
|
|
||||||
// make sure the number of arguments match
|
// make sure the number of arguments match
|
||||||
if (params1.size() == params2.size()) {
|
if (params1.size() == params2.size()) {
|
||||||
std::string declName = decl.scope;
|
std::string declName = getPathName(decl);
|
||||||
if (!declName.empty())
|
std::string forwardDeclName = getPathName(forwardDecl);
|
||||||
declName += " :: ";
|
|
||||||
if (decl.nameToken->strAt(-1) == "::") {
|
|
||||||
const Token * start = decl.nameToken;
|
|
||||||
|
|
||||||
while (Token::Match(start->tokAt(-2), "%name% ::"))
|
|
||||||
start = start->tokAt(-2);
|
|
||||||
|
|
||||||
while (start != decl.nameToken) {
|
|
||||||
declName += (start->str() + " ");
|
|
||||||
start = start->next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
declName += decl.name;
|
|
||||||
|
|
||||||
std::string forwardDeclName = forwardDecl.scope;
|
|
||||||
if (!forwardDeclName.empty())
|
|
||||||
forwardDeclName += " :: ";
|
|
||||||
forwardDeclName += forwardDecl.name;
|
|
||||||
|
|
||||||
// make sure the scopes and names match
|
// make sure the scopes and names match
|
||||||
if (forwardDeclName == declName) {
|
if (forwardDeclName == declName) {
|
||||||
|
@ -2124,6 +2186,7 @@ void TemplateSimplifier::simplifyTemplates(
|
||||||
mTemplateDeclarations.clear();
|
mTemplateDeclarations.clear();
|
||||||
mTemplateForwardDeclarations.clear();
|
mTemplateForwardDeclarations.clear();
|
||||||
mTemplateForwardDeclarationsMap.clear();
|
mTemplateForwardDeclarationsMap.clear();
|
||||||
|
mTemplateUserSpecializationMap.clear();
|
||||||
mTemplateInstantiations.clear();
|
mTemplateInstantiations.clear();
|
||||||
mInstantiatedTemplates.clear();
|
mInstantiatedTemplates.clear();
|
||||||
mExplicitInstantiationsToDelete.clear();
|
mExplicitInstantiationsToDelete.clear();
|
||||||
|
@ -2157,6 +2220,9 @@ void TemplateSimplifier::simplifyTemplates(
|
||||||
// Copy default argument values from forward declaration to declaration
|
// Copy default argument values from forward declaration to declaration
|
||||||
fixForwardDeclaredDefaultArgumentValues();
|
fixForwardDeclaredDefaultArgumentValues();
|
||||||
|
|
||||||
|
// Locate user defined specializations.
|
||||||
|
getUserDefinedSpecializations();
|
||||||
|
|
||||||
// Locate possible instantiations of templates..
|
// Locate possible instantiations of templates..
|
||||||
getTemplateInstantiations();
|
getTemplateInstantiations();
|
||||||
|
|
||||||
|
|
|
@ -156,6 +156,12 @@ private:
|
||||||
*/
|
*/
|
||||||
void useDefaultArgumentValues();
|
void useDefaultArgumentValues();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to locate a matching declaration for each user defined
|
||||||
|
* specialization.
|
||||||
|
*/
|
||||||
|
void getUserDefinedSpecializations();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* simplify template aliases
|
* simplify template aliases
|
||||||
*/
|
*/
|
||||||
|
@ -278,6 +284,7 @@ private:
|
||||||
std::list<TokenAndName> mTemplateDeclarations;
|
std::list<TokenAndName> mTemplateDeclarations;
|
||||||
std::list<TokenAndName> mTemplateForwardDeclarations;
|
std::list<TokenAndName> mTemplateForwardDeclarations;
|
||||||
std::map<Token *, Token *> mTemplateForwardDeclarationsMap;
|
std::map<Token *, Token *> mTemplateForwardDeclarationsMap;
|
||||||
|
std::map<Token *, Token *> mTemplateUserSpecializationMap;
|
||||||
std::list<TokenAndName> mTemplateInstantiations;
|
std::list<TokenAndName> mTemplateInstantiations;
|
||||||
std::list<TokenAndName> mInstantiatedTemplates;
|
std::list<TokenAndName> mInstantiatedTemplates;
|
||||||
std::list<TokenAndName> mMemberFunctionsToDelete;
|
std::list<TokenAndName> mMemberFunctionsToDelete;
|
||||||
|
|
|
@ -125,6 +125,9 @@ private:
|
||||||
TEST_CASE(template85); // #8902 crash
|
TEST_CASE(template85); // #8902 crash
|
||||||
TEST_CASE(template86); // crash
|
TEST_CASE(template86); // crash
|
||||||
TEST_CASE(template87);
|
TEST_CASE(template87);
|
||||||
|
TEST_CASE(template88); // #6183
|
||||||
|
TEST_CASE(template89); // #8917
|
||||||
|
TEST_CASE(template90); // crash
|
||||||
TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||||
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||||
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)
|
||||||
|
@ -479,7 +482,8 @@ private:
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
// The expected result..
|
// The expected result..
|
||||||
const char expected[] = "void foo<int*> ( ) "
|
const char expected[] = "void foo<int*> ( ) ; "
|
||||||
|
"void foo<int*> ( ) "
|
||||||
"{ x ( ) ; } "
|
"{ x ( ) ; } "
|
||||||
"int main ( ) "
|
"int main ( ) "
|
||||||
"{ foo<int*> ( ) ; }";
|
"{ foo<int*> ( ) ; }";
|
||||||
|
@ -505,6 +509,7 @@ private:
|
||||||
// The expected result..
|
// The expected result..
|
||||||
const char expected[] = "void a<2> ( ) ; "
|
const char expected[] = "void a<2> ( ) ; "
|
||||||
"void a<1> ( ) ; "
|
"void a<1> ( ) ; "
|
||||||
|
"void a<0> ( ) ; "
|
||||||
"void a<0> ( ) { } "
|
"void a<0> ( ) { } "
|
||||||
"int main ( ) "
|
"int main ( ) "
|
||||||
"{ a<2> ( ) ; return 0 ; } "
|
"{ a<2> ( ) ; return 0 ; } "
|
||||||
|
@ -1664,6 +1669,92 @@ private:
|
||||||
ASSERT_EQUALS(exp, tok(code));
|
ASSERT_EQUALS(exp, tok(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void template88() { // #6183.cpp
|
||||||
|
const char code[] = "class CTest {\n"
|
||||||
|
"public:\n"
|
||||||
|
" template <typename T>\n"
|
||||||
|
" static void Greeting(T val) {\n"
|
||||||
|
" std::cout << val << std::endl;\n"
|
||||||
|
" }\n"
|
||||||
|
"private:\n"
|
||||||
|
" static void SayHello() {\n"
|
||||||
|
" std::cout << \"Hello World!\" << std::endl;\n"
|
||||||
|
" }\n"
|
||||||
|
"};\n"
|
||||||
|
"template<>\n"
|
||||||
|
"void CTest::Greeting(bool) {\n"
|
||||||
|
" CTest::SayHello();\n"
|
||||||
|
"}\n"
|
||||||
|
"int main() {\n"
|
||||||
|
" CTest::Greeting<bool>(true);\n"
|
||||||
|
" return 0;\n"
|
||||||
|
"}";
|
||||||
|
const char exp[] = "class CTest { "
|
||||||
|
"public: "
|
||||||
|
"static void Greeting<bool> ( bool ) ; "
|
||||||
|
"template < typename T > "
|
||||||
|
"static void Greeting ( T val ) { "
|
||||||
|
"std :: cout << val << std :: endl ; "
|
||||||
|
"} "
|
||||||
|
"private: "
|
||||||
|
"static void SayHello ( ) { "
|
||||||
|
"std :: cout << \"Hello World!\" << std :: endl ; "
|
||||||
|
"} "
|
||||||
|
"} ; "
|
||||||
|
"void CTest :: Greeting<bool> ( bool ) { "
|
||||||
|
"CTest :: SayHello ( ) ; "
|
||||||
|
"} "
|
||||||
|
"int main ( ) { "
|
||||||
|
"CTest :: Greeting<bool> ( true ) ; "
|
||||||
|
"return 0 ; "
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(exp, tok(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
void template89() { // #8917
|
||||||
|
const char code[] = "struct Fred {\n"
|
||||||
|
" template <typename T> static void foo() { }\n"
|
||||||
|
"};\n"
|
||||||
|
"template void Fred::foo<char>();\n"
|
||||||
|
"template void Fred::foo<float>();\n"
|
||||||
|
"template <> void Fred::foo<bool>() { }\n"
|
||||||
|
"template <> void Fred::foo<int>() { }";
|
||||||
|
const char exp[] = "struct Fred { "
|
||||||
|
"static void foo<char> ( ) ; "
|
||||||
|
"static void foo<float> ( ) ; "
|
||||||
|
"static void foo<bool> ( ) ; "
|
||||||
|
"static void foo<int> ( ) ; "
|
||||||
|
"} ; "
|
||||||
|
"void Fred :: foo<char> ( ) { } "
|
||||||
|
"void Fred :: foo<float> ( ) { } "
|
||||||
|
"void Fred :: foo<bool> ( ) { } "
|
||||||
|
"void Fred :: foo<int> ( ) { }";
|
||||||
|
const char act[] = "struct Fred { "
|
||||||
|
"static void foo<char> ( ) ; "
|
||||||
|
"static void foo<float> ( ) ; "
|
||||||
|
"} ; "
|
||||||
|
"void Fred :: foo<bool> ( ) ; "
|
||||||
|
"void Fred :: foo<bool> ( ) { } "
|
||||||
|
"void Fred :: foo<int> ( ) ; "
|
||||||
|
"void Fred :: foo<int> ( ) { } "
|
||||||
|
"void Fred :: foo<char> ( ) { } "
|
||||||
|
"void Fred :: foo<float> ( ) { }";
|
||||||
|
TODO_ASSERT_EQUALS(exp, act, tok(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
void template90() { // crash
|
||||||
|
const char code[] = "template <typename T> struct S1 {};\n"
|
||||||
|
"void f(S1<double>) {}\n"
|
||||||
|
"template <typename T>\n"
|
||||||
|
"decltype(S1<T>().~S1<T>()) fun1() {};";
|
||||||
|
const char exp[] = "struct S1<double> ; "
|
||||||
|
"void f ( S1<double> ) { } "
|
||||||
|
"template < typename T > "
|
||||||
|
"decltype ( S1 < T > ( ) . ~ S1 < T > ( ) ) fun1 ( ) { } ; "
|
||||||
|
"struct S1<double> { } ;";
|
||||||
|
ASSERT_EQUALS(exp, tok(code));
|
||||||
|
}
|
||||||
|
|
||||||
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||||
const char code[] = "template <typename T> struct C {};\n"
|
const char code[] = "template <typename T> struct C {};\n"
|
||||||
"template <typename T> struct S {a};\n"
|
"template <typename T> struct S {a};\n"
|
||||||
|
|
|
@ -80,6 +80,8 @@ private:
|
||||||
TEST_CASE(hierarchie_loop); // ticket 5590
|
TEST_CASE(hierarchie_loop); // ticket 5590
|
||||||
|
|
||||||
TEST_CASE(staticVariable); //ticket #5566
|
TEST_CASE(staticVariable); //ticket #5566
|
||||||
|
|
||||||
|
TEST_CASE(templateSimplification); //ticket #6183
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -794,6 +796,29 @@ private:
|
||||||
"int i = F();");
|
"int i = F();");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Unused private function: 'Foo::F'\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style) Unused private function: 'Foo::F'\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void templateSimplification() { //ticket #6183
|
||||||
|
check("class CTest {\n"
|
||||||
|
"public:\n"
|
||||||
|
" template <typename T>\n"
|
||||||
|
" static void Greeting(T val) {\n"
|
||||||
|
" std::cout << val << std::endl;\n"
|
||||||
|
" }\n"
|
||||||
|
"private:\n"
|
||||||
|
" static void SayHello() {\n"
|
||||||
|
" std::cout << \"Hello World!\" << std::endl;\n"
|
||||||
|
" }\n"
|
||||||
|
"};\n"
|
||||||
|
"template<>\n"
|
||||||
|
"void CTest::Greeting(bool) {\n"
|
||||||
|
" CTest::SayHello();\n"
|
||||||
|
"}\n"
|
||||||
|
"int main() {\n"
|
||||||
|
" CTest::Greeting<bool>(true);\n"
|
||||||
|
" return 0;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestUnusedPrivateFunction)
|
REGISTER_TEST(TestUnusedPrivateFunction)
|
||||||
|
|
Loading…
Reference in New Issue