diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 7bf490f0c..a3967cf08 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -577,6 +577,47 @@ void Tokenizer::simplifyUsingToTypedef() } } +void Tokenizer::simplifyTypedefLHS() +{ + if (!list.front()) + return; + + for (Token* tok = list.front()->next(); tok; tok = tok->next()) { + if (tok->str() == "typedef") { + bool doSimplify = !Token::Match(tok->previous(), ";|{|}|:|public:|private:|protected:"); + if (doSimplify && Token::simpleMatch(tok->previous(), ")") && Token::Match(tok->linkAt(-1)->previous(), "if|for|while")) + doSimplify = false; + bool haveStart = false; + Token* start{}; + if (!doSimplify && Token::simpleMatch(tok->previous(), "}")) { + start = tok->linkAt(-1)->previous(); + while (Token::Match(start, "%name%")) { + if (Token::Match(start, "class|struct|union|enum")) { + start = start->previous(); + doSimplify = true; + haveStart = true; + break; + } + start = start->previous(); + } + } + if (doSimplify) { + if (!haveStart) { + start = tok; + while (start && !Token::Match(start, "[;{}]")) + start = start->previous(); + } + if (start) + start = start->next(); + else + start = list.front(); + start->insertTokenBefore(tok->str()); + tok->deleteThis(); + } + } + } +} + namespace { class TypedefSimplifier { private: @@ -5423,6 +5464,8 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) reportUnknownMacros(); + simplifyTypedefLHS(); + // typedef.. if (mTimerResults) { Timer t("Tokenizer::tokenize::simplifyTypedef", mSettings->showtime, mTimerResults); diff --git a/lib/tokenize.h b/lib/tokenize.h index cc761e066..de05fdfd4 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -268,6 +268,10 @@ public: */ void simplifyTypedef(); void simplifyTypedefCpp(); + /** + * Move typedef token to the left og the expression + */ + void simplifyTypedefLHS(); /** */ diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 6a1109232..ad7164acd 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -211,6 +211,7 @@ private: TEST_CASE(simplifyTypedef142); // T() when T is a pointer type TEST_CASE(simplifyTypedef143); // #11506 TEST_CASE(simplifyTypedef144); // #9353 + TEST_CASE(simplifyTypedef145); // #9353 TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -2022,10 +2023,7 @@ private: } void simplifyTypedef76() { // ticket #2453 segmentation fault - const char code[] = "void f1(typedef int x) {}"; - const char expected[] = "void f1 ( typedef int x ) { }"; - ASSERT_EQUALS(expected, tok(code, true, cppcheck::Platform::Type::Native, false)); - ASSERT_EQUALS("", errout.str()); + ASSERT_THROW(checkSimplifyTypedef("void f1(typedef int x) {}"), InternalError); } void simplifyTypedef77() { // ticket #2554 @@ -3254,6 +3252,23 @@ private: ASSERT_EQUALS("struct X { } ; std :: vector < X > v ;", tok(code)); } + void simplifyTypedef145() { // #11634 + const char* code{}; + code = "int typedef i;\n" + "i main() {}\n"; + ASSERT_EQUALS("int main ( ) { }", tok(code)); + + code = "struct {} typedef S;\n" + "void f() {\n" + " S();\n" + "}\n"; + ASSERT_EQUALS("struct S { } ; void f ( ) { struct S ( ) ; }", tok(code)); + + code = "struct {} typedef S;\n" // don't crash + "S();\n"; + ASSERT_EQUALS("struct S { } ; struct S ( ) ;", tok(code)); + } + void simplifyTypedefFunction1() { { const char code[] = "typedef void (*my_func)();\n"