From 0725c2290ca5c6633680e3f9d2fd5532b7616fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 10 Apr 2020 11:53:32 +0200 Subject: [PATCH] Tokenizer: Do not simplify function pointers to normal pointers as we loose important information --- lib/checkunusedvar.cpp | 9 ++- lib/symboldatabase.cpp | 8 ++- lib/tokenize.cpp | 34 ++++++++-- test/testsimplifytokens.cpp | 2 +- test/testsimplifytypedef.cpp | 120 +++++++++++++++++------------------ test/testtokenize.cpp | 44 ++++++------- test/testvarid.cpp | 2 +- 7 files changed, 122 insertions(+), 97 deletions(-) diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index bf8949eca..cc53cee05 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -594,6 +594,11 @@ static bool isPartOfClassStructUnion(const Token* tok) return false; } +static bool isVarDecl(const Token *tok) +{ + return tok && tok->variable() && tok->variable()->nameToken() == tok; +} + // Skip [ .. ] static const Token * skipBrackets(const Token *tok) { @@ -1047,11 +1052,11 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const variables.use(tok->astOperand2()->varId(), tok->astOperand2()); } - else if (tok->isExtendedOp() && tok->next() && tok->next()->varId() && tok->strAt(2) != "=") { + else if (tok->isExtendedOp() && tok->next() && tok->next()->varId() && tok->strAt(2) != "=" && !isVarDecl(tok->next())) { variables.readAll(tok->next()->varId(), tok); } - else if (tok->varId() && tok->next() && (tok->next()->str() == ")" || tok->next()->isExtendedOp())) { + else if (tok->varId() && !isVarDecl(tok) && tok->next() && (tok->next()->str() == ")" || tok->next()->isExtendedOp())) { if (Token::Match(tok->tokAt(-2), "%name% ( %var% [,)]") && !(tok->tokAt(-2)->variable() && tok->tokAt(-2)->variable()->isReference())) variables.use(tok->varId(), tok); diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 38a6304a1..7d7c6a69d 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -5603,8 +5603,14 @@ static const Token * parsedecl(const Token *type, ValueType * const valuetype, V valuetype->type = ValueType::Type::INT; } else valuetype->type = ValueType::Type::RECORD; - while (Token::Match(type, "%name%|*|&|::") && !Token::Match(type, "typename|template") && + bool par = false; + while (Token::Match(type, "%name%|*|&|::|(") && !Token::Match(type, "typename|template") && !type->variable() && !type->function()) { + if (type->str() == "(") { + if (par) + break; + par = true; + } if (type->isSigned()) valuetype->sign = ValueType::Sign::SIGNED; else if (type->isUnsigned()) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 6707f155a..7ffbd042f 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2994,6 +2994,7 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::mapisName()) { if (cpp && Token::Match(tok2, "namespace|public|private|protected")) @@ -3042,7 +3043,7 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::maplink()->next(), "(|[")) { + } else if (singleNameCount >= 1 && !par && Token::Match(tok2, "( [*&]") && Token::Match(tok2->link()->next(), "(|[")) { bracket = true; // Skip: Seems to be valid pointer to array or function pointer } else if (tok2->str() == "::") { singleNameCount = 0; @@ -6502,10 +6503,22 @@ void Tokenizer::simplifyFunctionPointers() // ok simplify this function pointer to an ordinary pointer Token::eraseTokens(tok->link(), endTok->next()); - tok->link()->deleteThis(); - while (Token::Match(tok, "( %type% ::")) - tok->deleteNext(2); - tok->deleteThis(); + if (Token::simpleMatch(tok->link()->previous(), ") )")) { + // Function returning function pointer + // void (*dostuff(void))(void) {} + 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); + while (Token::Match(tok, "( %type% ::")) + tok->deleteNext(2); + } } } @@ -6732,8 +6745,17 @@ 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); + varName = varName->link()->previous(); + endDecl->insertToken(";"); + endDecl = endDecl->next(); + endDecl->insertToken(varName->str()); + continue; + } //non-VLA case - if (Token::Match(varName, "%name% ,|=")) { + else if (Token::Match(varName, "%name% ,|=")) { if (varName->str() != "operator") { tok2 = varName->next(); // The ',' or '=' token diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 245a8ae93..dd636a452 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -4692,7 +4692,7 @@ private: // #ticket #5339 (simplify function pointer after comma) void simplifyFunctionPointer() { - ASSERT_EQUALS("f ( double x , double * y ) ;", tok("f (double x, double (*y) ());", true)); + ASSERT_EQUALS("f ( double x , double ( * y ) ( ) ) ;", tok("f (double x, double (*y) ());", true)); } void redundant_semicolon() { diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index ce21da9b6..fecb506e1 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -725,8 +725,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 ) ( ) ) { } " + "void addCallback1 ( bool ( * callback ) ( ) , int j ) { }"; ASSERT_EQUALS(expected, tok(code, false)); } @@ -740,9 +740,9 @@ private: "}"; const char expected[] = - "void g ( int * f ) " + "void g ( int ( * f ) ( ) ) " "{ " - "int * f2 ; f2 = ( int * ) f ; " + "int ( * f2 ) ( ) ; f2 = ( int * ) f ; " "}"; ASSERT_EQUALS(expected, tok(code, false)); @@ -756,9 +756,9 @@ private: "}"; const char expected[] = - "void g ( int * f ) " + "void g ( int ( * f ) ( ) ) " "{ " - "int * f2 ; f2 = static_cast < int * > ( f ) ; " + "int ( * f2 ) ( ) ; f2 = static_cast < int * > ( f ) ; " "}"; ASSERT_EQUALS(expected, tok(code, false)); @@ -1078,7 +1078,7 @@ private: "class X { } ; " "int main ( ) " "{ " - "X * * Foo ; Foo = new X ( * ) ( const X & ) [ 2 ] ; " + "X ( * * Foo ) ( ) ; Foo = new X ( * ) ( const X & ) [ 2 ] ; " "}"; ASSERT_EQUALS(expected, tok(code, false)); @@ -1354,7 +1354,7 @@ private: "F f;"; // The expected result.. - const char expected[] = "void * f ;"; + const char expected[] = "void ( * f ) ( ) ;"; ASSERT_EQUALS(expected, tok(code)); } } @@ -1489,7 +1489,7 @@ private: // The expected result.. const char expected[] = "struct C { " "" - "const void * pr ; " // this gets simplified to a regular pointer + "const void ( * pr ) ( ) ; " "operatorconstvoid(*)()& ( ) { return pr ; } " "} ;"; ASSERT_EQUALS(expected, tok(code)); @@ -1552,7 +1552,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 ) ( ) ; }"; ASSERT_EQUALS(expected, tok(code, false)); ASSERT_EQUALS("", errout.str()); } @@ -1669,7 +1669,7 @@ private: const char code[] = "typedef FMAC1 void (* a) ();\n" "void *(*b) ();"; const std::string actual(tok(code)); - ASSERT_EQUALS("void * * b ;", actual); + ASSERT_EQUALS("void * ( * b ) ( ) ;", actual); ASSERT_EQUALS("", errout.str()); } @@ -2120,7 +2120,7 @@ private: "};"; const char expected[] = "class symbol_table { " "public: " - "expression_error :: error_code * f ; " + "expression_error :: error_code ( * f ) ( ) ; " "} ;"; ASSERT_EQUALS(expected, tok(code, true, Settings::Native, false)); ASSERT_EQUALS("", errout.str()); @@ -2867,12 +2867,12 @@ private: // The expected result.. const char expected[] = "C f1 ( ) ; " - "C * f2 ; " // this gets simplified to a regular pointer + "C ( * f2 ) ( ) ; " "C ( & f3 ) ( ) ; " - "C * f4 ; " // this gets simplified to a regular pointer - "C * f5 ; " // this gets simplified to a regular pointer - "C * f6 ; " // this gets simplified to a regular pointer - "C * f7 ;"; // this gets simplified to a regular pointer + "C ( * f4 ) ( ) ; " + "C ( * f5 ) ( ) ; " + "C ( * f6 ) ( ) ; " + "C ( * f7 ) ( ) ;"; ASSERT_EQUALS(expected, tok(code, true, Settings::Native, false)); ASSERT_EQUALS("", errout.str()); } @@ -2896,12 +2896,12 @@ private: // The expected result.. // C const -> const C const char expected[] = "const C f1 ( ) ; " - "const C * f2 ; " // this gets simplified to a regular pointer + "const C ( * f2 ) ( ) ; " "const C ( & f3 ) ( ) ; " - "const C * f4 ; " // this gets simplified to a regular pointer - "const C * f5 ; " // this gets simplified to a regular pointer - "const C * f6 ; " // this gets simplified to a regular pointer - "const C * f7 ;"; // this gets simplified to a regular pointer + "const C ( * f4 ) ( ) ; " + "const C ( * f5 ) ( ) ; " + "const C ( * f6 ) ( ) ; " + "const C ( * f7 ) ( ) ;"; ASSERT_EQUALS(expected, tok(code, true, Settings::Native, false)); ASSERT_EQUALS("", errout.str()); } @@ -2924,12 +2924,12 @@ private: // The expected result.. const char expected[] = "const C f1 ( ) ; " - "const C * f2 ; " // this gets simplified to a regular pointer + "const C ( * f2 ) ( ) ; " "const C ( & f3 ) ( ) ; " - "const C * f4 ; " // this gets simplified to a regular pointer - "const C * f5 ; " // this gets simplified to a regular pointer - "const C * f6 ; " // this gets simplified to a regular pointer - "const C * f7 ;"; // this gets simplified to a regular pointer + "const C ( * f4 ) ( ) ; " + "const C ( * f5 ) ( ) ; " + "const C ( * f6 ) ( ) ; " + "const C ( * f7 ) ( ) ;"; ASSERT_EQUALS(expected, tok(code, true, Settings::Native, false)); ASSERT_EQUALS("", errout.str()); } @@ -2952,12 +2952,12 @@ private: // The expected result.. const char expected[] = "C * f1 ( ) ; " - "C * * f2 ; " // this gets simplified to a regular pointer + "C * ( * f2 ) ( ) ; " "C * ( & f3 ) ( ) ; " - "C * * f4 ; " // this gets simplified to a regular pointer - "C * * f5 ; " // this gets simplified to a regular pointer - "C * * f6 ; " // this gets simplified to a regular pointer - "C * * f7 ;"; // this gets simplified to a regular pointer + "C * ( * f4 ) ( ) ; " + "C * ( * f5 ) ( ) ; " + "C * ( * f6 ) ( ) ; " + "C * ( * f7 ) ( ) ;"; ASSERT_EQUALS(expected, tok(code, true, Settings::Native, false)); ASSERT_EQUALS("", errout.str()); } @@ -2980,12 +2980,12 @@ private: // The expected result.. const char expected[] = "const C * f1 ( ) ; " - "const C * * f2 ; " // this gets simplified to a regular pointer + "const C * ( * f2 ) ( ) ; " "const C * ( & f3 ) ( ) ; " - "const C * * f4 ; " // this gets simplified to a regular pointer - "const C * * f5 ; " // this gets simplified to a regular pointer - "const C * * f6 ; " // this gets simplified to a regular pointer - "const C * * f7 ;"; // this gets simplified to a regular pointer + "const C * ( * f4 ) ( ) ; " + "const C * ( * f5 ) ( ) ; " + "const C * ( * f6 ) ( ) ; " + "const C * ( * f7 ) ( ) ;"; ASSERT_EQUALS(expected, tok(code, true, Settings::Native, false)); ASSERT_EQUALS("", errout.str()); } @@ -3009,12 +3009,12 @@ private: // The expected result.. // C const -> const C const char expected[] = "const C * f1 ( ) ; " - "const C * * f2 ; " // this gets simplified to a regular pointer + "const C * ( * f2 ) ( ) ; " "const C * ( & f3 ) ( ) ; " - "const C * * f4 ; " // this gets simplified to a regular pointer - "const C * * f5 ; " // this gets simplified to a regular pointer - "const C * * f6 ; " // this gets simplified to a regular pointer - "const C * * f7 ;"; // this gets simplified to a regular pointer + "const C * ( * f4 ) ( ) ; " + "const C * ( * f5 ) ( ) ; " + "const C * ( * f6 ) ( ) ; " + "const C * ( * f7 ) ( ) ;"; ASSERT_EQUALS(expected, tok(code, true, Settings::Native, false)); ASSERT_EQUALS("", errout.str()); } @@ -3063,14 +3063,14 @@ private: "type12 t12;"; // The expected result.. - const char expected[] = "int * t1 ; " // simplified to regular pointer - "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 ) ( ) ; " + "int ( * const t2 ) ( ) ; " + "int ( * volatile t3 ) ( ) ; " + "int ( * const volatile t4 ) ( ) ; " + "int ( * t5 ) ( ) ; " + "int ( * const t6 ) ( ) ; " + "int ( * volatile t7 ) ( ) ; " + "int ( * const volatile t8 ) ( ) ; " "int ( :: C :: * t9 ) ( float ) ; " "int ( :: C :: * const t10 ) ( float ) ; " "int ( :: C :: * volatile t11 ) ( float ) ; " @@ -3156,10 +3156,10 @@ private: "func4 f4;"; // The expected result.. - const char expected[] = "B :: C * f1 ; " - "B :: C * f2 ; " - "B :: C * f3 ; " - "B :: C * f4 ;"; + const char expected[] = "B :: C ( * f1 ) ( ) ; " + "B :: C ( * f2 ) ( ) ; " + "B :: C ( * f3 ) ( ) ; " + "B :: C ( * f4 ) ( ) ;"; ASSERT_EQUALS(expected, tok(code, true, Settings::Native, false)); ASSERT_EQUALS("", errout.str()); } @@ -3194,10 +3194,10 @@ private: "func4 f4;"; // The expected result.. - const char expected[] = "A :: B :: C * f1 ; " - "A :: B :: C * f2 ; " - "A :: B :: C * f3 ; " - "A :: B :: C * f4 ;"; + const char expected[] = "A :: B :: C ( * f1 ) ( ) ; " + "A :: B :: C ( * f2 ) ( ) ; " + "A :: B :: C ( * f3 ) ( ) ; " + "A :: B :: C ( * f4 ) ( ) ;"; ASSERT_EQUALS(expected, tok(code, true, Settings::Native, false)); ASSERT_EQUALS("", errout.str()); } @@ -3216,8 +3216,8 @@ private: "namespace MySpace { " "enum Format_E2 { FORMAT21 , FORMAT22 } ; enum Format_E2 Format_T2 ; " "} " - "Format_E1 * * t1 ; " - "MySpace :: Format_E2 * * t2 ;", + "Format_E1 ( * * t1 ) ( ) ; " + "MySpace :: Format_E2 ( * * t2 ) ( ) ;", tok(code,false)); } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 910e2aa5c..61f493b23 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -797,14 +797,14 @@ private: // #3503 - don't "simplify" SetFunction member function to a variable void tokenize31() { ASSERT_EQUALS("struct TTestClass { TTestClass ( ) { }\n" - "void SetFunction ( Other * m_f ) { }\n" + "void SetFunction ( Other ( * m_f ) ( ) ) { }\n" "} ;", tokenizeAndStringify("struct TTestClass { TTestClass() { }\n" " void SetFunction(Other(*m_f)()) { }\n" "};")); ASSERT_EQUALS("struct TTestClass { TTestClass ( ) { }\n" - "void SetFunction ( Other * m_f ) ;\n" + "void SetFunction ( Other ( * m_f ) ( ) ) ;\n" "} ;", tokenizeAndStringify("struct TTestClass { TTestClass() { }\n" " void SetFunction(Other(*m_f)());\n" @@ -5010,10 +5010,10 @@ private: } void functionpointer1() { - ASSERT_EQUALS("void * f ;", tokenizeAndStringify("void (*f)();")); - ASSERT_EQUALS("void * * f ;", tokenizeAndStringify("void *(*f)();")); - ASSERT_EQUALS("unsigned int * f ;", tokenizeAndStringify("unsigned int (*f)();")); - ASSERT_EQUALS("unsigned int * * f ;", tokenizeAndStringify("unsigned int * (*f)();")); + ASSERT_EQUALS("void ( * f ) ( ) ;", tokenizeAndStringify("void (*f)();")); + ASSERT_EQUALS("void * ( * f ) ( ) ;", tokenizeAndStringify("void *(*f)();")); + ASSERT_EQUALS("unsigned int ( * f ) ( ) ;", tokenizeAndStringify("unsigned int (*f)();")); + ASSERT_EQUALS("unsigned int * ( * f ) ( ) ;", tokenizeAndStringify("unsigned int * (*f)();")); } void functionpointer2() { @@ -5022,8 +5022,8 @@ private: "PF pf = &f1;" "PF pfs[] = { &f1, &f1 };"; const char expected[] = "void f1 ( ) { } " - "void * pf ; pf = & f1 ; " - "void * pfs [ 2 ] = { & f1 , & f1 } ;"; + "void ( * pf ) ( ) ; pf = & f1 ; " + "void ( * pfs ) ( ) [ ] = { & f1 , & f1 } ;"; // TODO : Is [] placed correctly? ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } @@ -5043,48 +5043,40 @@ private: "{\n" " typedef void (*FP)();\n" " virtual FP getFP();\n" - " virtual void execute();\n" - "};\n" - "void f() {\n" - " int a[9];\n" - "}\n"; + "};"; const char expected[] = "1: struct S\n" "2: {\n" "3:\n" "4: virtual void * getFP ( ) ;\n" - "5: virtual void execute ( ) ;\n" - "6: } ;\n" - "7: void f ( ) {\n" - "8: int a@1 [ 9 ] ;\n" - "9: }\n"; + "5: } ;\n"; ASSERT_EQUALS(expected, tokenizeDebugListing(code, false)); } void functionpointer5() { const char code[] = ";void (*fp[])(int a) = {0,0,0};"; - const char expected[] = "1: ; void * fp@1 [ 3 ] = { 0 , 0 , 0 } ;\n"; + const char expected[] = "1: ; void ( * fp@1 [ ] ) ( ) = { 0 , 0 , 0 } ;\n"; // TODO: Array dimension ASSERT_EQUALS(expected, tokenizeDebugListing(code, false)); } void functionpointer6() { - const char code1[] = ";void (*fp(f))(int);"; - const char expected1[] = "1: ; void * fp ( f ) ;\n"; // No varId - it could be a function + const char code1[] = "void (*fp(void))(int) {}"; + const char expected1[] = "1: void * fp ( ) { }\n"; ASSERT_EQUALS(expected1, tokenizeDebugListing(code1, false)); - const char code2[] = ";std::string (*fp(f))(int);"; - const char expected2[] = "1: ; std :: string * fp ( f ) ;\n"; + const char code2[] = "std::string (*fp(void))(int);"; + const char expected2[] = "1: std :: string * fp ( ) ;\n"; ASSERT_EQUALS(expected2, tokenizeDebugListing(code2, false)); } void functionpointer7() { const char code1[] = "void (X::*y)();"; - const char expected1[] = "1: void * y@1 ;\n"; + const char expected1[] = "1: void ( * y@1 ) ( ) ;\n"; ASSERT_EQUALS(expected1, tokenizeDebugListing(code1, false)); } void functionpointer8() { const char code1[] = "int (*f)() throw(int);"; - const char expected1[] = "1: int * f@1 ;\n"; + const char expected1[] = "1: int ( * f@1 ) ( ) ;\n"; ASSERT_EQUALS(expected1, tokenizeDebugListing(code1, false)); } @@ -6014,7 +6006,7 @@ private: void borland() { // __closure - ASSERT_EQUALS("int * a ;", + ASSERT_EQUALS("int ( * a ) ( ) ;", // TODO VarId tokenizeAndStringify("int (__closure *a)();", false, true, Settings::Win32A)); // __property diff --git a/test/testvarid.cpp b/test/testvarid.cpp index 418bf94eb..08dbc4c15 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -2933,7 +2933,7 @@ private: const char expected[] = "1: struct A ;\n" "2:\n" "3: struct A {\n" - "4: bool * pFun@1 ;\n" + "4: bool ( * pFun@1 ) ( ) ;\n" "5: void setPFun ( int mode@2 ) ;\n" "6: bool funcNorm ( ) ;\n" "7: } ;\n"