Fixed #1215 (are enums processed properly?)
This commit is contained in:
parent
5912035696
commit
13f627d0d5
114
lib/tokenize.cpp
114
lib/tokenize.cpp
|
@ -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
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue