diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 2a9ef63b8..070c45589 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -1575,7 +1575,7 @@ void TemplateSimplifier::expandTemplate( Token * start; Token * end; auto it = mTemplateForwardDeclarationsMap.find(dst); - if (it != mTemplateForwardDeclarationsMap.end()) { + if (!isSpecialization && it != mTemplateForwardDeclarationsMap.end()) { dst = it->second; dstStart = dst->previous(); const Token * temp1 = dst->tokAt(1)->findClosingBracket(); @@ -1583,6 +1583,14 @@ void TemplateSimplifier::expandTemplate( start = temp1->next(); end = temp2->linkAt(1)->next(); } else { + if (it != mTemplateForwardDeclarationsMap.end()) { + std::list::iterator it1 = std::find_if(mTemplateForwardDeclarations.begin(), + mTemplateForwardDeclarations.end(), + FindToken(it->second)); + if (it1 != mTemplateForwardDeclarations.end()) + mMemberFunctionsToDelete.push_back(*it1); + } + auto it2 = mTemplateSpecializationMap.find(dst); if (it2 != mTemplateSpecializationMap.end()) { dst = it2->second; @@ -3734,6 +3742,15 @@ void TemplateSimplifier::simplifyTemplates( if (it != mTemplateDeclarations.end()) { removeTemplate(it->token()); mTemplateDeclarations.erase(it); + } else { + const std::list::iterator it1 = std::find_if(mTemplateForwardDeclarations.begin(), + mTemplateForwardDeclarations.end(), + FindToken(mMemberFunctionsToDelete.begin()->token())); + // multiple functions can share the same declaration so make sure it hasn't already been deleted + if (it1 != mTemplateForwardDeclarations.end()) { + removeTemplate(it1->token()); + mTemplateForwardDeclarations.erase(it1); + } } mMemberFunctionsToDelete.erase(mMemberFunctionsToDelete.begin()); } diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 2f06d04fa..bf723aeb5 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -209,6 +209,7 @@ private: TEST_CASE(template164); // #9394 TEST_CASE(template165); // #10032 syntax error TEST_CASE(template166); // #10081 hang + TEST_CASE(template167); TEST_CASE(template_specialization_1); // #7868 - template specialization template struct S> {..}; TEST_CASE(template_specialization_2); // #7868 - template specialization template struct S> {..}; TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template) @@ -4189,6 +4190,34 @@ private: ASSERT_EQUALS(exp, tok(code)); } + void template167() { + const char code[] = "struct MathLib {\n" + " template static std::string toString(T value) {\n" + " return std::string{};\n" + " }\n" + "};\n" + "template<> std::string MathLib::toString(double value);\n" + "template<> std::string MathLib::toString(double value) {\n" + " return std::string{std::to_string(value)};\n" + "}\n" + "void foo() {\n" + " std::string str = MathLib::toString(1.0);\n" + "}"; + const char exp[] = "struct MathLib { " + "static std :: string toString ( double value ) ; " + "template < class T > static std :: string toString ( T value ) { " + "return std :: string { } ; " + "} " + "} ; " + "std :: string MathLib :: toString ( double value ) { " + "return std :: string { std :: to_string ( value ) } ; " + "} " + "void foo ( ) { " + "std :: string str ; str = MathLib :: toString ( 1.0 ) ; " + "}"; + ASSERT_EQUALS(exp, tok(code)); + } + void template_specialization_1() { // #7868 - template specialization template struct S> {..}; const char code[] = "template struct C {};\n" "template struct S {a};\n"