Refactoring Check64BitPortability. Use ValueType.
This commit is contained in:
parent
7f1b43e79c
commit
5216f904e7
|
@ -30,18 +30,6 @@ namespace {
|
||||||
Check64BitPortability instance;
|
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()
|
void Check64BitPortability::pointerassignment()
|
||||||
{
|
{
|
||||||
if (!_settings->isEnabled("portability"))
|
if (!_settings->isEnabled("portability"))
|
||||||
|
@ -65,30 +53,21 @@ void Check64BitPortability::pointerassignment()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
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 ;")) {
|
if (tok->str() != "return")
|
||||||
enum { NO, INT, PTR, PTRDIFF } type = NO;
|
continue;
|
||||||
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 (retPointer && (type == INT || type == PTRDIFF))
|
if (!tok->astOperand1() || tok->astOperand1()->isNumber())
|
||||||
returnIntegerError(tok);
|
continue;
|
||||||
else if (!retPointer && type == PTR)
|
|
||||||
returnPointerError(tok);
|
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) {
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
|
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "[;{}] %var% = %name%")) {
|
if (tok->str() != "=")
|
||||||
const Token* tok2 = tok->tokAt(3);
|
continue;
|
||||||
while (Token::Match(tok2->next(), ".|::"))
|
|
||||||
tok2 = tok2->tokAt(2);
|
|
||||||
if (!Token::Match(tok2, "%var% ;|+"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const Variable *var1(tok->next()->variable());
|
const ValueType *lhstype = tok->astOperand1() ? tok->astOperand1()->valueType() : nullptr;
|
||||||
const Variable *var2(tok2->variable());
|
const ValueType *rhstype = tok->astOperand2() ? tok->astOperand2()->valueType() : nullptr;
|
||||||
|
if (!lhstype || !rhstype)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (isaddr(var1) && isint(var2) && tok2->strAt(1) != "+")
|
// Assign integer to pointer..
|
||||||
assignmentIntegerToAddressError(tok->next());
|
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()) {
|
// Assign pointer to integer..
|
||||||
// assigning address => warning
|
if (rhstype->pointer >= 1U &&
|
||||||
// some trivial addition => warning
|
lhstype->pointer == 0U &&
|
||||||
if (Token::Match(tok2->next(), "+ %any% !!;"))
|
lhstype->originalTypeName.empty() &&
|
||||||
continue;
|
lhstype->type == ValueType::Type::INT)
|
||||||
|
assignmentAddressToIntegerError(tok);
|
||||||
assignmentAddressToIntegerError(tok->next());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,7 @@ private:
|
||||||
" int x = 10;\n"
|
" int x = 10;\n"
|
||||||
" int *a = x * x;\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"
|
check("void foo(int *start, int *end) {\n"
|
||||||
" int len;\n"
|
" int len;\n"
|
||||||
|
|
Loading…
Reference in New Issue