diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 8cfee07e0..dfc2046fc 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -924,6 +924,7 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s // typedef.. simplifyTypedef(); + // enum.. simplifyEnum(); // Remove __asm.. @@ -4702,12 +4703,17 @@ void Tokenizer::simplifyEnum() Token::Match(tok, "enum %type% {")) { Token * tok1; + Token * start = tok; Token * end; + Token * enumType = 0; if (tok->tokAt(1)->str() == "{") tok1 = tok->tokAt(2); else + { + enumType = tok->tokAt(1); tok1 = tok->tokAt(3); + } end = tok1->tokAt(-1)->link(); @@ -4743,6 +4749,7 @@ void Tokenizer::simplifyEnum() bool exitThisScope = false; int exitScope = 0; bool simplifyEnum = false; + bool hasClass = false; for (Token *tok2 = end->next(); tok2; tok2 = tok2->next()) { if (tok2->str() == "}") @@ -4762,6 +4769,7 @@ void Tokenizer::simplifyEnum() else if (!pattern.empty() && Token::Match(tok2, pattern.c_str())) { simplifyEnum = true; + hasClass = true; } else if (inScope && !exitThisScope && tok2->str() == enumName->str()) { @@ -4770,18 +4778,99 @@ void Tokenizer::simplifyEnum() // Don't replace this enum if it's preceded by "::" } else + { simplifyEnum = true; + hasClass = false; + } } if (simplifyEnum) { tok2->str(enumValue->strAt(0)); + if (hasClass) + { + tok2->deleteNext(); + tok2->deleteNext(); + } + simplifyEnum = false; } } } } + + if (enumType) + { + const std::string pattern(className.empty() ? "" : (className + " :: " + enumType->str()).c_str()); + int level = 0; + bool inScope = true; + + bool exitThisScope = false; + int exitScope = 0; + bool simplifyEnum = false; + bool hasClass = false; + for (Token *tok2 = end->next(); tok2; tok2 = tok2->next()) + { + if (tok2->str() == "}") + { + --level; + if (level < 0) + inScope = false; + + if (exitThisScope) + { + if (level < exitScope) + exitThisScope = false; + } + } + else if (tok2->str() == "{") + ++level; + else if (!pattern.empty() && ((Token::Match(tok2, "enum") && Token::Match(tok2->next(), pattern.c_str())) || Token::Match(tok2, pattern.c_str()))) + { + simplifyEnum = true; + hasClass = true; + } + else if (inScope && !exitThisScope && (tok2->str() == enumType->str() || (tok2->str() == "enum" && tok2->next()->str() == enumType->str()))) + { + if (Token::simpleMatch(tok2->previous(), "::")) + { + // Don't replace this enum if it's preceded by "::" + } + else + { + simplifyEnum = true; + hasClass = false; + } + } + + if (simplifyEnum) + { + if (tok2->str() == "enum") + tok2->deleteNext(); + tok2->str("int"); + + if (hasClass) + { + tok2->deleteNext(); + tok2->deleteNext(); + } + + simplifyEnum = false; + } + } + } + + tok1 = start; + while (tok1->next() && tok1->next() != end->next()) + tok1->deleteNext(); + if (start != _tokens) + { + tok1 = start->previous(); + tok1->deleteNext(); + } + else + _tokens->deleteThis(); } } } diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index fe01b165a..024c10126 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -178,6 +178,7 @@ private: TEST_CASE(enum1); TEST_CASE(enum2); TEST_CASE(enum3); + TEST_CASE(enum4); // remove "std::" on some standard functions TEST_CASE(removestd); @@ -2474,10 +2475,10 @@ private: "XYZ e2;"; const char expected[] = - "enum abc { a = 0 , b = 1 , c = 2 } ; ; " - "enum xyz { x = 0 , y = 1 , z = 2 } ; ; " - "enum abc e1 ; " - "enum xyz e2 ;"; + "; ; " + "; ; " + "int e1 ; " + "int e2 ;"; ASSERT_EQUALS(expected, tok(code, false)); } @@ -3145,8 +3146,8 @@ private: void enum1() { - const char code[] = "enum A { a, b, c };"; - const char expected[] = "enum A { a = 0 , b = 1 , c = 2 } ;"; + const char code[] = "enum A { a, b, c }; A c1 = c;"; + const char expected[] = "; int c1 ; c1 = 2 ;"; ASSERT_EQUALS(expected, tok(code, false)); } @@ -3154,7 +3155,7 @@ private: void enum2() { const char code[] = "enum A { a, }; int array[a];"; - const char expected[] = "enum A { a = 0 , } ; int array [ 0 ] ;"; + const char expected[] = "; int array [ 0 ] ;"; ASSERT_EQUALS(expected, tok(code, false)); } @@ -3162,7 +3163,34 @@ private: void enum3() { const char code[] = "enum { a, }; int array[a];"; - const char expected[] = "enum { a = 0 , } ; int array [ 0 ] ;"; + const char expected[] = "; int array [ 0 ] ;"; + + ASSERT_EQUALS(expected, tok(code, false)); + } + + void enum4() + { + const char code[] = "class A {\n" + "public:\n" + " enum EA { a1, a2, a3 };\n" + " EA get() const;\n" + " void put(EA a) { ea = a; ea = a1; }\n" + "private:\n" + " EA ea;\n" + "};\n" + "A::EA A::get() const { return ea; }\n" + "A::EA e = A::a1;"; + + const char expected[] = "class A { " + "public: " + "; " + "int get ( ) const ; " + "void put ( int a ) { ea = a ; ea = 0 ; } " + "private: " + "int ea ; " + "} ; " + "int A :: get ( ) const { return ea ; } " + "int e ; e = 0 ;"; ASSERT_EQUALS(expected, tok(code, false)); }