Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion lib/check64bit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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..
Expand Down
16 changes: 10 additions & 6 deletions lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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), ") (")) {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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())
Expand Down
9 changes: 8 additions & 1 deletion lib/tokenize.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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;
}
Expand Down
6 changes: 6 additions & 0 deletions test/test64bit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ class Test64BitPortability : public TestFixture {
" t.a[i][j] = new std::vector<int>;\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() {
Expand Down
Loading