Fixed #1215 (are enums processed properly?)

This commit is contained in:
Robert Reif 2010-01-04 17:22:06 +01:00 committed by Daniel Marjamäki
parent 5912035696
commit 13f627d0d5
3 changed files with 141 additions and 3 deletions

View File

@ -721,6 +721,8 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[])
// typedef..
simplifyTypedef();
simplifyEnum();
// Remove __asm..
for (Token *tok = _tokens; tok; tok = tok->next())
{
@ -4393,6 +4395,118 @@ void Tokenizer::simplifyNestedStrcat()
}
void Tokenizer::simplifyEnum()
{
std::string className;
int classLevel = 0;
for (Token *tok = _tokens; tok; tok = tok->next())
{
if (Token::Match(tok, "class|namespace %any%"))
{
className = tok->next()->str();
classLevel = 0;
continue;
}
else if (tok->str() == "}")
{
--classLevel;
if (classLevel < 0)
className = "";
continue;
}
else if (tok->str() == "{")
{
++classLevel;
continue;
}
else if (Token::Match(tok, "enum %type% {"))
{
Token * tok1;
Token * end;
if (tok->tokAt(1)->str() == "{")
tok1 = tok->tokAt(2);
else
tok1 = tok->tokAt(3);
end = tok1->tokAt(-1)->link();
long last_value = -1;
for (; tok1 && tok1 != end; tok1 = tok1->next())
{
Token * enumName = 0;
Token * enumValue = 0;
if (Token::Match(tok1, "%type% ,|}"))
{
enumName = tok1;
last_value++;
tok1->insertToken("=");
tok1 = tok1->next();
tok1->insertToken(MathLib::toString<long>(last_value).c_str());
enumValue = tok1->next();
}
else if (Token::Match(tok1, "%type% = %num% ,|}"))
{
enumName = tok1;
last_value = atoi(tok1->strAt(2));
enumValue = tok1->tokAt(2);
}
if (enumName && enumValue)
{
const std::string pattern(className.empty() ? "" : (className + " :: " + enumName->str()).c_str());
int level = 0;
bool inScope = true;
bool exitThisScope = false;
int exitScope = 0;
bool simplifyEnum = 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, pattern.c_str()))
{
simplifyEnum = true;
}
else if (inScope && !exitThisScope && tok2->str() == enumName->str())
{
if (Token::simpleMatch(tok2->previous(), "::"))
{
// Don't replace this enum if it's preceded by "::"
}
else
simplifyEnum = true;
}
if (simplifyEnum)
{
tok2->str(enumValue->strAt(0));
simplifyEnum = false;
}
}
}
}
}
}
}
//---------------------------------------------------------------------------
// Helper functions for handling the tokens list
//---------------------------------------------------------------------------

View File

@ -326,6 +326,11 @@ private:
*/
void simplifyWhile0();
/**
* Replace enum with constant value
*/
void simplifyEnum();
/**
* Remove exception specifications. This function calls itself recursively.
* @param tok First token in scope to cleanup

View File

@ -154,6 +154,9 @@ private:
// simplify "while (0)"
TEST_CASE(while0);
TEST_CASE(while1);
TEST_CASE(enum1);
TEST_CASE(enum2);
}
std::string tok(const char code[], bool simplify = true)
@ -2303,7 +2306,7 @@ private:
"typedef struct s S, * PS\n;"
"typedef struct t { int a; } T, *TP;"
"typedef enum { a = 0 , b = 1 , c = 2 } abc;"
"typedef enum xyz { a = 0 , b = 1 , c = 2 } ABC;"
"typedef enum xyz { x = 0 , y = 1 , z = 2 } XYZ;"
"typedef vector<int> V1;"
"typedef std::vector<int> V2;"
"typedef std::vector<std::vector<int> > V3;"
@ -2316,7 +2319,7 @@ private:
"T t;\n"
"TP tp;\n"
"abc e1;\n"
"ABC e2;\n"
"XYZ e2;\n"
"V1 v1;\n"
"V2 v2;\n"
"V3 v3;";
@ -2329,7 +2332,7 @@ private:
"typedef struct s S ; typedef struct s * PS ; "
"struct t { int a ; } ; typedef struct t T ; typedef struct t * TP ; "
"enum abc { a = 0 , b = 1 , c = 2 } ; typedef enum abc abc ; "
"enum xyz { a = 0 , b = 1 , c = 2 } ; typedef enum xyz ABC ; "
"enum xyz { x = 0 , y = 1 , z = 2 } ; typedef enum xyz XYZ ; "
"typedef vector < int > V1 ; "
"typedef std :: vector < int > V2 ; "
"typedef std :: vector < std :: vector < int > > V3 ; "
@ -2561,6 +2564,22 @@ private:
ASSERT_EQUALS(expected, tok(code));
}
void enum1()
{
const char code[] = "enum A { a, b, c };";
const char expected[] = "enum A { a = 0 , b = 1 , c = 2 } ;";
ASSERT_EQUALS(expected, tok(code, false));
}
void enum2()
{
const char code[] = "enum A { a, }; int array[a];";
const char expected[] = "enum A { a = 0 , } ; int array [ 0 ] ;";
ASSERT_EQUALS(expected, tok(code, false));
}
};
REGISTER_TEST(TestSimplifyTokens)