diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 818de8a08..3b5704d1c 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -921,11 +921,7 @@ namespace { } } - bool canReplace(const Token* tok) { - if (mNameToken == tok) - return false; - if (!Token::Match(tok->previous(), "%name%|;|{|}|(|,|<") && !Token::Match(tok->previous(), "!!. %name% (")) - return false; + static int canReplaceStatic(const Token* tok) { if (!Token::Match(tok, "%name% %name%|*|&|&&|;|(|)|,|::")) { if (Token::Match(tok->previous(), "( %name% =") && Token::Match(tok->linkAt(-1), ") %name%|{") && !tok->tokAt(-2)->isKeyword()) return true; @@ -933,8 +929,19 @@ namespace { return true; if (Token::Match(tok->previous(), "new %name% [")) return true; - if (Token::Match(tok->previous(), "< %name% >")) + if (Token::Match(tok->previous(), "< %name%") && tok->previous()->findClosingBracket()) return true; + if (Token::Match(tok->previous(), ", %name% >|>>")) { + for (const Token* prev = tok->previous(); prev; prev = prev->previous()) { + if (Token::Match(prev, "[;{}(]")) + break; + if (prev->str() == "<" && prev->findClosingBracket() == tok->next()) + return true; + if (prev->str() == ")") + prev = prev->link(); + } + return true; + } if (Token::Match(tok->previous(), "public|protected|private")) return true; if (Token::Match(tok->previous(), ", %name% :")) { @@ -951,6 +958,19 @@ namespace { } return false; } + return -1; + } + + bool canReplace(const Token* tok) { + if (mNameToken == tok) + return false; + if (!Token::Match(tok->previous(), "%name%|;|{|}|(|,|<") && !Token::Match(tok->previous(), "!!. %name% (")) + return false; + { + const int res = canReplaceStatic(tok); + if (res == 0 || res == 1) + return res != 0; + } if (Token::Match(tok->previous(), "%name%") && !tok->previous()->isKeyword()) return false; if (Token::simpleMatch(tok->next(), "(") && Token::Match(tok->linkAt(1), ") %name%|{")) @@ -1843,7 +1863,7 @@ void Tokenizer::simplifyTypedefCpp() } else if (Token::Match(tok2->tokAt(-2), "%type% *|&")) { // Ticket #5868: Don't substitute variable names } else if (tok2->previous()->str() != ".") { - simplifyType = true; + simplifyType = (TypedefSimplifier::canReplaceStatic(tok2) != 0); } } } diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index d0947e3e1..b4d68c792 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -812,7 +812,7 @@ private: } void garbageCode85() { // #6784 - ASSERT_THROW(checkCode("{ } { } typedef void ( *VoidFunc() ) ( ) ; VoidFunc"), InternalError); // do not crash + checkCode("{ } { } typedef void ( *VoidFunc() ) ( ) ; VoidFunc"); // do not crash } void garbageCode86() { // #6785 diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 6ca82db5b..efc9f0b44 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -49,6 +49,7 @@ private: TEST_CASE(canreplace1); TEST_CASE(canreplace2); TEST_CASE(canreplace3); + TEST_CASE(canreplace4); TEST_CASE(cconst); TEST_CASE(cstruct1); TEST_CASE(cstruct2); @@ -353,6 +354,14 @@ private: ASSERT_EQUALS("struct S { const char * g ( ) const { return s . c_str ( ) ; } std :: string s ; } ;", simplifyTypedefC(code1)); } + void canreplace4() { + const char code1[] = "typedef std::vector X;\n" // #12026 + "struct S {\n" + " enum E { X };\n" + "};\n"; + ASSERT_EQUALS("struct S { enum E { X } ; } ;", simplifyTypedef(code1)); + } + void cconst() { const char code1[] = "typedef void* HWND;\n" "const HWND x;";