diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 22eab99c1..346ad5184 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -9323,22 +9323,23 @@ void Tokenizer::simplifyStructDecl() unsigned int count = 0; // Skip simplification of unions in class definition - std::list skip; + std::list skip; // true = in function, false = not in function skip.push_back(false); for (Token *tok = _tokens; tok; tok = tok->next()) { Token *restart; + // check for start of scope and determine if it is in a function if (tok->str() == "{") - skip.push_back(!Token::Match(tok->previous(), "const|)")); + skip.push_back(Token::Match(tok->previous(), "const|)")); + + // end of scope else if (tok->str() == "}" && !skip.empty()) skip.pop_back(); - else if (!skip.empty() && skip.back() && tok->str() == "union") - continue; // check for named struct/union - if (Token::Match(tok, "struct|union %type% :|{")) + else if (Token::Match(tok, "class|struct|union %type% :|{")) { Token *isStatic = tok->previous() && tok->previous()->str() == "static" ? tok->previous() : NULL; Token *type = tok->next(); @@ -9348,7 +9349,7 @@ void Tokenizer::simplifyStructDecl() next = next->next(); if (!next) continue; - + skip.push_back(false); tok = next->link(); restart = next; @@ -9372,6 +9373,8 @@ void Tokenizer::simplifyStructDecl() // check for anonymous struct/union else if (Token::Match(tok, "struct|union {")) { + bool inFunction = skip.back(); + skip.push_back(false); Token *tok1 = tok; restart = tok->next(); @@ -9391,10 +9394,10 @@ void Tokenizer::simplifyStructDecl() tok->insertToken(name.c_str()); } - // unnamed anonymous struct/union so remove it + // unnamed anonymous struct/union so possibly remove it else if (tok->next() && tok->next()->str() == ";") { - if (tok1->str() == "union") + if (tok1->str() == "union" && inFunction) { // Try to create references in the union.. Token *tok2 = tok1->tokAt(2); @@ -9428,18 +9431,22 @@ void Tokenizer::simplifyStructDecl() } } - tok1->deleteThis(); - if (tok1->next() == tok) + // don't remove unnamed anonymous unions from a class, struct or union + if (!(tok1->str() == "union" && !inFunction)) { tok1->deleteThis(); - tok = tok1; - } - else - tok1->deleteThis(); - restart = tok1->previous(); - tok->deleteThis(); - if (tok->next()) + if (tok1->next() == tok) + { + tok1->deleteThis(); + tok = tok1; + } + else + tok1->deleteThis(); + restart = tok1->previous(); tok->deleteThis(); + if (tok->next()) + tok->deleteThis(); + } } if (!restart) diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 5f169d74a..a87acda5a 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -335,6 +335,7 @@ private: // struct ABC { } abc; => struct ABC { }; ABC abc; TEST_CASE(simplifyStructDecl1); TEST_CASE(simplifyStructDecl2); // ticket #2579 + TEST_CASE(simplifyStructDecl3); // register int var; => int var; // inline int foo() {} => int foo() {} @@ -6931,6 +6932,129 @@ private: ASSERT_EQUALS(expected, tok(code, false)); } + void simplifyStructDecl3() + { + { + const char code[] = "class ABC { } abc;"; + const char expected[] = "class ABC { } ; ABC abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class ABC { } * pabc;"; + const char expected[] = "class ABC { } ; ABC * pabc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class ABC { } abc[4];"; + const char expected[] = "class ABC { } ; ABC abc [ 4 ] ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class ABC { } abc, def;"; + const char expected[] = "class ABC { } ; ABC abc ; ABC def ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class ABC { } abc, * pabc;"; + const char expected[] = "class ABC { } ; ABC abc ; ABC * pabc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class ABC { class DEF {} def; } abc;"; + const char expected[] = "class ABC { class DEF { } ; DEF def ; } ; ABC abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class { } abc;"; + const char expected[] = "class { } abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class { } * pabc;"; + const char expected[] = "class { } * pabc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class { } abc[4];"; + const char expected[] = "class { } abc [ 4 ] ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class { } abc, def;"; + const char expected[] = "class { } abc , def ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class { } abc, * pabc;"; + const char expected[] = "class { } abc , * pabc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct { class DEF {} def; } abc;"; + const char expected[] = "struct Anonymous0 { class DEF { } ; DEF def ; } ; Anonymous0 abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class ABC { struct {} def; } abc;"; + const char expected[] = "class ABC { struct Anonymous0 { } ; Anonymous0 def ; } ; ABC abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class { class {} def; } abc;"; + const char expected[] = "class { class { } def ; } abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class ABC { struct {} def; };"; + const char expected[] = "class ABC { struct Anonymous0 { } ; Anonymous0 def ; } ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class ABC : public XYZ { struct {} def; };"; + const char expected[] = "class ABC : public XYZ { struct Anonymous0 { } ; Anonymous0 def ; } ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class { int x; }; int y;"; + const char expected[] = "class { int x ; } ; int y ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class { int x; };"; + const char expected[] = "class { int x ; } ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class { };"; + const char expected[] = "class { } ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "class { struct { struct { } ; } ; };"; + const char expected[] = "class { } ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + } + void removeUnwantedKeywords() { ASSERT_EQUALS("int var ;", tok("register int var ;", true));