From 01de8256ea30f73b405534107e8cf81a25a14b0f Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 2 Mar 2022 07:46:15 +0100 Subject: [PATCH] Fix #10798 cppcheckError with enum class and typedefs (#3867) * Fix #10798 cppcheckError with enum class and typedefs * Format * Format * Leave enum class scope * Remove comment --- lib/tokenize.cpp | 30 +++++++++++++++++++----------- test/testsimplifytokens.cpp | 7 +++++++ test/testsimplifytypedef.cpp | 15 +++++++++++++++ 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 5bef73738..391ac5a04 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1068,6 +1068,7 @@ void Tokenizer::simplifyTypedef() bool globalScope = false; int classLevel = spaceInfo.size(); bool inTypeDef = false; + bool inEnumClass = false; std::string removed; std::string classPath; for (size_t i = 1; i < spaceInfo.size(); ++i) { @@ -1121,6 +1122,7 @@ void Tokenizer::simplifyTypedef() if (memberScope == 0) inMemberFunc = false; } + inEnumClass = false; if (classLevel > 1 && tok2 == spaceInfo[classLevel - 1].bodyEnd2) { --classLevel; @@ -1165,19 +1167,23 @@ void Tokenizer::simplifyTypedef() // check for entering a new scope else if (tok2->str() == "{") { // check for entering a new namespace - if (isCPP() && tok2->strAt(-2) == "namespace") { - if (classLevel < spaceInfo.size() && - spaceInfo[classLevel].isNamespace && - spaceInfo[classLevel].className == tok2->previous()->str()) { - spaceInfo[classLevel].bodyEnd2 = tok2->link(); - ++classLevel; - pattern.clear(); - for (int i = classLevel; i < spaceInfo.size(); ++i) - pattern += spaceInfo[i].className + " :: "; + if (isCPP()) { + if (tok2->strAt(-2) == "namespace") { + if (classLevel < spaceInfo.size() && + spaceInfo[classLevel].isNamespace && + spaceInfo[classLevel].className == tok2->previous()->str()) { + spaceInfo[classLevel].bodyEnd2 = tok2->link(); + ++classLevel; + pattern.clear(); + for (int i = classLevel; i < spaceInfo.size(); ++i) + pattern += spaceInfo[i].className + " :: "; - pattern += typeName->str(); + pattern += typeName->str(); + } + ++scope; } - ++scope; + if (Token::Match(tok2->tokAt(-3), "enum class %name%")) + inEnumClass = true; } // keep track of scopes within member function @@ -1303,6 +1309,8 @@ void Tokenizer::simplifyTypedef() } } + simplifyType = simplifyType && !inEnumClass; + if (simplifyType) { mTypedefInfo.back().used = true; diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index b56da791b..2f794383b 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -329,6 +329,7 @@ private: TEST_CASE(simplifyKnownVariables60); // #6829 TEST_CASE(simplifyKnownVariables61); // #7805 TEST_CASE(simplifyKnownVariables62); // #5666 - p=&str[0] + TEST_CASE(simplifyKnownVariables63); // #10798 TEST_CASE(simplifyKnownVariablesBailOutAssign1); TEST_CASE(simplifyKnownVariablesBailOutAssign2); TEST_CASE(simplifyKnownVariablesBailOutAssign3); // #4395 - nested assignments @@ -6646,6 +6647,12 @@ private: "}", /*simplify=*/ true)); } + void simplifyKnownVariables63() { // #10798 + tokenizeAndStringify("typedef void (*a)();\n" + "enum class E { a };\n"); + ASSERT_EQUALS("", errout.str()); // don't throw + } + void simplifyKnownVariablesBailOutAssign1() { const char code[] = "int foo() {\n" " int i; i = 0;\n" diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index ce288ccd2..9c0495e0e 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -186,6 +186,7 @@ private: TEST_CASE(simplifyTypedef137); TEST_CASE(simplifyTypedef138); TEST_CASE(simplifyTypedef139); + TEST_CASE(simplifyTypedef140); // #10798 TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -3027,6 +3028,20 @@ private: tok(code)); } + void simplifyTypedef140() { // #10798 + { + const char code[] = "typedef void (*b)();\n" + "enum class E { a, b, c };\n"; + ASSERT_EQUALS("enum class E { a , b , c } ;", tok(code)); + } + { + const char code[] = "typedef int A;\n" + "enum class E { A };\n"; + ASSERT_EQUALS("enum class E { A } ;", tok(code)); + } + + } + void simplifyTypedefFunction1() { { const char code[] = "typedef void (*my_func)();\n"