diff --git a/lib/check64bit.cpp b/lib/check64bit.cpp index eeda1c93648..63d01b96f89 100644 --- a/lib/check64bit.cpp +++ b/lib/check64bit.cpp @@ -48,6 +48,13 @@ static bool is32BitIntegerReturn(const Function* func, const Settings* settings) return vt && vt->pointer == 0 && vt->isIntegral() && vt->typeSize(settings->platform) == 4; } +static bool isFunctionPointer(const Token* tok) +{ + if (!tok || !tok->variable()) + return false; + return Tokenizer::isFunctionPointer(tok->variable()->nameToken()); +} + void Check64BitPortability::pointerassignment() { if (!mSettings->severity.isEnabled(Severity::portability)) @@ -120,7 +127,8 @@ void Check64BitPortability::pointerassignment() !tok->astOperand2()->isNumber() && rhstype->pointer == 0U && rhstype->originalTypeName.empty() && - rhstype->type == ValueType::Type::INT) + rhstype->type == ValueType::Type::INT && + !isFunctionPointer(tok->astOperand1())) assignmentIntegerToAddressError(tok); // Assign pointer to integer.. diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index da279b8f453..aaed296dc4c 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -674,7 +674,7 @@ namespace { return; mUsed = true; - const bool isFunctionPointer = Token::Match(mNameToken, "%name% )"); + const bool isFunctionPointer = Tokenizer::isFunctionPointer(mNameToken); // Special handling for T(...) when T is a pointer if (Token::Match(tok, "%name% [({]") && !isFunctionPointer && !Token::simpleMatch(tok->linkAt(1), ") (")) { @@ -1019,6 +1019,10 @@ namespace { }; } +bool Tokenizer::isFunctionPointer(const Token* tok) { + return Token::Match(tok, "%name% ) ("); +} + void Tokenizer::simplifyTypedef() { // Simplify global typedefs that are not redefined with the fast 1-pass simplification. @@ -1088,7 +1092,7 @@ void Tokenizer::simplifyTypedef() typedefInfo.lineNumber = typedefToken->linenr(); typedefInfo.column = typedefToken->column(); typedefInfo.used = t.second.isUsed(); - typedefInfo.isFunctionPointer = Token::Match(t.second.nameToken(), "%name% ) ("); + typedefInfo.isFunctionPointer = isFunctionPointer(t.second.nameToken()); if (typedefInfo.isFunctionPointer) { const Token* tok = typedefToken; while (tok != t.second.endToken()) { @@ -1622,7 +1626,7 @@ void Tokenizer::simplifyTypedefCpp() typedefInfo.lineNumber = typeName->linenr(); typedefInfo.column = typeName->column(); typedefInfo.used = false; - typedefInfo.isFunctionPointer = Token::Match(typeName, "%name% ) ("); + typedefInfo.isFunctionPointer = isFunctionPointer(typeName); if (typedefInfo.isFunctionPointer) { const Token* t = typeDef; while (t != tok) { @@ -7155,7 +7159,7 @@ void Tokenizer::simplifyFunctionPointers() while (Token::Match(tok2, "%type%|:: %type%|::")) tok2 = tok2->next(); - if (!Token::Match(tok2, "%name% ) (") && + if (!isFunctionPointer(tok2) && !Token::Match(tok2, "%name% [ ] ) (") && !(Token::Match(tok2, "%name% (") && Token::simpleMatch(tok2->linkAt(1), ") ) ("))) continue; @@ -7448,7 +7452,7 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co } // Function pointer if (Token::simpleMatch(varName, "( *") && - Token::Match(varName->link()->previous(), "%name% ) (") && + isFunctionPointer(varName->link()->previous()) && Token::simpleMatch(varName->link()->linkAt(1), ") =")) { Token *endDecl = varName->link()->linkAt(1); varName = varName->link()->previous(); @@ -9376,7 +9380,7 @@ Token* Tokenizer::getAttributeFuncTok(Token* tok, bool gccattr) const { if (Token::simpleMatch(prev, ")")) { if (Token::Match(prev->link()->previous(), "%name% (")) return prev->link()->previous(); - if (Token::Match(prev->link()->tokAt(-2), "%name% ) (")) + if (isFunctionPointer(prev->link()->tokAt(-2))) return prev->link()->tokAt(-2); } if (Token::simpleMatch(prev, ")") && Token::Match(prev->link()->tokAt(-2), "operator %op% (") && isCPP()) diff --git a/lib/tokenize.h b/lib/tokenize.h index f9feebb43f0..d001c54cb10 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -601,7 +601,7 @@ class CPPCHECKLIB Tokenizer { /** * Helper function to check whether number is one (1 or 0.1E+1 or 1E+0) or not? * @param s the string to check - * @return true in case is is one and false otherwise. + * @return true in case it is one and false otherwise. */ static bool isOneNumber(const std::string &s); @@ -613,6 +613,13 @@ class CPPCHECKLIB Tokenizer { */ static const Token * startOfExecutableScope(const Token * tok); + /** + * Helper function to check whether tok is the declaration of a function pointer + * @param tok the Token to check + * @return true in case tok is a function pointer and false otherwise. + */ + static bool isFunctionPointer(const Token* tok); + const Settings &getSettings() const { return mSettings; } diff --git a/test/test64bit.cpp b/test/test64bit.cpp index e3b83c98060..6f9a5fbda2f 100644 --- a/test/test64bit.cpp +++ b/test/test64bit.cpp @@ -67,6 +67,12 @@ class Test64BitPortability : public TestFixture { " t.a[i][j] = new std::vector;\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("int f();\n" // #11522 + "void g() {\n" + " int (*fp)() = *(int(*)())f;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void novardecl() {