diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index e72c5d24a..532579a51 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1151,9 +1151,16 @@ void Tokenizer::simplifyTypedef() } } else { if (tok2->strAt(-1) == "::") { - // Don't replace this typename if it's preceded by "::" unless it's a namespace - if (!spaceInfo.empty() && (tok2->strAt(-2) == spaceInfo[0].className) && spaceInfo[0].isNamespace) { - tok2->tokAt(-3)->deleteNext(2); + std::size_t relativeSpaceInfoSize = spaceInfo.size(); + Token * tokBeforeType = tok2->previous(); + while (relativeSpaceInfoSize != 0 && + tokBeforeType && tokBeforeType->str() == "::" && + tokBeforeType->strAt(-1) == spaceInfo[relativeSpaceInfoSize-1].className) { + tokBeforeType = tokBeforeType->tokAt(-2); + --relativeSpaceInfoSize; + } + if (tokBeforeType && tokBeforeType->str() != "::") { + Token::eraseTokens(tokBeforeType, tok2); simplifyType = true; } } else if (Token::Match(tok2->previous(), "case|;|{|} %type% :")) { diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index b7c772899..8cc7bd3ce 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -960,6 +960,62 @@ private: "A::B::C::INT_C A::B::C::funC() { return c; }" "A::B::C::D::LONG_D A::B::C::D::funD() { return d; }"; + const char codeFullSpecified[] = "class A {\n" + "public:\n" + " typedef char CHAR_A;\n" + " A::CHAR_A funA();\n" + " class B {\n" + " public:\n" + " typedef short SHRT_B;\n" + " A::B::SHRT_B funB();\n" + " class C {\n" + " public:\n" + " typedef int INT_C;\n" + " A::B::C::INT_C funC();\n" + " struct D {\n" + " typedef long LONG_D;\n" + " A::B::C::D::LONG_D funD();\n" + " A::B::C::D::LONG_D d;\n" + " };\n" + " A::B::C::INT_C c;\n" + " };\n" + " A::B::SHRT_B b;\n" + " };\n" + " A::CHAR_A a;\n" + "};\n" + "A::CHAR_A A::funA() { return a; }\n" + "A::B::SHRT_B A::B::funB() { return b; }\n" + "A::B::C::INT_C A::B::C::funC() { return c; }" + "A::B::C::D::LONG_D A::B::C::D::funD() { return d; }"; + + const char codePartialSpecified[] = "class A {\n" + "public:\n" + " typedef char CHAR_A;\n" + " CHAR_A funA();\n" + " class B {\n" + " public:\n" + " typedef short SHRT_B;\n" + " B::SHRT_B funB();\n" + " class C {\n" + " public:\n" + " typedef int INT_C;\n" + " C::INT_C funC();\n" + " struct D {\n" + " typedef long LONG_D;\n" + " D::LONG_D funD();\n" + " C::D::LONG_D d;\n" + " };\n" + " B::C::INT_C c;\n" + " };\n" + " B::SHRT_B b;\n" + " };\n" + " CHAR_A a;\n" + "};\n" + "A::CHAR_A A::funA() { return a; }\n" + "A::B::SHRT_B A::B::funB() { return b; }\n" + "A::B::C::INT_C A::B::C::funC() { return c; }" + "A::B::C::D::LONG_D A::B::C::D::funD() { return d; }"; + const char expected[] = "class A { " "public: " @@ -990,6 +1046,8 @@ private: "long A :: B :: C :: D :: funD ( ) { return d ; }"; ASSERT_EQUALS(expected, tok(code, false)); + ASSERT_EQUALS(expected, tok(codePartialSpecified, false)); + ASSERT_EQUALS(expected, tok(codeFullSpecified, false)); } void simplifyTypedef34() {