diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index a590da6fd..d710c7486 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -7359,7 +7359,8 @@ void Tokenizer::simplifyEnum() Token *typeTokenEnd = nullptr; // 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(); // check for name @@ -7521,15 +7522,17 @@ void Tokenizer::simplifyEnum() if (_settings->terminated()) return; - const std::string pattern = className.empty() ? - std::string("") : - std::string(className + " :: "); + std::string pattern; + if (!className.empty()) + pattern += className + " :: "; + if (enumClass) + pattern += enumType->str() + " :: "; + int level = 0; - bool inScope = true; + bool inScope = !enumClass; // enum class objects are always in a different scope std::stack > shadowId; // duplicate ids in inner scope bool simplify = false; - bool hasClass = false; EnumValue *ev = nullptr; if (!tok1) @@ -7631,10 +7634,14 @@ void Tokenizer::simplifyEnum() // skip ( .. ) tok2 = tok2->next()->link(); } - } else if (!pattern.empty() && Token::Match(tok2, pattern.c_str()) && enumValues.find(tok2->strAt(2)) != enumValues.end()) { - simplify = true; - hasClass = true; - ev = &(enumValues.find(tok2->strAt(2))->second); + } else if (!pattern.empty() && Token::Match(tok2, pattern.c_str())) { + const Token* tok3 = tok2; + while (tok3->strAt(1) == "::") + 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 (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 @@ -7647,7 +7654,6 @@ void Tokenizer::simplifyEnum() // * it's followed by "[" } else { simplify = true; - hasClass = false; ev = &(enumValues.find(tok2->str())->second); } } else { @@ -7661,11 +7667,13 @@ void Tokenizer::simplifyEnum() if (simplify) { if (ev->value) { tok2->str(ev->value->str()); - if (hasClass) + while (tok2->strAt(1) == "::") tok2->deleteNext(2); } else { + while (tok2->strAt(1) == "::") + tok2->deleteNext(2); tok2 = tok2->previous(); - tok2->deleteNext(hasClass ? 3 : 1); + tok2->deleteNext(); bool hasOp = false; int indentlevel = 0; 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); if (tok->next()->link()->next()->str() == "void") // __attribute__((constructor)) void func() {} 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); else // void __attribute__((constructor)) func() {} tok->next()->link()->next()->isAttributeConstructor(true); @@ -9109,7 +9117,7 @@ void Tokenizer::simplifyAttribute() // prototype for destructor is: void func(void); if (tok->next()->link()->next()->str() == "void") // __attribute__((destructor)) void func() {} 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); else // void __attribute__((destructor)) func() {} tok->next()->link()->next()->isAttributeDestructor(true); diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index c46e479c9..b9d8aabb0 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -6841,11 +6841,18 @@ private: { const char code[] = "enum class Enum1 { a };\n" - "Enum1 e1 = a;"; + "Enum1 e1 = Enum1::a;"; const char expected[] = "int e1 ; e1 = 0 ;"; 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" "Enum1 e1 = a;"; @@ -6855,21 +6862,21 @@ private: { 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 ;"; ASSERT_EQUALS(expected, checkSimplifyEnum(code)); } { 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 ;"; ASSERT_EQUALS(expected, checkSimplifyEnum(code)); } { 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 ;"; ASSERT_EQUALS(expected, checkSimplifyEnum(code)); } @@ -6989,23 +6996,25 @@ private: } void enum30() { // #3852 - false positive - - const char code[] = "class TestIf\n" - "{\n" - "public:\n" - " enum class Foo\n" - " {\n" - " one = 0,\n" - " two = 1\n" - " };\n" - " enum class Bar\n" - " {\n" - " one = 0,\n" - " two = 1\n" - " };\n" - "};\n"; - checkSimplifyEnum(code); - TODO_ASSERT_EQUALS("","[test.cpp:12] -> [test.cpp:7]: (style) Variable 'two' hides enumerator with same name\n", errout.str()); + const char code [] = "class TestIf\n" + "{\n" + "public:\n" + " enum class Foo\n" + " {\n" + " one = 0,\n" + " two = 1\n" + " };\n" + " enum class Bar\n" + " {\n" + " one = 0,\n" + " two = 1\n" + " };\n" + "};\n" + "int main() {" + " return TestIf::Bar::two;\n" + "}"; + ASSERT_EQUALS("class TestIf { public: } ; int main ( ) { return 1 ; }", checkSimplifyEnum(code)); + ASSERT_EQUALS("", errout.str()); } void enum31() { // #3934 - calculation in first item diff --git a/test/testunusedfunctions.cpp b/test/testunusedfunctions.cpp index 7c60717dd..9460f75ae 100644 --- a/test/testunusedfunctions.cpp +++ b/test/testunusedfunctions.cpp @@ -277,6 +277,11 @@ private: check("void f() __attribute__((destructor(1000)));\n" "void f() { }"); ASSERT_EQUALS("", errout.str()); + + // Don't crash on wrong syntax + check("int x __attribute__((constructor));\n" + "int x __attribute__((destructor));"); + ASSERT_EQUALS("", errout.str()); }