Tokenizer: tweaked simplification of function pointers. Argument types are kept.

This commit is contained in:
Daniel Marjamäki 2023-02-26 18:03:24 +01:00
parent a0cc35e3fa
commit 65fc31cba9
5 changed files with 57 additions and 26 deletions

View File

@ -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;

View File

@ -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();

View File

@ -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 ) ; "

View File

@ -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("");

View File

@ -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"