Skip to content

Commit 0dad8b6

Browse files
IOBYTEdanmar
authored andcommitted
Fixed danmar#6268 (False positive functionStatic (inconclusive) - nested namespaces)
1 parent 1779921 commit 0dad8b6

File tree

3 files changed

+112
-6
lines changed

3 files changed

+112
-6
lines changed

lib/tokenize.cpp

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,15 +1067,42 @@ void Tokenizer::simplifyTypedef()
10671067
pattern1 = pattern;
10681068

10691069
if (pattern1.find("::") != std::string::npos) { // has a "something ::"
1070-
if (tok2->strAt(-1) == "::") {
1071-
tok2->tokAt(-2)->deleteNext();
1072-
globalScope = true;
1070+
Token *start = tok2;
1071+
size_t count = 0;
1072+
int back = int(classLevel) - 1;
1073+
bool good = true;
1074+
// check for extra qualification
1075+
while (back >= 0 && Token::Match(start->tokAt(-2), "%type% ::")) {
1076+
if (start->strAt(-2) == spaceInfo[back].className) {
1077+
start = start->tokAt(-2);
1078+
back--;
1079+
count++;
1080+
} else {
1081+
good = false;
1082+
break;
1083+
}
10731084
}
1085+
// check global namespace
1086+
if (good && back == 0 && start->strAt(-1) == "::")
1087+
good = false;
10741088

1075-
for (std::size_t i = classLevel; i < spaceInfo.size(); ++i) {
1076-
tok2->deleteNext(2);
1089+
if (good) {
1090+
// remove any extra qualification if present
1091+
while (count--)
1092+
tok2->tokAt(-3)->deleteNext(2);
1093+
1094+
// remove global namespace if present
1095+
if (tok2->strAt(-1) == "::") {
1096+
tok2->tokAt(-2)->deleteNext();
1097+
globalScope = true;
1098+
}
1099+
1100+
// remove qualification if present
1101+
for (std::size_t i = classLevel; i < spaceInfo.size(); ++i) {
1102+
tok2->deleteNext(2);
1103+
}
1104+
simplifyType = true;
10771105
}
1078-
simplifyType = true;
10791106
} else if ((inScope && !exitThisScope) || inMemberFunc) {
10801107
if (tok2->strAt(-1) == "::") {
10811108
// Don't replace this typename if it's preceded by "::" unless it's a namespace

test/testclass.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ class TestClass : public TestFixture {
144144
TEST_CASE(const61); // ticket #5606
145145
TEST_CASE(const62); // ticket #5701
146146
TEST_CASE(const63); // ticket #5983
147+
TEST_CASE(const64); // ticket #6268
147148
TEST_CASE(const_handleDefaultParameters);
148149
TEST_CASE(const_passThisToMemberOfOtherClass);
149150
TEST_CASE(assigningPointerToPointerIsNotAConstOperation);
@@ -4911,6 +4912,21 @@ class TestClass : public TestFixture {
49114912
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'A::clear' can be const.\n", errout.str());
49124913
}
49134914

4915+
void const64() {
4916+
checkConst("namespace B {\n"
4917+
" namespace D {\n"
4918+
" typedef int DKIPtr;\n"
4919+
" }\n"
4920+
" class ZClass {\n"
4921+
" void set(const ::B::D::DKIPtr& p) {\n"
4922+
" membervariable = p;\n"
4923+
" }\n"
4924+
" ::B::D::DKIPtr membervariable;\n"
4925+
" };\n"
4926+
"}");
4927+
ASSERT_EQUALS("", errout.str());
4928+
}
4929+
49144930
void const_handleDefaultParameters() {
49154931
checkConst("struct Foo {\n"
49164932
" void foo1(int i, int j = 0) {\n"

test/testsimplifytypedef.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ class TestSimplifyTypedef : public TestFixture {
144144
TEST_CASE(simplifyTypedef107); // ticket #3963 - bad code => segmentation fault
145145
TEST_CASE(simplifyTypedef108); // ticket #4777
146146
TEST_CASE(simplifyTypedef109); // ticket #1823 - rvalue reference
147+
TEST_CASE(simplifyTypedef110); // ticket #6268
147148

148149
TEST_CASE(simplifyTypedefFunction1);
149150
TEST_CASE(simplifyTypedefFunction2); // ticket #1685
@@ -2398,6 +2399,68 @@ class TestSimplifyTypedef : public TestFixture {
23982399
ASSERT_EQUALS("", errout.str());
23992400
}
24002401

2402+
void simplifyTypedef110() {
2403+
const char code[] = "namespace A {\n"
2404+
" namespace B {\n"
2405+
" namespace D {\n"
2406+
" typedef int DKIPtr;\n"
2407+
" }\n"
2408+
" struct ZClass {\n"
2409+
" void set1(const A::B::D::DKIPtr& p) {\n"
2410+
" membervariable1 = p;\n"
2411+
" }\n"
2412+
" void set2(const ::A::B::D::DKIPtr& p) {\n"
2413+
" membervariable2 = p;\n"
2414+
" }\n"
2415+
" void set3(const B::D::DKIPtr& p) {\n"
2416+
" membervariable3 = p;\n"
2417+
" }\n"
2418+
" void set4(const ::B::D::DKIPtr& p) {\n"
2419+
" membervariable4 = p;\n"
2420+
" }\n"
2421+
" void set5(const C::D::DKIPtr& p) {\n"
2422+
" membervariable5 = p;\n"
2423+
" }\n"
2424+
" A::B::D::DKIPtr membervariable1;\n"
2425+
" ::A::B::D::DKIPtr membervariable2;\n"
2426+
" B::D::DKIPtr membervariable3;\n"
2427+
" ::B::D::DKIPtr membervariable4;\n"
2428+
" C::D::DKIPtr membervariable5;\n"
2429+
" };\n"
2430+
" }\n"
2431+
"}";
2432+
const char expected[] = "namespace A { "
2433+
"namespace B { "
2434+
"struct ZClass { "
2435+
"void set1 ( const int & p ) { "
2436+
"membervariable1 = p ; "
2437+
"} "
2438+
"void set2 ( const int & p ) { "
2439+
"membervariable2 = p ; "
2440+
"} "
2441+
"void set3 ( const int & p ) { "
2442+
"membervariable3 = p ; "
2443+
"} "
2444+
"void set4 ( const :: B :: D :: DKIPtr & p ) { "
2445+
"membervariable4 = p ; "
2446+
"} "
2447+
"void set5 ( const C :: D :: DKIPtr & p ) { "
2448+
"membervariable5 = p ; "
2449+
"} "
2450+
"int membervariable1 ; "
2451+
"int membervariable2 ; "
2452+
"int membervariable3 ; "
2453+
":: B :: D :: DKIPtr membervariable4 ; "
2454+
"C :: D :: DKIPtr membervariable5 ; "
2455+
"} ; "
2456+
"} "
2457+
"}";
2458+
2459+
checkSimplifyTypedef(code);
2460+
ASSERT_EQUALS(expected, tok(code));
2461+
ASSERT_EQUALS("", errout.str());
2462+
}
2463+
24012464
void simplifyTypedefFunction1() {
24022465
{
24032466
const char code[] = "typedef void (*my_func)();\n"

0 commit comments

Comments
 (0)