From 0dad8b64e8e57090ed534d748797369fdc01a8a7 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Thu, 27 Nov 2014 06:29:33 +0100 Subject: [PATCH] Fixed #6268 (False positive functionStatic (inconclusive) - nested namespaces) --- lib/tokenize.cpp | 39 ++++++++++++++++++---- test/testclass.cpp | 16 +++++++++ test/testsimplifytypedef.cpp | 63 ++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 6 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index fee2f7d3a..f56a0c949 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1067,15 +1067,42 @@ void Tokenizer::simplifyTypedef() pattern1 = pattern; if (pattern1.find("::") != std::string::npos) { // has a "something ::" - if (tok2->strAt(-1) == "::") { - tok2->tokAt(-2)->deleteNext(); - globalScope = true; + Token *start = tok2; + size_t count = 0; + int back = int(classLevel) - 1; + bool good = true; + // check for extra qualification + while (back >= 0 && Token::Match(start->tokAt(-2), "%type% ::")) { + if (start->strAt(-2) == spaceInfo[back].className) { + start = start->tokAt(-2); + back--; + count++; + } else { + good = false; + break; + } } + // check global namespace + if (good && back == 0 && start->strAt(-1) == "::") + good = false; - for (std::size_t i = classLevel; i < spaceInfo.size(); ++i) { - tok2->deleteNext(2); + if (good) { + // remove any extra qualification if present + while (count--) + tok2->tokAt(-3)->deleteNext(2); + + // remove global namespace if present + if (tok2->strAt(-1) == "::") { + tok2->tokAt(-2)->deleteNext(); + globalScope = true; + } + + // remove qualification if present + for (std::size_t i = classLevel; i < spaceInfo.size(); ++i) { + tok2->deleteNext(2); + } + simplifyType = true; } - simplifyType = true; } else if ((inScope && !exitThisScope) || inMemberFunc) { if (tok2->strAt(-1) == "::") { // Don't replace this typename if it's preceded by "::" unless it's a namespace diff --git a/test/testclass.cpp b/test/testclass.cpp index 26cdd8585..09b24ddfc 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -144,6 +144,7 @@ private: TEST_CASE(const61); // ticket #5606 TEST_CASE(const62); // ticket #5701 TEST_CASE(const63); // ticket #5983 + TEST_CASE(const64); // ticket #6268 TEST_CASE(const_handleDefaultParameters); TEST_CASE(const_passThisToMemberOfOtherClass); TEST_CASE(assigningPointerToPointerIsNotAConstOperation); @@ -4911,6 +4912,21 @@ private: ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'A::clear' can be const.\n", errout.str()); } + void const64() { + checkConst("namespace B {\n" + " namespace D {\n" + " typedef int DKIPtr;\n" + " }\n" + " class ZClass {\n" + " void set(const ::B::D::DKIPtr& p) {\n" + " membervariable = p;\n" + " }\n" + " ::B::D::DKIPtr membervariable;\n" + " };\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } + void const_handleDefaultParameters() { checkConst("struct Foo {\n" " void foo1(int i, int j = 0) {\n" diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index a0a7c080e..1652aae0b 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -144,6 +144,7 @@ private: TEST_CASE(simplifyTypedef107); // ticket #3963 - bad code => segmentation fault TEST_CASE(simplifyTypedef108); // ticket #4777 TEST_CASE(simplifyTypedef109); // ticket #1823 - rvalue reference + TEST_CASE(simplifyTypedef110); // ticket #6268 TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -2398,6 +2399,68 @@ private: ASSERT_EQUALS("", errout.str()); } + void simplifyTypedef110() { + const char code[] = "namespace A {\n" + " namespace B {\n" + " namespace D {\n" + " typedef int DKIPtr;\n" + " }\n" + " struct ZClass {\n" + " void set1(const A::B::D::DKIPtr& p) {\n" + " membervariable1 = p;\n" + " }\n" + " void set2(const ::A::B::D::DKIPtr& p) {\n" + " membervariable2 = p;\n" + " }\n" + " void set3(const B::D::DKIPtr& p) {\n" + " membervariable3 = p;\n" + " }\n" + " void set4(const ::B::D::DKIPtr& p) {\n" + " membervariable4 = p;\n" + " }\n" + " void set5(const C::D::DKIPtr& p) {\n" + " membervariable5 = p;\n" + " }\n" + " A::B::D::DKIPtr membervariable1;\n" + " ::A::B::D::DKIPtr membervariable2;\n" + " B::D::DKIPtr membervariable3;\n" + " ::B::D::DKIPtr membervariable4;\n" + " C::D::DKIPtr membervariable5;\n" + " };\n" + " }\n" + "}"; + const char expected[] = "namespace A { " + "namespace B { " + "struct ZClass { " + "void set1 ( const int & p ) { " + "membervariable1 = p ; " + "} " + "void set2 ( const int & p ) { " + "membervariable2 = p ; " + "} " + "void set3 ( const int & p ) { " + "membervariable3 = p ; " + "} " + "void set4 ( const :: B :: D :: DKIPtr & p ) { " + "membervariable4 = p ; " + "} " + "void set5 ( const C :: D :: DKIPtr & p ) { " + "membervariable5 = p ; " + "} " + "int membervariable1 ; " + "int membervariable2 ; " + "int membervariable3 ; " + ":: B :: D :: DKIPtr membervariable4 ; " + "C :: D :: DKIPtr membervariable5 ; " + "} ; " + "} " + "}"; + + checkSimplifyTypedef(code); + ASSERT_EQUALS(expected, tok(code)); + ASSERT_EQUALS("", errout.str()); + } + void simplifyTypedefFunction1() { { const char code[] = "typedef void (*my_func)();\n"