64-bit portability: fixed two of the TODO test cases. Ticket: #2791

This commit is contained in:
Daniel Marjamäki 2011-07-06 17:57:39 +02:00
parent f39e462e8e
commit 4055b0ec5f
3 changed files with 37 additions and 17 deletions

View File

@ -31,6 +31,19 @@ namespace
Check64BitPortability instance; Check64BitPortability instance;
} }
/** Is given variable a pointer or array? */
static bool isaddr(const Variable *var)
{
const Token *nametok = var ? var->nameToken() : 0;
return (var && (nametok->strAt(-1) == "*" || nametok->strAt(1) == "["));
}
/** Is given variable an integer variable */
static bool isint(const Variable *var)
{
return (var && Token::Match(var->nameToken()->previous(), "int|long|DWORD"));
}
void Check64BitPortability::pointerassignment() void Check64BitPortability::pointerassignment()
{ {
if (!_settings->_checkCodingStyle) if (!_settings->_checkCodingStyle)
@ -38,35 +51,40 @@ void Check64BitPortability::pointerassignment()
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{ {
if (Token::Match(tok, "[;{}] %var% = %var% ;")) if (Token::Match(tok, "[;{}] %var% = %var% [;+]"))
{ {
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
const Variable *var1(symbolDatabase->getVariableFromVarId(tok->tokAt(1)->varId())); const Variable *var1(symbolDatabase->getVariableFromVarId(tok->tokAt(1)->varId()));
const Variable *var2(symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId())); const Variable *var2(symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId()));
if (!var1 || !var2)
continue;
// Check if var1 is an int/long/DWORD variable if (isaddr(var1) && isint(var2))
if (!Token::Match(var1->nameToken()->previous(), "int|long|DWORD")) assignmentIntegerToAddressError(tok->next());
continue;
// Check if var2 is a pointer variable else if (isint(var1) && isaddr(var2))
if (!Token::simpleMatch(var2->nameToken()->previous(), "*")) assignmentAddressToIntegerError(tok->next());
continue;
pointerassignmentError(tok->next());
} }
} }
} }
void Check64BitPortability::pointerassignmentError(const Token *tok) void Check64BitPortability::assignmentAddressToIntegerError(const Token *tok)
{ {
reportError(tok, Severity::portability, reportError(tok, Severity::portability,
"addresstoint", "AssignmentAddressToInteger",
"Assigning an address value to the integer (int/long/etc) type is not portable\n" "Assigning an address value to the integer (int/long/etc) type is not portable\n"
"Assigning an address value to the integer (int/long/etc) type is not portable across different platforms and " "Assigning an address value to the integer (int/long/etc) type is not portable across different platforms and "
"compilers. For example in 32-bit Windows and linux they are same width, but in 64-bit Windows and linux " "compilers. For example in 32-bit Windows and linux they are same width, but in 64-bit Windows and linux "
"they are of different width. In worst case you end up assigning 64-bit address to 32-bit integer. The safe " "they are of different width. In worst case you end up assigning 64-bit address to 32-bit integer. The safe "
"way is to always assign addresses only to pointer types (or typedefs)."); "way is to always assign addresses only to pointer types (or typedefs).");
} }
void Check64BitPortability::assignmentIntegerToAddressError(const Token *tok)
{
reportError(tok, Severity::portability,
"AssignmentIntegerToAddress",
"Assigning an integer (int/long/etc) to a pointer is not portable\n"
"Assigning an integer (int/long/etc) to a pointer is not portable across different platforms and "
"compilers. For example in 32-bit Windows and linux they are same width, but in 64-bit Windows and linux "
"they are of different width. In worst case you end up assigning 32-bit integer to 64-bit pointer. The safe "
"way is to always assign address to pointer.");
}

View File

@ -66,12 +66,14 @@ public:
private: private:
void pointerassignmentError(const Token *tok); void assignmentAddressToIntegerError(const Token *tok);
void assignmentIntegerToAddressError(const Token *tok);
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
{ {
Check64BitPortability c(0, settings, errorLogger); Check64BitPortability c(0, settings, errorLogger);
c.pointerassignmentError(0); c.assignmentAddressToIntegerError(0);
c.assignmentIntegerToAddressError(0);
} }
std::string myName() const std::string myName() const

View File

@ -83,14 +83,14 @@ private:
" int a = p;\n" " int a = p;\n"
" return a + 4;\n" " return a + 4;\n"
"}\n"); "}\n");
TODO_ASSERT_EQUALS("[test.cpp:3]: (portability) Assigning an address value to the integer (int/long/etc) type is not portable\n", "", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (portability) Assigning an address value to the integer (int/long/etc) type is not portable\n", errout.str());
check("void foo(int x)\n" check("void foo(int x)\n"
"{\n" "{\n"
" int *p = x;\n" " int *p = x;\n"
" *p = 0;\n" " *p = 0;\n"
"}\n"); "}\n");
TODO_ASSERT_EQUALS("[test.cpp:3]: (portability) Assigning an address value to the integer (int/long/etc) type is not portable\n", "", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (portability) Assigning an integer (int/long/etc) to a pointer is not portable\n", errout.str());
} }
void structmember() void structmember()