From 8d9f0b3528f59b50bf0555062fad9f0292904bbe Mon Sep 17 00:00:00 2001 From: IOBYTE Date: Sun, 6 Dec 2020 16:08:42 -0500 Subject: [PATCH] =?UTF-8?q?fix=20#9394=20("debug:=20Executable=20scope=20'?= =?UTF-8?q?x'=20with=20unknown=20function."=20with=20=E2=80=A6=20(#2935)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/templatesimplifier.cpp | 21 ++++++++++++--- test/testsimplifytemplate.cpp | 51 +++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 456dbc73f..c3814f8f5 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -151,8 +151,12 @@ TemplateSimplifier::TokenAndName::TokenAndName(Token *token, const std::string & } } // check for member class or function and adjust scope - if ((isFunction() || isClass()) && mNameToken->strAt(-1) == "::") { + if ((isFunction() || isClass()) && + (mNameToken->strAt(-1) == "::" || Token::simpleMatch(mNameToken->tokAt(-2), ":: ~"))) { const Token * start = mNameToken; + if (start->strAt(-1) == "~") + start = start->previous(); + const Token *end = start; while (start && (Token::Match(start->tokAt(-2), "%name% ::") || (Token::simpleMatch(start->tokAt(-2), "> ::") && @@ -164,10 +168,10 @@ TemplateSimplifier::TokenAndName::TokenAndName(Token *token, const std::string & start = start->tokAt(-2); } - if (start && start != nameToken) { + if (start && start != end) { if (!mScope.empty()) mScope += " ::"; - while (start && start->next() != mNameToken) { + while (start && start->next() != end) { if (start->str() == "<") start = start->findClosingBracket(); else { @@ -3024,6 +3028,17 @@ bool TemplateSimplifier::simplifyTemplateInstantiations( continue; } + // make sure constructors and destructors don't match each other + if (templateDeclaration.nameToken()->strAt(-1) == "~" && instantiation.token()->strAt(-1) != "~") + continue; + + // template families should match + if (!instantiation.isFunction() && templateDeclaration.isFunction()) { + // there are exceptions + if (!Token::simpleMatch(instantiation.token()->tokAt(-2), "decltype (")) + continue; + } + if (templateDeclaration.isFunction() && instantiation.isFunction()) { std::vector declFuncArgs; getFunctionArguments(templateDeclaration.nameToken(), declFuncArgs); diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 0441e69f0..32e766ad8 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -206,6 +206,7 @@ private: TEST_CASE(template161); TEST_CASE(template162); TEST_CASE(template163); // #9685 syntax error + TEST_CASE(template164); // #9394 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) @@ -4096,14 +4097,24 @@ private: void template162() { const char code[] = "template \n" + "struct CountryCode {\n" + " CountryCode(std::string cc);\n" + "};" + "template \n" "CountryCode::CountryCode(std::string cc) : m_String{std::move(cc)} {\n" "}\n" "template class CountryCode<2>;\n" "template class CountryCode<3>;"; - const char exp[] = "CountryCode<2> :: CountryCode<2> ( std :: string cc ) ; " - "CountryCode<3> :: CountryCode<3> ( std :: string cc ) ; " + const char exp[] = "struct CountryCode<2> ; " + "struct CountryCode<3> ; " + "struct CountryCode<2> { " + "CountryCode<2> ( std :: string cc ) ; " + "} ; " "CountryCode<2> :: CountryCode<2> ( std :: string cc ) : m_String { std :: move ( cc ) } { " "} " + "struct CountryCode<3> { " + "CountryCode<3> ( std :: string cc ) ; " + "} ; " "CountryCode<3> :: CountryCode<3> ( std :: string cc ) : m_String { std :: move ( cc ) } { " "}"; ASSERT_EQUALS(exp, tok(code)); @@ -4114,6 +4125,42 @@ private: ASSERT_EQUALS(code, tok(code)); } + void template164() { // #9394 + const char code[] = "template \n" + "struct A {\n" + " A();\n" + " ~A();\n" + " static void f();\n" + "};\n" + "template \n" + "A::A() { }\n" + "template \n" + "A::~A() { }\n" + "template \n" + "void A::f() { }\n" + "template class A;\n" + "template class A;"; + const char exp[] = "struct A ; " + "struct A ; " + "struct A { " + "A ( ) ; " + "~ A ( ) ; " + "static void f ( ) ; " + "} ; " + "A :: A ( ) { } " + "A :: ~ A ( ) { } " + "void A :: f ( ) { } " + "struct A { " + "A ( ) ; " + "~ A ( ) ; " + "static void f ( ) ; " + "} ; " + "A :: A ( ) { } " + "A :: ~ A ( ) { } " + "void A :: f ( ) { }"; + 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"