diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 74c1de092..e40d873cc 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -377,11 +377,6 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti function.isExplicit = true; } - // function returning function pointer - else if (tok->str() == "(") { - function.retFuncPtr = true; - } - const Token *tok1 = tok; // look for end of previous statement @@ -416,12 +411,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti function.retDef = tok1; } - const Token *end; - - if (!function.retFuncPtr) - end = function.argDef->link(); - else - end = tok->link()->next()->link(); + const Token *end = function.argDef->link(); // const function if (end->next()->str() == "const") @@ -635,10 +625,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // function? if (isFunction(tok, scope, &funcStart, &argStart)) { - bool retFuncPtr = Token::simpleMatch(argStart->link(), ") ) ("); const Token* scopeBegin = argStart->link()->next(); - if (retFuncPtr) - scopeBegin = scopeBegin->next()->link()->next(); if (scopeBegin->isName()) { // Jump behind 'const' or unknown Macro scopeBegin = scopeBegin->next(); if (scopeBegin->str() == "throw") @@ -666,7 +653,6 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti Function* function = addGlobalFunction(scope, tok, argStart, funcStart); if (!function) _tokenizer->syntaxError(tok); - function->retFuncPtr = retFuncPtr; // global functions can't be const but we have tests that are if (Token::Match(argStart->link(), ") const| noexcept")) { @@ -709,7 +695,6 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // save function prototype in database if (newFunc) { Function* func = addGlobalFunctionDecl(scope, tok, argStart, funcStart); - func->retFuncPtr = retFuncPtr; if (Token::Match(argStart->link(), ") const| noexcept")) { int arg = 2; @@ -1529,18 +1514,12 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To func->hasBody = true; } else if (func->type != Function::eDestructor && !destructor) { // normal function? - if (!func->retFuncPtr && (*tok)->next()->link()) { + if ((*tok)->next()->link()) { if ((func->isConst && (*tok)->next()->link()->next()->str() == "const") || (!func->isConst && (*tok)->next()->link()->next()->str() != "const")) { func->hasBody = true; } } - - // function returning function pointer? - else if (func->retFuncPtr) { - // todo check for const - func->hasBody = true; - } } if (func->hasBody) { @@ -1915,7 +1894,6 @@ void SymbolDatabase::printOut(const char *title) const std::cout << " isNoExcept: " << (func->isNoExcept ? "true" : "false") << std::endl; std::cout << " isThrow: " << (func->isThrow ? "true" : "false") << std::endl; std::cout << " isOperator: " << (func->isOperator ? "true" : "false") << std::endl; - std::cout << " retFuncPtr: " << (func->retFuncPtr ? "true" : "false") << std::endl; std::cout << " noexceptArg: " << (func->noexceptArg ? func->noexceptArg->str() : "none") << std::endl; std::cout << " throwArg: " << (func->throwArg ? func->throwArg->str() : "none") << std::endl; std::cout << " tokenDef: " << func->tokenDef->str() << " " <<_tokenizer->list.fileLine(func->tokenDef) << std::endl; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 6fe814fbe..730408f47 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -547,7 +547,6 @@ public: isNoExcept(false), isThrow(false), isOperator(false), - retFuncPtr(false), noexceptArg(nullptr), throwArg(nullptr) { } @@ -617,7 +616,6 @@ public: bool isNoExcept; // is noexcept bool isThrow; // is throw bool isOperator; // is operator - bool retFuncPtr; // returns function pointer const Token *noexceptArg; const Token *throwArg; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 7336ba1ee..05e284261 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5053,25 +5053,35 @@ void Tokenizer:: simplifyFunctionPointers() else if (tok->previous() && !Token::Match(tok->previous(), "{|}|;|,|(|public:|protected:|private:")) continue; - if (Token::Match(tok, "%type% *| *| ( * %var% [| ]| ) (")) - ; - else if (Token::Match(tok, "%type% %type% *| *| ( * %var% [| ]| ) (")) + while (Token::Match(tok, "%type%|:: %type%|::")) tok = tok->next(); - else + + Token *tok2 = (tok && tok->isName()) ? tok->next() : nullptr; + while (Token::Match(tok2, "*|&")) + tok2 = tok2->next(); + if (!Token::Match(tok2, "( * %var%")) + continue; + tok2 = tok2->tokAt(2); + while (Token::Match(tok2, "%type%|:: %type%|::")) + tok2 = tok2->next(); + + if (!Token::Match(tok2, "%var% ) (") && + !Token::Match(tok2, "%var% [ ] ) (") && + !(Token::Match(tok2, "%var% (") && Token::Match(tok2->linkAt(1), ") ) ("))) continue; - while (tok->next()->str() == "*") + while (tok->str() != "(") tok = tok->next(); // check that the declaration ends - const Token *endTok = tok->next()->link()->next()->link(); - if (!Token::Match(endTok, ") ;|,|)|=|[")) + const Token *endTok = tok->link()->next()->link(); + if (!Token::Match(endTok, ") ;|,|)|=|[|{")) continue; // ok simplify this function pointer to an ordinary pointer - Token::eraseTokens(tok->next()->link(), endTok->next()); - tok->next()->link()->deleteThis(); - tok->deleteNext(); + Token::eraseTokens(tok->link(), endTok->next()); + tok->link()->deleteThis(); + tok->deleteThis(); } } diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 161097432..9555b69f6 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -3945,7 +3945,7 @@ private: const char expected[] = "class Fred { " "" - "void ( * get ( ) ) ( ) { return test ; } " + "void * get ( ) { return test ; } " "static void test ( ) { } " "} ;"; @@ -3962,7 +3962,7 @@ private: const char expected[] = "class Fred { " "" - "void * ( * get ( ) ) ( void * ) { return test ; } " + "void * * get ( ) { return test ; } " "static void * test ( void * p ) { return p ; } " "} ;"; @@ -3979,7 +3979,7 @@ private: const char expected[] = "class Fred { " "" - "unsigned int * ( * get ( ) ) ( unsigned int * ) { return test ; } " + "unsigned int * * get ( ) { return test ; } " "static unsigned int * test ( unsigned int * p ) { return p ; } " "} ;"; @@ -3997,7 +3997,7 @@ private: const char expected[] = "class Fred { " "" - "const unsigned int * ( * get ( ) ) ( const unsigned int * ) { return test ; } " + "const unsigned int * * get ( ) { return test ; } " "const static unsigned int * test ( const unsigned int * p ) { return p ; } " "} ;"; @@ -4014,7 +4014,7 @@ private: const char expected[] = "class Fred { " "" - "void * ( * get ( int i ) ) ( void * ) { return test ; } " + "void * * get ( int i ) { return test ; } " "static void * test ( void * p ) { return p ; } " "} ;"; @@ -5416,11 +5416,11 @@ private: const char expected1[] = "namespace NS { " "" "class A { " - "int ( * f ( ) ) ( ) ; " + "int * f ( ) ; " "} ; " "} " "namespace NS { " - "int ( * A :: f ( ) ) ( ) { } " + "int * A :: f ( ) { } " "}"; checkSimplifyTypedef(code1); ASSERT_EQUALS(expected1, tok(code1)); @@ -5436,10 +5436,10 @@ private: const char expected2[] = "namespace NS { " "" "class A { " - "int ( * f ( ) ) ( ) ; " + "int * f ( ) ; " "} ; " "} " - "int ( * NS :: A :: f ( ) ) ( ) { }"; + "int * NS :: A :: f ( ) { }"; checkSimplifyTypedef(code2); ASSERT_EQUALS(expected2, tok(code2)); ASSERT_EQUALS("", errout.str()); @@ -5461,13 +5461,13 @@ private: "namespace NS2 { " "" "class A { " - "int ( * f ( ) ) ( ) ; " + "int * f ( ) ; " "} ; " "} " "} " "namespace NS1 { " "namespace NS2 { " - "int ( * A :: f ( ) ) ( ) { } " + "int * A :: f ( ) { } " "} " "}"; checkSimplifyTypedef(code3); @@ -5489,12 +5489,12 @@ private: "namespace NS2 { " "" "class A { " - "int ( * f ( ) ) ( ) ; " + "int * f ( ) ; " "} ; " "} " "} " "namespace NS1 { " - "int ( * NS2 :: A :: f ( ) ) ( ) { } " + "int * NS2 :: A :: f ( ) { } " "}"; checkSimplifyTypedef(code4); ASSERT_EQUALS(expected4, tok(code4)); @@ -5588,8 +5588,7 @@ private: "};\n"; const char expected[] = "class symbol_table { " "public: " - "" - "expression_error :: error_code ( * f ) ( void * cbparam , const char * name , expression_space space ) ; " + "expression_error :: error_code * f ; " "} ;"; checkSimplifyTypedef(code); @@ -6158,8 +6157,8 @@ private: // The expected result.. const std::string expected("int ( * ( * t1 ) ( bool ) ) ( int , int ) ; " - "int ( * t2 ( bool ) ) ( int , int ) ; " - "int ( * t3 ( bool ) ) ( int , int ) ;"); + "int * t2 ( bool ) ; " + "int * t3 ( bool ) ;"); ASSERT_EQUALS(expected, tok(code, false)); checkSimplifyTypedef(code); @@ -6194,9 +6193,9 @@ private: // The expected result.. const std::string expected("int * t1 ; " // simplified to regular pointer - "int ( * const t2 ) ( float ) ; " + "int * const t2 ; " "int * t3 ; " // volatile removed, gets simplified to regular pointer - "int ( * const t4 ) ( float ) ; " // volatile removed + "int * const t4 ; " // volatile removed "int ( C :: * t5 ) ( float ) ; " "int ( C :: * const t6 ) ( float ) ; " "int ( C :: * t7 ) ( float ) ; " // volatile removed @@ -6226,13 +6225,13 @@ private: // The expected result.. const std::string expected("struct Fred " "{ " - "void ( * get1 ( ) ) ( ) { return 0 ; } " - "void ( * get2 ( ) ) ( ) { return 0 ; } " - "void ( * get3 ( ) ) ( ) ; " - "void ( * get4 ( ) ) ( ) ; " + "void * get1 ( ) { return 0 ; } " + "void * get2 ( ) { return 0 ; } " + "void * get3 ( ) ; " + "void * get4 ( ) ; " "} ; " - "void ( * Fred :: get3 ( ) ) ( ) { return 0 ; } " - "void ( * Fred :: get4 ( ) ) ( ) { return 0 ; }"); + "void * Fred :: get3 ( ) { return 0 ; } " + "void * Fred :: get4 ( ) { return 0 ; }"); ASSERT_EQUALS(expected, tok(code, false)); @@ -7663,10 +7662,10 @@ private: "};"; const char expected[] = "struct Fred " "{ " - "void ( * get1 ( ) ) ( ) { return 0 ; } " - "void ( * get2 ( ) ) ( ) { return 0 ; } " - "void ( * get3 ( ) ) ( ) ; " - "void ( * get4 ( ) ) ( ) ; " + "void * get1 ( ) { return 0 ; } " + "void * get2 ( ) { return 0 ; } " + "void * get3 ( ) ; " + "void * get4 ( ) ; " "} ;"; ASSERT_EQUALS(expected, tok(code, false)); } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index b7a8a7a29..5c34ea792 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -712,7 +712,9 @@ private: ASSERT(db && db->scopeList.size() == 3); if (db) { - const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(4)); + const Token * const functionToken = Token::findmatch(tokenizer.tokens(), "func"); + + const Scope *scope = findFunctionScopeByToken(db, functionToken); ASSERT(scope && scope->className == "func"); ASSERT(scope && scope->functionOf && scope->functionOf == db->findScopeByName("Fred")); @@ -720,10 +722,10 @@ private: const Function *function = findFunctionByName("func", &db->scopeList.back()); ASSERT(function && function->token->str() == "func"); - ASSERT(function && function->token == tokenizer.tokens()->tokAt(4)); + ASSERT(function && function->token == functionToken); ASSERT(function && function->hasBody && function->isInline); ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred")); - ASSERT(function && function->retDef == tokenizer.tokens()->tokAt(3)); + ASSERT(function && function->retDef == functionToken->previous()); ASSERT(db && db->findScopeByName("Fred") && db->findScopeByName("Fred")->definedType->getFunction("func") == function); } @@ -736,14 +738,16 @@ private: ASSERT(db && db->scopeList.size() == 2); if (db) { - const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(4)); + const Token * const functionToken = Token::findmatch(tokenizer.tokens(), "func"); + + const Scope *scope = findFunctionScopeByToken(db, functionToken); ASSERT(scope == nullptr); const Function *function = findFunctionByName("func", &db->scopeList.back()); ASSERT(function && function->token->str() == "func"); - ASSERT(function && function->token == tokenizer.tokens()->tokAt(4)); + ASSERT(function && function->token == functionToken); ASSERT(function && !function->hasBody); } } @@ -755,7 +759,9 @@ private: ASSERT(db && db->scopeList.size() == 3); if (db) { - const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(12)); + const Token * const functionToken = Token::findmatch(tokenizer.tokens()->linkAt(2), "func"); + + const Scope *scope = findFunctionScopeByToken(db, functionToken); ASSERT(scope && scope->className == "func"); ASSERT(scope && scope->functionOf && scope->functionOf == db->findScopeByName("Fred")); @@ -763,7 +769,7 @@ private: const Function *function = findFunctionByName("func", &db->scopeList.back()); ASSERT(function && function->token->str() == "func"); - ASSERT(function && function->token == tokenizer.tokens()->tokAt(12)); + ASSERT(function && function->token == functionToken); ASSERT(function && function->hasBody && !function->isInline); ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred")); } @@ -776,15 +782,17 @@ private: ASSERT(db && db->scopeList.size() == 2); if (db) { - const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(3)); + const Token * const functionToken = Token::findmatch(tokenizer.tokens(), "func"); + + const Scope *scope = findFunctionScopeByToken(db, functionToken); ASSERT(scope && scope->className == "func"); const Function *function = findFunctionByName("func", &db->scopeList.front()); ASSERT(function && function->token->str() == "func"); - ASSERT(function && function->token == tokenizer.tokens()->tokAt(3)); - ASSERT(function && function->hasBody && function->retFuncPtr); + ASSERT(function && function->token == functionToken); + ASSERT(function && function->hasBody); } } @@ -795,15 +803,17 @@ private: ASSERT(db && db->scopeList.size() == 3); if (db) { - const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(6)); + const Token * const functionToken = Token::findmatch(tokenizer.tokens(), "func"); + + const Scope *scope = findFunctionScopeByToken(db, functionToken); ASSERT(scope && scope->className == "func"); const Function *function = findFunctionByName("func", &db->scopeList.back()); ASSERT(function && function->token->str() == "func"); - ASSERT(function && function->token == tokenizer.tokens()->tokAt(6)); - ASSERT(function && function->hasBody && function->isInline && function->retFuncPtr); + ASSERT(function && function->token == functionToken); + ASSERT(function && function->hasBody && function->isInline); } } @@ -814,15 +824,17 @@ private: ASSERT(db && db->scopeList.size() == 2); if (db) { - const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(6)); + const Token * const functionToken = Token::findmatch(tokenizer.tokens(), "func"); + + const Scope *scope = findFunctionScopeByToken(db, functionToken); ASSERT(scope == nullptr); const Function *function = findFunctionByName("func", &db->scopeList.back()); ASSERT(function && function->token->str() == "func"); - ASSERT(function && function->token == tokenizer.tokens()->tokAt(6)); - ASSERT(function && !function->hasBody && function->retFuncPtr); + ASSERT(function && function->token == functionToken); + ASSERT(function && !function->hasBody); } } @@ -833,15 +845,17 @@ private: ASSERT(db && db->scopeList.size() == 3); if (db) { - const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(23)); + const Token * const functionToken = Token::findmatch(tokenizer.tokens()->linkAt(2), "func"); + + const Scope *scope = findFunctionScopeByToken(db, functionToken); ASSERT(scope && scope->className == "func"); const Function *function = findFunctionByName("func", &db->scopeList.back()); ASSERT(function && function->token->str() == "func"); - ASSERT(function && function->token == tokenizer.tokens()->tokAt(23)); - ASSERT(function && function->hasBody && !function->isInline && function->retFuncPtr); + ASSERT(function && function->token == functionToken); + ASSERT(function && function->hasBody && !function->isInline); } } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index d36a4fce7..d03f927af 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -437,6 +437,7 @@ private: TEST_CASE(functionpointer3); TEST_CASE(functionpointer4); TEST_CASE(functionpointer5); + TEST_CASE(functionpointer6); TEST_CASE(removeRedundantAssignment); @@ -3881,7 +3882,7 @@ private: void varid40() { const char code[] ="extern \"C\" int (*a())();"; ASSERT_EQUALS("\n\n##file 0\n" - "1: int ( * a ( ) ) ( ) ;\n", + "1: int * a ( ) ;\n", tokenizeDebugListing(code)); } @@ -7032,7 +7033,7 @@ private: "1: struct S\n" "2: {\n" "3:\n" - "4: virtual void ( * getFP ( ) ) ( ) ;\n" + "4: virtual void * getFP ( ) ;\n" "5: virtual void execute ( ) ;\n" "6: } ;\n" "7: void f ( ) {\n" @@ -7048,6 +7049,18 @@ private: ASSERT_EQUALS(expected, tokenizeDebugListing(code, false)); } + void functionpointer6() { + const char code1[] = ";void (*fp(f))(int);"; + const char expected1[] = "\n\n##file 0\n" + "1: ; void * fp@1 ( f ) ;\n"; + ASSERT_EQUALS(expected1, tokenizeDebugListing(code1, false)); + + const char code2[] = ";std::string (*fp(f))(int);"; + const char expected2[] = "\n\n##file 0\n" + "1: ; std :: string * fp@1 ( f ) ;\n"; + ASSERT_EQUALS(expected2, tokenizeDebugListing(code2, false)); + } + void removeRedundantAssignment() { ASSERT_EQUALS("void f ( ) { }", tokenizeAndStringify("void f() { int *p, *q; p = q; }", true)); ASSERT_EQUALS("void f ( ) { }", tokenizeAndStringify("void f() { int *p = 0, *q; p = q; }", true));