diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 82160233b..09aa30144 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -10250,7 +10250,30 @@ void Tokenizer::removeUnnecessaryQualification() } else if (tok->strAt(2) == "~") tok1 = tok1->next(); - if (tok1 && Token::Match(tok1->link(), ") const| {|;|:")) { + if (!tok1 || !Token::Match(tok1->link(), ") const| {|;|:")) { + continue; + } + + const bool isConstructorOrDestructor = + Token::Match(tok, "%type% :: ~| %type%") && (tok->strAt(2) == tok->str() || (tok->strAt(2) == "~" && tok->strAt(3) == tok->str())); + if (!isConstructorOrDestructor) { + bool isPrependedByType = Token::Match(tok->previous(), "%type%"); + if (!isPrependedByType) { + const Token* tok2 = tok->tokAt(-2); + isPrependedByType = Token::Match(tok2, "%type% *|&"); + } + if (!isPrependedByType) { + const Token* tok3 = tok->tokAt(-3); + isPrependedByType = Token::Match(tok3, "%type% * *|&"); + } + if (!isPrependedByType) { + // It's not a constructor declaration and it's not a function declaration so + // this is a function call which can have all the qualifiers just fine - skip. + continue; + } + } + + { std::string qualification; if (portabilityEnabled) qualification = tok->str() + "::"; diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 3b25292fd..e220873bc 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -262,6 +262,12 @@ private: TEST_CASE(removeUnnecessaryQualification8); TEST_CASE(removeUnnecessaryQualification9); // ticket #3151 TEST_CASE(removeUnnecessaryQualification10); // ticket #3310 segmentation fault + TEST_CASE(removeUnnecessaryQualification11); + TEST_CASE(removeUnnecessaryQualification12); + TEST_CASE(removeUnnecessaryQualification13); + TEST_CASE(removeUnnecessaryQualification14); + TEST_CASE(removeUnnecessaryQualification15); + TEST_CASE(removeUnnecessaryQualification16); TEST_CASE(simplifyVarDecl1); // ticket # 2682 segmentation fault TEST_CASE(simplifyVarDecl2); // ticket # 2834 segmentation fault @@ -3951,7 +3957,7 @@ private: " };\n" "}\n"; tok(code, false); - ASSERT_EQUALS("[test.cpp:11]: (portability) The extra qualification 'two::c::' is unnecessary and is considered an error by many compilers.\n", errout.str()); + ASSERT_EQUALS("", errout.str()); } void removeUnnecessaryQualification6() { @@ -4012,6 +4018,62 @@ private: ASSERT_EQUALS("", errout.str()); } + void removeUnnecessaryQualification11() { + const char code[] = "class Fred {\n" + "public:\n" + " Fred& Fred::Magic();\n" + "};\n"; + tok(code, false); + ASSERT_EQUALS("[test.cpp:3]: (portability) The extra qualification 'Fred::' is unnecessary and is considered an error by many compilers.\n", errout.str()); + } + + void removeUnnecessaryQualification12() { + const char code[] = "class Fred {\n" + "public:\n" + " Fred* Fred::Magic();\n" + "};\n"; + tok(code, false); + ASSERT_EQUALS("[test.cpp:3]: (portability) The extra qualification 'Fred::' is unnecessary and is considered an error by many compilers.\n", errout.str()); + } + + void removeUnnecessaryQualification13() { + const char code[] = "class Fred {\n" + "public:\n" + " Fred** Fred::Magic();\n" + "};\n"; + tok(code, false); + ASSERT_EQUALS("[test.cpp:3]: (portability) The extra qualification 'Fred::' is unnecessary and is considered an error by many compilers.\n", errout.str()); + } + + void removeUnnecessaryQualification14() { + const char code[] = "class Fred {\n" + "public:\n" + " Fred*& Fred::Magic();\n" + "};\n"; + tok(code, false); + ASSERT_EQUALS("[test.cpp:3]: (portability) The extra qualification 'Fred::' is unnecessary and is considered an error by many compilers.\n", errout.str()); + } + + void removeUnnecessaryQualification15() { + const char code[] = "class Fred {\n" + "public:\n" + " Fred*& Magic() {\n" + " Fred::Magic(param);\n" + " }\n" + "};\n"; + tok(code, false); + ASSERT_EQUALS("", errout.str()); + } + + void removeUnnecessaryQualification16() { + const char code[] = "class Fred {\n" + "public:\n" + " void Fred::Magic();\n" + "};\n"; + tok(code, false); + ASSERT_EQUALS("[test.cpp:3]: (portability) The extra qualification 'Fred::' is unnecessary and is considered an error by many compilers.\n", errout.str()); + } + void simplifyVarDecl1() { // ticket # 2682 segmentation fault const char code[] = "x a[0] ="; tok(code, false);