From d39956414f1953dcb8f68aa0b13c1d5b6a143e1f Mon Sep 17 00:00:00 2001 From: IOBYTE Date: Thu, 21 Jan 2021 13:47:51 -0500 Subject: [PATCH] fix #10122, #10124 and #10125 (debug: Executable scope 'x' with unknown function.) (#3073) --- lib/symboldatabase.cpp | 4 +-- lib/tokenize.cpp | 9 ++++-- test/testsymboldatabase.cpp | 60 +++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index adf5cfdd8..1bc453f67 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2371,8 +2371,8 @@ static bool typesMatch( tok2 = tok2->next(); // update parser token positions if (tok1 && tok2) { - *new_first = tok1; - *new_second = tok2; + *new_first = tok1->previous(); + *new_second = tok2->previous(); return true; } } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index ec4f4e3bc..2f50794e9 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -561,8 +561,11 @@ void Tokenizer::simplifyUsingToTypedef() { for (Token *tok = list.front(); tok; tok = tok->next()) { // using a::b; => typedef a::b b; - if (Token::Match(tok, "[;{}] using %name% :: %name% ::|;") && !tok->tokAt(2)->isKeyword()) { - Token *endtok = tok->tokAt(5); + if ((Token::Match(tok, "[;{}] using %name% :: %name% ::|;") && !tok->tokAt(2)->isKeyword()) || + (Token::Match(tok, "[;{}] using :: %name% :: %name% ::|;") && !tok->tokAt(3)->isKeyword())) { + Token *endtok = tok->tokAt(5); + if (Token::Match(endtok, "%name%")) + endtok = endtok->next(); while (Token::Match(endtok, ":: %name%")) endtok = endtok->tokAt(2); if (endtok && endtok->str() == ";") { @@ -1904,7 +1907,7 @@ namespace { std::string::size_type index = scope.size(); std::string::size_type new_index = std::string::npos; bool match = true; - while (tok2->strAt(-1) == "::") { + while (Token::Match(tok2->tokAt(-2), "%name% ::") && !tok2->tokAt(-2)->isKeyword()) { std::string last; if (match && !scope1.empty()) { new_index = scope1.rfind(' ', index - 1); diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 6838f8c04..1b57f3ca6 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -400,6 +400,9 @@ private: TEST_CASE(findFunction33); // #9885 variadic function TEST_CASE(findFunction34); // #10061 TEST_CASE(findFunction35); + TEST_CASE(findFunction36); // #10122 + TEST_CASE(findFunction37); // #10124 + TEST_CASE(findFunction38); // #10152 TEST_CASE(findFunctionContainer); TEST_CASE(findFunctionExternC); TEST_CASE(findFunctionGlobalScope); // ::foo @@ -6262,6 +6265,63 @@ private: ASSERT_EQUALS(5, foo->function()->tokenDef->linenr()); } + void findFunction36() { // #10122 + GET_SYMBOL_DB("namespace external {\n" + " enum class T { };\n" + "}\n" + "namespace ns {\n" + " class A {\n" + " public:\n" + " void f(external::T);\n" + " };\n" + "}\n" + "namespace ns {\n" + " void A::f(external::T link_type) { }\n" + "}"); + ASSERT_EQUALS("", errout.str()); + const Token *functok = Token::findsimplematch(tokenizer.tokens(), "f ( external :: T link_type )"); + ASSERT(functok); + ASSERT(functok->function()); + ASSERT(functok->function()->name() == "f"); + ASSERT_EQUALS(7, functok->function()->tokenDef->linenr()); + } + + void findFunction37() { // #10124 + GET_SYMBOL_DB("namespace ns {\n" + " class V { };\n" + "}\n" + "class A {\n" + "public:\n" + " void f(const ns::V&);\n" + "};\n" + "using ::ns::V;\n" + "void A::f(const V&) { }"); + ASSERT_EQUALS("", errout.str()); + const Token *functok = Token::findsimplematch(tokenizer.tokens(), "f ( const :: ns :: V & )"); + ASSERT(functok); + ASSERT(functok->function()); + ASSERT(functok->function()->name() == "f"); + ASSERT_EQUALS(6, functok->function()->tokenDef->linenr()); + } + + void findFunction38() { // #10125 + GET_SYMBOL_DB("namespace ns {\n" + " class V { };\n" + " using Var = V;\n" + "}\n" + "class A {\n" + " void f(const ns::Var&);\n" + "};\n" + "using ::ns::Var;\n" + "void A::f(const Var&) {}"); + ASSERT_EQUALS("", errout.str()); + const Token *functok = Token::findsimplematch(tokenizer.tokens(), "f ( const :: ns :: V & )"); + ASSERT(functok); + ASSERT(functok->function()); + ASSERT(functok->function()->name() == "f"); + ASSERT_EQUALS(6, functok->function()->tokenDef->linenr()); + } + void findFunctionContainer() { { GET_SYMBOL_DB("void dostuff(std::vector v);\n"