Refactoring Check64BitPortability. Use ValueType.

This commit is contained in:
Daniel Marjamäki 2015-12-30 19:59:23 +01:00
parent 7f1b43e79c
commit 5216f904e7
2 changed files with 33 additions and 55 deletions

View File

@ -30,18 +30,6 @@ namespace {
Check64BitPortability instance;
}
/** Is given variable a pointer or array? */
static bool isaddr(const Variable *var)
{
return (var && (var->isPointer() || var->isArray()));
}
/** Is given variable an integer variable */
static bool isint(const Variable *var)
{
return (var && var->isIntegralType() && !var->isArrayOrPointer() && var->typeStartToken()->str() != "bool");
}
void Check64BitPortability::pointerassignment()
{
if (!_settings->isEnabled("portability"))
@ -65,30 +53,21 @@ void Check64BitPortability::pointerassignment()
continue;
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "return %name%|%num% [;+]") && !Token::simpleMatch(tok, "return 0 ;")) {
enum { NO, INT, PTR, PTRDIFF } type = NO;
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
if ((type == NO || type == INT) && Token::Match(tok2, "%var% [+;]") && isaddr(tok2->variable()))
type = PTR;
else if (type == NO && (tok2->isNumber() || isint(tok2->variable())))
type = INT;
else if (type == PTR && Token::Match(tok2, "- %var%") && isaddr(tok2->next()->variable()))
type = PTRDIFF;
else if (tok2->str() == "(") {
// TODO: handle parentheses
type = NO;
break;
} else if (type == PTR && Token::simpleMatch(tok2, "."))
type = NO; // Reset after pointer reference, see #4642
else if (tok2->str() == ";")
break;
}
if (tok->str() != "return")
continue;
if (retPointer && (type == INT || type == PTRDIFF))
returnIntegerError(tok);
else if (!retPointer && type == PTR)
returnPointerError(tok);
}
if (!tok->astOperand1() || tok->astOperand1()->isNumber())
continue;
const ValueType * const returnType = tok->astOperand1()->valueType();
if (!returnType)
continue;
if (retPointer && returnType->pointer == 0U)
returnIntegerError(tok);
if (!retPointer && returnType->pointer >= 1U)
returnPointerError(tok);
}
}
@ -96,28 +75,27 @@ void Check64BitPortability::pointerassignment()
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "[;{}] %var% = %name%")) {
const Token* tok2 = tok->tokAt(3);
while (Token::Match(tok2->next(), ".|::"))
tok2 = tok2->tokAt(2);
if (!Token::Match(tok2, "%var% ;|+"))
continue;
if (tok->str() != "=")
continue;
const Variable *var1(tok->next()->variable());
const Variable *var2(tok2->variable());
const ValueType *lhstype = tok->astOperand1() ? tok->astOperand1()->valueType() : nullptr;
const ValueType *rhstype = tok->astOperand2() ? tok->astOperand2()->valueType() : nullptr;
if (!lhstype || !rhstype)
continue;
if (isaddr(var1) && isint(var2) && tok2->strAt(1) != "+")
assignmentIntegerToAddressError(tok->next());
// Assign integer to pointer..
if (lhstype->pointer >= 1U &&
rhstype->pointer == 0U &&
rhstype->originalTypeName.empty() &&
rhstype->type == ValueType::Type::INT)
assignmentIntegerToAddressError(tok);
else if (isint(var1) && isaddr(var2) && !tok2->isPointerCompare()) {
// assigning address => warning
// some trivial addition => warning
if (Token::Match(tok2->next(), "+ %any% !!;"))
continue;
assignmentAddressToIntegerError(tok->next());
}
}
// Assign pointer to integer..
if (rhstype->pointer >= 1U &&
lhstype->pointer == 0U &&
lhstype->originalTypeName.empty() &&
lhstype->type == ValueType::Type::INT)
assignmentAddressToIntegerError(tok);
}
}
}

View File

@ -138,7 +138,7 @@ private:
" int x = 10;\n"
" int *a = x * x;\n"
"}");
TODO_ASSERT_EQUALS("error", "", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (portability) Assigning an integer to a pointer is not portable.\n", errout.str());
check("void foo(int *start, int *end) {\n"
" int len;\n"