This commit is contained in:
Alexander Mai 2014-03-16 18:37:38 +01:00
commit 6fb4ce37fb
3 changed files with 58 additions and 36 deletions

View File

@ -7359,7 +7359,8 @@ void Tokenizer::simplifyEnum()
Token *typeTokenEnd = nullptr; Token *typeTokenEnd = nullptr;
// check for C++0x enum class // check for C++0x enum class
if (Token::Match(tok->next(), "class|struct")) bool enumClass = Token::Match(tok->next(), "class|struct");
if (enumClass)
tok->deleteNext(); tok->deleteNext();
// check for name // check for name
@ -7521,15 +7522,17 @@ void Tokenizer::simplifyEnum()
if (_settings->terminated()) if (_settings->terminated())
return; return;
const std::string pattern = className.empty() ? std::string pattern;
std::string("") : if (!className.empty())
std::string(className + " :: "); pattern += className + " :: ";
if (enumClass)
pattern += enumType->str() + " :: ";
int level = 0; int level = 0;
bool inScope = true; bool inScope = !enumClass; // enum class objects are always in a different scope
std::stack<std::set<std::string> > shadowId; // duplicate ids in inner scope std::stack<std::set<std::string> > shadowId; // duplicate ids in inner scope
bool simplify = false; bool simplify = false;
bool hasClass = false;
EnumValue *ev = nullptr; EnumValue *ev = nullptr;
if (!tok1) if (!tok1)
@ -7631,10 +7634,14 @@ void Tokenizer::simplifyEnum()
// skip ( .. ) // skip ( .. )
tok2 = tok2->next()->link(); tok2 = tok2->next()->link();
} }
} else if (!pattern.empty() && Token::Match(tok2, pattern.c_str()) && enumValues.find(tok2->strAt(2)) != enumValues.end()) { } else if (!pattern.empty() && Token::Match(tok2, pattern.c_str())) {
simplify = true; const Token* tok3 = tok2;
hasClass = true; while (tok3->strAt(1) == "::")
ev = &(enumValues.find(tok2->strAt(2))->second); tok3 = tok3->tokAt(2);
if (enumValues.find(tok3->str()) != enumValues.end()) {
simplify = true;
ev = &(enumValues.find(tok3->str())->second);
}
} else if (inScope && // enum is in scope } else if (inScope && // enum is in scope
(shadowId.empty() || shadowId.top().find(tok2->str()) == shadowId.top().end()) && // no shadow enum/var/etc of enum (shadowId.empty() || shadowId.top().find(tok2->str()) == shadowId.top().end()) && // no shadow enum/var/etc of enum
enumValues.find(tok2->str()) != enumValues.end()) { // tok2 is a enum id with a known value enumValues.find(tok2->str()) != enumValues.end()) { // tok2 is a enum id with a known value
@ -7647,7 +7654,6 @@ void Tokenizer::simplifyEnum()
// * it's followed by "[" // * it's followed by "["
} else { } else {
simplify = true; simplify = true;
hasClass = false;
ev = &(enumValues.find(tok2->str())->second); ev = &(enumValues.find(tok2->str())->second);
} }
} else { } else {
@ -7661,11 +7667,13 @@ void Tokenizer::simplifyEnum()
if (simplify) { if (simplify) {
if (ev->value) { if (ev->value) {
tok2->str(ev->value->str()); tok2->str(ev->value->str());
if (hasClass) while (tok2->strAt(1) == "::")
tok2->deleteNext(2); tok2->deleteNext(2);
} else { } else {
while (tok2->strAt(1) == "::")
tok2->deleteNext(2);
tok2 = tok2->previous(); tok2 = tok2->previous();
tok2->deleteNext(hasClass ? 3 : 1); tok2->deleteNext();
bool hasOp = false; bool hasOp = false;
int indentlevel = 0; int indentlevel = 0;
for (const Token *enumtok = ev->start; enumtok != ev->end; enumtok = enumtok->next()) { for (const Token *enumtok = ev->start; enumtok != ev->end; enumtok = enumtok->next()) {
@ -9099,7 +9107,7 @@ void Tokenizer::simplifyAttribute()
// prototype for constructor is: void func(void); // prototype for constructor is: void func(void);
if (tok->next()->link()->next()->str() == "void") // __attribute__((constructor)) void func() {} if (tok->next()->link()->next()->str() == "void") // __attribute__((constructor)) void func() {}
tok->next()->link()->next()->next()->isAttributeConstructor(true); tok->next()->link()->next()->next()->isAttributeConstructor(true);
else if (tok->next()->link()->next()->str() == ";") // void func() __attribute__((constructor)); else if (tok->next()->link()->next()->str() == ";" && tok->linkAt(-1)) // void func() __attribute__((constructor));
tok->previous()->link()->previous()->isAttributeConstructor(true); tok->previous()->link()->previous()->isAttributeConstructor(true);
else // void __attribute__((constructor)) func() {} else // void __attribute__((constructor)) func() {}
tok->next()->link()->next()->isAttributeConstructor(true); tok->next()->link()->next()->isAttributeConstructor(true);
@ -9109,7 +9117,7 @@ void Tokenizer::simplifyAttribute()
// prototype for destructor is: void func(void); // prototype for destructor is: void func(void);
if (tok->next()->link()->next()->str() == "void") // __attribute__((destructor)) void func() {} if (tok->next()->link()->next()->str() == "void") // __attribute__((destructor)) void func() {}
tok->next()->link()->next()->next()->isAttributeDestructor(true); tok->next()->link()->next()->next()->isAttributeDestructor(true);
else if (tok->next()->link()->next()->str() == ";") // void func() __attribute__((destructor)); else if (tok->next()->link()->next()->str() == ";" && tok->linkAt(-1)) // void func() __attribute__((destructor));
tok->previous()->link()->previous()->isAttributeDestructor(true); tok->previous()->link()->previous()->isAttributeDestructor(true);
else // void __attribute__((destructor)) func() {} else // void __attribute__((destructor)) func() {}
tok->next()->link()->next()->isAttributeDestructor(true); tok->next()->link()->next()->isAttributeDestructor(true);

View File

@ -6841,11 +6841,18 @@ private:
{ {
const char code[] = "enum class Enum1 { a };\n" const char code[] = "enum class Enum1 { a };\n"
"Enum1 e1 = a;"; "Enum1 e1 = Enum1::a;";
const char expected[] = "int e1 ; e1 = 0 ;"; const char expected[] = "int e1 ; e1 = 0 ;";
ASSERT_EQUALS(expected, checkSimplifyEnum(code)); ASSERT_EQUALS(expected, checkSimplifyEnum(code));
} }
{
const char code[] = "enum class Enum1 { a };\n"
"Enum1 e1 = a;";
const char expected[] = "int e1 ; e1 = a ;";
ASSERT_EQUALS(expected, checkSimplifyEnum(code));
}
{ {
const char code[] = "enum Enum1 : char { a };\n" const char code[] = "enum Enum1 : char { a };\n"
"Enum1 e1 = a;"; "Enum1 e1 = a;";
@ -6855,21 +6862,21 @@ private:
{ {
const char code[] = "enum class Enum1 : unsigned char { a };\n" const char code[] = "enum class Enum1 : unsigned char { a };\n"
"Enum1 e1 = a;"; "Enum1 e1 = Enum1::a;";
const char expected[] = "unsigned char e1 ; e1 = 0 ;"; const char expected[] = "unsigned char e1 ; e1 = 0 ;";
ASSERT_EQUALS(expected, checkSimplifyEnum(code)); ASSERT_EQUALS(expected, checkSimplifyEnum(code));
} }
{ {
const char code[] = "enum class Enum1 : unsigned int { a };\n" const char code[] = "enum class Enum1 : unsigned int { a };\n"
"Enum1 e1 = a;"; "Enum1 e1 = Enum1::a;";
const char expected[] = "unsigned int e1 ; e1 = 0 ;"; const char expected[] = "unsigned int e1 ; e1 = 0 ;";
ASSERT_EQUALS(expected, checkSimplifyEnum(code)); ASSERT_EQUALS(expected, checkSimplifyEnum(code));
} }
{ {
const char code[] = "enum class Enum1 : unsigned long long int { a };\n" const char code[] = "enum class Enum1 : unsigned long long int { a };\n"
"Enum1 e1 = a;"; "Enum1 e1 = Enum1::a;";
const char expected[] = "unsigned long long e1 ; e1 = 0 ;"; const char expected[] = "unsigned long long e1 ; e1 = 0 ;";
ASSERT_EQUALS(expected, checkSimplifyEnum(code)); ASSERT_EQUALS(expected, checkSimplifyEnum(code));
} }
@ -6989,23 +6996,25 @@ private:
} }
void enum30() { // #3852 - false positive void enum30() { // #3852 - false positive
const char code [] = "class TestIf\n"
const char code[] = "class TestIf\n" "{\n"
"{\n" "public:\n"
"public:\n" " enum class Foo\n"
" enum class Foo\n" " {\n"
" {\n" " one = 0,\n"
" one = 0,\n" " two = 1\n"
" two = 1\n" " };\n"
" };\n" " enum class Bar\n"
" enum class Bar\n" " {\n"
" {\n" " one = 0,\n"
" one = 0,\n" " two = 1\n"
" two = 1\n" " };\n"
" };\n" "};\n"
"};\n"; "int main() {"
checkSimplifyEnum(code); " return TestIf::Bar::two;\n"
TODO_ASSERT_EQUALS("","[test.cpp:12] -> [test.cpp:7]: (style) Variable 'two' hides enumerator with same name\n", errout.str()); "}";
ASSERT_EQUALS("class TestIf { public: } ; int main ( ) { return 1 ; }", checkSimplifyEnum(code));
ASSERT_EQUALS("", errout.str());
} }
void enum31() { // #3934 - calculation in first item void enum31() { // #3934 - calculation in first item

View File

@ -277,6 +277,11 @@ private:
check("void f() __attribute__((destructor(1000)));\n" check("void f() __attribute__((destructor(1000)));\n"
"void f() { }"); "void f() { }");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// Don't crash on wrong syntax
check("int x __attribute__((constructor));\n"
"int x __attribute__((destructor));");
ASSERT_EQUALS("", errout.str());
} }