Skip to content

Commit 2fee3b4

Browse files
Partial fix for #11522 FP AssignmentIntegerToAddress with function pointer (#8009)
1 parent dfc639c commit 2fee3b4

File tree

4 files changed

+33
-8
lines changed

4 files changed

+33
-8
lines changed

lib/check64bit.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ static bool is32BitIntegerReturn(const Function* func, const Settings* settings)
4848
return vt && vt->pointer == 0 && vt->isIntegral() && vt->typeSize(settings->platform) == 4;
4949
}
5050

51+
static bool isFunctionPointer(const Token* tok)
52+
{
53+
if (!tok || !tok->variable())
54+
return false;
55+
return Tokenizer::isFunctionPointer(tok->variable()->nameToken());
56+
}
57+
5158
void Check64BitPortability::pointerassignment()
5259
{
5360
if (!mSettings->severity.isEnabled(Severity::portability))
@@ -120,7 +127,8 @@ void Check64BitPortability::pointerassignment()
120127
!tok->astOperand2()->isNumber() &&
121128
rhstype->pointer == 0U &&
122129
rhstype->originalTypeName.empty() &&
123-
rhstype->type == ValueType::Type::INT)
130+
rhstype->type == ValueType::Type::INT &&
131+
!isFunctionPointer(tok->astOperand1()))
124132
assignmentIntegerToAddressError(tok);
125133

126134
// Assign pointer to integer..

lib/tokenize.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ namespace {
674674
return;
675675

676676
mUsed = true;
677-
const bool isFunctionPointer = Token::Match(mNameToken, "%name% )");
677+
const bool isFunctionPointer = Tokenizer::isFunctionPointer(mNameToken);
678678

679679
// Special handling for T(...) when T is a pointer
680680
if (Token::Match(tok, "%name% [({]") && !isFunctionPointer && !Token::simpleMatch(tok->linkAt(1), ") (")) {
@@ -1019,6 +1019,10 @@ namespace {
10191019
};
10201020
}
10211021

1022+
bool Tokenizer::isFunctionPointer(const Token* tok) {
1023+
return Token::Match(tok, "%name% ) (");
1024+
}
1025+
10221026
void Tokenizer::simplifyTypedef()
10231027
{
10241028
// Simplify global typedefs that are not redefined with the fast 1-pass simplification.
@@ -1088,7 +1092,7 @@ void Tokenizer::simplifyTypedef()
10881092
typedefInfo.lineNumber = typedefToken->linenr();
10891093
typedefInfo.column = typedefToken->column();
10901094
typedefInfo.used = t.second.isUsed();
1091-
typedefInfo.isFunctionPointer = Token::Match(t.second.nameToken(), "%name% ) (");
1095+
typedefInfo.isFunctionPointer = isFunctionPointer(t.second.nameToken());
10921096
if (typedefInfo.isFunctionPointer) {
10931097
const Token* tok = typedefToken;
10941098
while (tok != t.second.endToken()) {
@@ -1622,7 +1626,7 @@ void Tokenizer::simplifyTypedefCpp()
16221626
typedefInfo.lineNumber = typeName->linenr();
16231627
typedefInfo.column = typeName->column();
16241628
typedefInfo.used = false;
1625-
typedefInfo.isFunctionPointer = Token::Match(typeName, "%name% ) (");
1629+
typedefInfo.isFunctionPointer = isFunctionPointer(typeName);
16261630
if (typedefInfo.isFunctionPointer) {
16271631
const Token* t = typeDef;
16281632
while (t != tok) {
@@ -7155,7 +7159,7 @@ void Tokenizer::simplifyFunctionPointers()
71557159
while (Token::Match(tok2, "%type%|:: %type%|::"))
71567160
tok2 = tok2->next();
71577161

7158-
if (!Token::Match(tok2, "%name% ) (") &&
7162+
if (!isFunctionPointer(tok2) &&
71597163
!Token::Match(tok2, "%name% [ ] ) (") &&
71607164
!(Token::Match(tok2, "%name% (") && Token::simpleMatch(tok2->linkAt(1), ") ) (")))
71617165
continue;
@@ -7448,7 +7452,7 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co
74487452
}
74497453
// Function pointer
74507454
if (Token::simpleMatch(varName, "( *") &&
7451-
Token::Match(varName->link()->previous(), "%name% ) (") &&
7455+
isFunctionPointer(varName->link()->previous()) &&
74527456
Token::simpleMatch(varName->link()->linkAt(1), ") =")) {
74537457
Token *endDecl = varName->link()->linkAt(1);
74547458
varName = varName->link()->previous();
@@ -9376,7 +9380,7 @@ Token* Tokenizer::getAttributeFuncTok(Token* tok, bool gccattr) const {
93769380
if (Token::simpleMatch(prev, ")")) {
93779381
if (Token::Match(prev->link()->previous(), "%name% ("))
93789382
return prev->link()->previous();
9379-
if (Token::Match(prev->link()->tokAt(-2), "%name% ) ("))
9383+
if (isFunctionPointer(prev->link()->tokAt(-2)))
93809384
return prev->link()->tokAt(-2);
93819385
}
93829386
if (Token::simpleMatch(prev, ")") && Token::Match(prev->link()->tokAt(-2), "operator %op% (") && isCPP())

lib/tokenize.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ class CPPCHECKLIB Tokenizer {
601601
/**
602602
* Helper function to check whether number is one (1 or 0.1E+1 or 1E+0) or not?
603603
* @param s the string to check
604-
* @return true in case is is one and false otherwise.
604+
* @return true in case it is one and false otherwise.
605605
*/
606606
static bool isOneNumber(const std::string &s);
607607

@@ -613,6 +613,13 @@ class CPPCHECKLIB Tokenizer {
613613
*/
614614
static const Token * startOfExecutableScope(const Token * tok);
615615

616+
/**
617+
* Helper function to check whether tok is the declaration of a function pointer
618+
* @param tok the Token to check
619+
* @return true in case tok is a function pointer and false otherwise.
620+
*/
621+
static bool isFunctionPointer(const Token* tok);
622+
616623
const Settings &getSettings() const {
617624
return mSettings;
618625
}

test/test64bit.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ class Test64BitPortability : public TestFixture {
6767
" t.a[i][j] = new std::vector<int>;\n"
6868
"}\n");
6969
ASSERT_EQUALS("", errout_str());
70+
71+
check("int f();\n" // #11522
72+
"void g() {\n"
73+
" int (*fp)() = *(int(*)())f;\n"
74+
"}\n");
75+
ASSERT_EQUALS("", errout_str());
7076
}
7177

7278
void novardecl() {

0 commit comments

Comments
 (0)