diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 00c61dcad..b42b829d2 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -509,7 +509,7 @@ void Tokenizer::duplicateDeclarationError(const Token *tok1, const Token *tok2, } // check if this statement is a duplicate definition -bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name) +bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name, const Token *typeDef) { // check for an end of definition const Token * tok = *tokPtr; @@ -624,7 +624,11 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name) int level = (tok->previous()->str() == "}") ? 1 : 0; while (tok && tok->previous() && (!Token::Match(tok->previous(), ";|{") || (level != 0))) { - if (tok->previous()->str() == "typedef") + if (tok->previous()->str() == "}") + { + tok = tok->previous()->link(); + } + else if (tok->previous()->str() == "typedef") { duplicateTypedefError(*tokPtr, name, "Typedef"); return true; @@ -636,7 +640,14 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name) } else if (tok->previous()->str() == "struct") { - if (tok->next()->str() != ";") + if (tok->strAt(-2) == "typedef" && + tok->next()->str() == "{" && + typeDef->strAt(3) != "{") + { + // declaration after forward declaration + return true; + } + else if (tok->next()->str() != ";") { duplicateTypedefError(*tokPtr, name, "Struct"); return true; @@ -1373,7 +1384,7 @@ void Tokenizer::simplifyTypedef() { tok2 = tok2->next(); } - else if (duplicateTypedef(&tok2, typeName)) + else if (duplicateTypedef(&tok2, typeName, typeDef)) { exitScope = scope; diff --git a/lib/tokenize.h b/lib/tokenize.h index 913d2ceed..179b6a406 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -580,7 +580,7 @@ public: */ void duplicateEnumError(const Token *tok1, const Token *tok2, const std::string & type); - bool duplicateTypedef(Token **tokPtr, const Token *name); + bool duplicateTypedef(Token **tokPtr, const Token *name, const Token *typeDef); void duplicateTypedefError(const Token *tok1, const Token *tok2, const std::string & type); /** diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index fe8d2b8a9..902b4567f 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -235,6 +235,7 @@ private: TEST_CASE(simplifyTypedef75); // ticket #2426 TEST_CASE(simplifyTypedef76); // ticket #2453 TEST_CASE(simplifyTypedef77); // ticket #2554 + TEST_CASE(simplifyTypedef78); // ticket #2568 TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -3941,7 +3942,7 @@ private: ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:1]: (style) Typedef 'A' hides typedef with same name\n" "[test.cpp:20] -> [test.cpp:1]: (style) Function parameter 'A' hides typedef with same name\n" "[test.cpp:21] -> [test.cpp:1]: (style) Variable 'A' hides typedef with same name\n" - "[test.cpp:24] -> [test.cpp:1]: (style) Struct 'A' hides typedef with same name\n", errout.str()); + "[test.cpp:24] -> [test.cpp:1]: (style) Typedef 'A' hides typedef with same name\n", errout.str()); } void simplifyTypedef36() @@ -4846,6 +4847,16 @@ private: ASSERT_EQUALS(expected, sizeof_(code)); } + void simplifyTypedef78() // ticket #2568 + { + const char code[] = "typedef struct A A_t;\n" + "A_t a;\n" + "typedef struct A { } A_t;\n" + "A_t a1;\n"; + const std::string expected = "; struct A a ; struct A { } ; struct A a1 ;"; + ASSERT_EQUALS(expected, sizeof_(code)); + } + void simplifyTypedefFunction1() { {