Tokenizer: Do not simplify function pointers to normal pointers as we loose important information

This commit is contained in:
Daniel Marjamäki 2020-04-10 11:53:32 +02:00
parent e0c8118c02
commit 0725c2290c
7 changed files with 122 additions and 97 deletions

View File

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

View File

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

View File

@ -2994,6 +2994,7 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::stri
bool hasstruct = false; // Is there a "struct" or "class"?
bool bracket = false;
bool ref = false;
bool par = false;
while (tok2) {
if (tok2->isName()) {
if (cpp && Token::Match(tok2, "namespace|public|private|protected"))
@ -3042,7 +3043,7 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::stri
}
} else if (Token::Match(tok2, "&|&&")) {
ref = !bracket;
} else if (singleNameCount == 1 && Token::Match(tok2, "( [*&]") && Token::Match(tok2->link()->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

View File

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

View File

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

View File

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

View File

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