From 65fc31cba9c9807286fc04a4d4a7ca337a6b9163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 26 Feb 2023 18:03:24 +0100 Subject: [PATCH] Tokenizer: tweaked simplification of function pointers. Argument types are kept. --- lib/checkunusedvar.cpp | 2 ++ lib/tokenize.cpp | 28 ++++++++++++++++++---------- test/testsimplifytypedef.cpp | 26 +++++++++++++------------- test/testtokenize.cpp | 15 ++++++++++++--- test/testvarid.cpp | 12 ++++++++++++ 5 files changed, 57 insertions(+), 26 deletions(-) diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 8a35b6e74..978b4dc57 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1181,6 +1181,8 @@ void CheckUnusedVar::checkFunctionVariableUsage() const Token * eq = tok->next(); while (Token::simpleMatch(eq, "[")) eq = eq->link()->next(); + if (Token::simpleMatch(eq, ") (") && Token::simpleMatch(eq->linkAt(1), ") =")) + eq = eq->linkAt(1)->next(); if (Token::simpleMatch(eq, "=")) { varDecl = tok; tok = eq; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index a0df78666..8b369747b 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -6173,20 +6173,26 @@ void Tokenizer::simplifyFunctionPointers() endTok->deleteNext(); // ok simplify this function pointer to an ordinary pointer - Token::eraseTokens(tok->link(), endTok->next()); if (Token::simpleMatch(tok->link()->previous(), ") )")) { // Function returning function pointer // void (*dostuff(void))(void) {} + Token::eraseTokens(tok->link(), endTok->next()); tok->link()->deleteThis(); tok->deleteThis(); } else { - // Function pointer variable - // void (*p)(void) {} - tok->link()->insertToken("("); - Token *par1 = tok->link()->next(); - par1->insertToken(")"); - par1->link(par1->next()); - par1->next()->link(par1); + Token::eraseTokens(tok->link()->linkAt(1), endTok->next()); + + // remove variable names + for (Token* tok3 = tok->link()->tokAt(2); Token::Match(tok3, "%name%|*|&|[|(|::|,|<"); tok3 = tok3->next()) { + if (tok3->str() == "<" && tok3->link()) + tok3 = tok3->link(); + else if (Token::Match(tok3, "[|(")) + tok3 = tok3->link(); + if (Token::Match(tok3, "%type%|*|&|> %name% [,)[]")) + tok3->deleteNext(); + } + + // TODO Keep this info while (Token::Match(tok, "( %type% ::")) tok->deleteNext(2); } @@ -6424,8 +6430,10 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co varName = varName->next(); } // Function pointer - if (Token::simpleMatch(varName, "( *") && Token::Match(varName->link()->previous(), "%name% ) ( ) =")) { - Token *endDecl = varName->link()->tokAt(2); + if (Token::simpleMatch(varName, "( *") && + Token::Match(varName->link()->previous(), "%name% ) (") && + Token::simpleMatch(varName->link()->linkAt(1), ") =")) { + Token *endDecl = varName->link()->linkAt(1); varName = varName->link()->previous(); endDecl->insertToken(";"); endDecl = endDecl->next(); diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 5f24c36ea..e6696a740 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -779,8 +779,8 @@ private: "void addCallback1(Callback callback, int j) { }"; const char expected[] = - "void addCallback ( bool ( * callback ) ( ) ) { } " - "void addCallback1 ( bool ( * callback ) ( ) , int j ) { }"; + "void addCallback ( bool ( * callback ) ( int ) ) { } " + "void addCallback1 ( bool ( * callback ) ( int ) , int j ) { }"; ASSERT_EQUALS(expected, tok(code, false)); } @@ -1132,7 +1132,7 @@ private: "class X { } ; " "int main ( ) " "{ " - "X ( * * Foo ) ( ) ; Foo = new X ( * ) ( const X & ) [ 2 ] ; " + "X ( * * Foo ) ( const X & ) ; Foo = new X ( * ) ( const X & ) [ 2 ] ; " "}"; ASSERT_EQUALS(expected, tok(code, false)); @@ -1606,7 +1606,7 @@ private: " localEntitiyAddFunc_t f;\n" "}"; // The expected result.. - const char expected[] = "enum qboolean { qfalse , qtrue } ; void f ( ) { qboolean b ; qboolean ( * f ) ( ) ; }"; + const char expected[] = "enum qboolean { qfalse , qtrue } ; void f ( ) { qboolean b ; qboolean ( * f ) ( struct le_s * , entity_t * ) ; }"; ASSERT_EQUALS(expected, tok(code, false)); ASSERT_EQUALS("", errout.str()); } @@ -2174,7 +2174,7 @@ private: "};"; const char expected[] = "class symbol_table { " "public: " - "expression_error :: error_code ( * f ) ( ) ; " + "expression_error :: error_code ( * f ) ( void * , const char * , expression_space ) ; " "} ;"; ASSERT_EQUALS(expected, tok(code, true, Settings::Native, false)); ASSERT_EQUALS("", errout.str()); @@ -3518,14 +3518,14 @@ private: "type12 t12;"; // The expected result.. - const char expected[] = "int ( * t1 ) ( ) ; " - "int ( * const t2 ) ( ) ; " - "int ( * volatile t3 ) ( ) ; " - "int ( * const volatile t4 ) ( ) ; " - "int ( * t5 ) ( ) ; " - "int ( * const t6 ) ( ) ; " - "int ( * volatile t7 ) ( ) ; " - "int ( * const volatile t8 ) ( ) ; " + const char expected[] = "int ( * t1 ) ( float ) ; " + "int ( * const t2 ) ( float ) ; " + "int ( * volatile t3 ) ( float ) ; " + "int ( * const volatile t4 ) ( float ) ; " + "int ( * t5 ) ( float ) ; " + "int ( * const t6 ) ( float ) ; " + "int ( * volatile t7 ) ( float ) ; " + "int ( * const volatile t8 ) ( float ) ; " "int ( :: C :: * t9 ) ( float ) ; " "int ( :: C :: * const t10 ) ( float ) ; " "int ( :: C :: * volatile t11 ) ( float ) ; " diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index d1cc2b33d..de7fe4400 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -224,6 +224,7 @@ private: TEST_CASE(vardecl28); TEST_CASE(vardecl29); // #9282 TEST_CASE(vardecl30); + TEST_CASE(vardecl31); // function pointer init TEST_CASE(vardecl_stl_1); TEST_CASE(vardecl_stl_2); TEST_CASE(vardecl_stl_3); @@ -2523,6 +2524,14 @@ private: tokenizeAndStringify(code, true, Settings::Native, "test.c")); } + void vardecl31() { + const char code1[] = "void foo() { int (*fptr)() = 0; }"; + ASSERT_EQUALS("void foo ( ) { int ( * fptr ) ( ) ; fptr = 0 ; }", tokenizeAndStringify(code1)); + + const char code2[] = "void foo() { int (*fptr)(int) = 0; }"; + ASSERT_EQUALS("void foo ( ) { int ( * fptr ) ( int ) ; fptr = 0 ; }", tokenizeAndStringify(code2)); + } + void volatile_variables() { { const char code[] = "volatile int a=0;\n" @@ -3557,7 +3566,7 @@ private: ASSERT_EQUALS("unsigned int ( * f ) ( ) ;", tokenizeAndStringify("unsigned int (*f)();")); ASSERT_EQUALS("unsigned int * ( * f ) ( ) ;", tokenizeAndStringify("unsigned int * (*f)();")); ASSERT_EQUALS("void ( * f [ 2 ] ) ( ) ;", tokenizeAndStringify("void (*f[2])();")); - TODO_ASSERT_EQUALS("void ( * f [ 2 ] ) ( ) ;", "void ( * f ) ( ) [ 2 ] ;", tokenizeAndStringify("typedef void func_t(void); func_t *f[2];")); + TODO_ASSERT_EQUALS("void ( * f [ 2 ] ) ( ) ;", "void ( * f ) ( void ) [ 2 ] ;", tokenizeAndStringify("typedef void func_t(void); func_t *f[2];")); } void simplifyFunctionPointers2() { @@ -3598,7 +3607,7 @@ private: void simplifyFunctionPointers5() { const char code[] = ";void (*fp[])(int a) = {0,0,0};"; - const char expected[] = "1: ; void ( * fp@1 [ ] ) ( ) = { 0 , 0 , 0 } ;\n"; // TODO: Array dimension + const char expected[] = "1: ; void ( * fp@1 [ ] ) ( int ) = { 0 , 0 , 0 } ;\n"; // TODO: Array dimension ASSERT_EQUALS(expected, tokenizeDebugListing(code)); } @@ -3709,7 +3718,7 @@ private: void functionAttributeBefore3() { // #10978 const char code[] = "void __attribute__((__noreturn__)) (*func_notret)(void);"; - const char expected[] = "void ( * func_notret ) ( ) ;"; + const char expected[] = "void ( * func_notret ) ( void ) ;"; errout.str(""); diff --git a/test/testvarid.cpp b/test/testvarid.cpp index 9c8aa5d9b..9dccf684e 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -190,6 +190,7 @@ private: TEST_CASE(varid_not); // #9689 'not x' TEST_CASE(varid_declInIfCondition); TEST_CASE(varid_globalScope); + TEST_CASE(varid_function_pointer_args); TEST_CASE(varidclass1); TEST_CASE(varidclass2); @@ -2996,6 +2997,17 @@ private: ASSERT_EQUALS(exp1, tokenize(code1)); } + void varid_function_pointer_args() { + const char code[] = "void foo() {\n" + " char *text;\n" + " void (*cb)(char* text);\n" + "}\n"; + ASSERT_EQUALS("1: void foo ( ) {\n" + "2: char * text@1 ;\n" + "3: void ( * cb@2 ) ( char * ) ;\n" + "4: }\n", tokenize(code)); + } + void varidclass1() { const std::string actual = tokenize( "class Fred\n"