diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index e579f8013..09d248965 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1242,6 +1242,9 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s simplifyConst(); + // struct simplification "struct S {} s; => struct S { } ; S s ; + simplifyStructDecl(); + // struct initialization (must be used before simplifyVarDecl) simplifyStructInit(); @@ -6793,3 +6796,51 @@ void Tokenizer::simplifyFuncInWhile() tok = end; } } + +void Tokenizer::simplifyStructDecl() +{ + unsigned int count = 0; + + for (Token *tok = _tokens; tok; tok = tok->next()) + { + // check for named struct/union + if (Token::Match(tok, "struct|union %type% {")) + { + Token *type = tok->next(); + Token *next = tok->tokAt(2); + + tok = tok->tokAt(2)->link(); + + // check for named type + if (Token::Match(tok->next(), "*|&| %type% ,|;|[")) + { + tok->insertToken(";"); + tok = tok->next(); + tok->insertToken(type->str().c_str()); + tok = next; + } + } + + // check for anonymous struct/union + else if (Token::Match(tok, "struct|union {")) + { + Token *tok1 = tok; + + tok = tok->next()->link(); + + if (Token::Match(tok->next(), "*|&| %type% ,|;|[")) + { + std::string name; + + name = "Anonymous" + MathLib::toString(count++); + + tok1->insertToken(name.c_str()); + + tok->insertToken(";"); + tok = tok->next(); + tok->insertToken(name.c_str()); + tok = tok1->next(); + } + } + } +} diff --git a/lib/tokenize.h b/lib/tokenize.h index 6f29d90f8..8a0178771 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -289,6 +289,12 @@ public: /** Struct initialization */ void simplifyStructInit(); + /** Struct simplification + * "struct S { } s;" => "struct S { }; S s;" + */ + + void simplifyStructDecl(); + /** * Remove redundant paranthesis: * - "((x))" => "(x)" diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 02e09685f..d84584033 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -225,6 +225,9 @@ private: // struct ABC abc = { .a = 3 }; => struct ABC abc; abc.a = 3; TEST_CASE(initstruct); + + // struct ABC { } abc; => struct ABC { }; ABC abc; + TEST_CASE(simplifyStructDecl); } std::string tok(const char code[], bool simplify = true) @@ -4126,6 +4129,99 @@ private: ASSERT_EQUALS("; struct A a ; a . buf = & key ;", tok("; struct A a = { .buf = &key };")); ASSERT_EQUALS("; struct ABC abc ; abc . a = 3 ; abc . b = x ; abc . c = & key ;", tok("; struct ABC abc = { .a = 3, .b = x, .c = &key };")); } + + void simplifyStructDecl() + { + { + const char code[] = "struct ABC { } abc;"; + const char expected[] = "struct ABC { } ; ABC abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct ABC { } * pabc;"; + const char expected[] = "struct ABC { } ; ABC * pabc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct ABC { } abc[4];"; + const char expected[] = "struct ABC { } ; ABC abc [ 4 ] ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct ABC { } abc, def;"; + const char expected[] = "struct ABC { } ; ABC abc ; ABC def ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct ABC { } abc, * pabc;"; + const char expected[] = "struct ABC { } ; ABC abc ; ABC * pabc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct ABC { struct DEF {} def; } abc;"; + const char expected[] = "struct ABC { struct DEF { } ; DEF def ; } ; ABC abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct { } abc;"; + const char expected[] = "struct Anonymous0 { } ; Anonymous0 abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct { } * pabc;"; + const char expected[] = "struct Anonymous0 { } ; Anonymous0 * pabc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct { } abc[4];"; + const char expected[] = "struct Anonymous0 { } ; Anonymous0 abc [ 4 ] ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct { } abc, def;"; + const char expected[] = "struct Anonymous0 { } ; Anonymous0 abc ; Anonymous0 def ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct { } abc, * pabc;"; + const char expected[] = "struct Anonymous0 { } ; Anonymous0 abc ; Anonymous0 * pabc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct { struct DEF {} def; } abc;"; + const char expected[] = "struct Anonymous0 { struct DEF { } ; DEF def ; } ; Anonymous0 abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct ABC { struct {} def; } abc;"; + const char expected[] = "struct ABC { struct Anonymous0 { } ; Anonymous0 def ; } ; ABC abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "struct { struct {} def; } abc;"; + const char expected[] = "struct Anonymous0 { struct Anonymous1 { } ; Anonymous1 def ; } ; Anonymous0 abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + + { + const char code[] = "union ABC { int i; float f; } abc;"; + const char expected[] = "union ABC { int i ; float f ; } ; ABC abc ;"; + ASSERT_EQUALS(expected, tok(code, false)); + } + } }; REGISTER_TEST(TestSimplifyTokens) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 88f8fc548..2aef71966 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -118,6 +118,7 @@ private: TEST_CASE(varid12); TEST_CASE(varid13); TEST_CASE(varid14); + TEST_CASE(varid15); TEST_CASE(varidStl); TEST_CASE(varid_delete); TEST_CASE(varid_functions); @@ -1511,6 +1512,23 @@ private: ASSERT_EQUALS(expected, actual); } + void varid15() + { + const std::string actual = tokenizeDebugListing( + "struct S {\n" + " struct T {\n" + " } t;\n" + "} s;"); + + const std::string expected("\n\n##file 0\n" + "1: struct S {\n" + "2: struct T {\n" + "3: } ; T t@1 ;\n" + "4: } ; S s@2 ;\n"); + + ASSERT_EQUALS(expected, actual); + } + void varidStl() { const std::string actual = tokenizeDebugListing(