diff --git a/lib/check64bit.cpp b/lib/check64bit.cpp index 5bb4f5ecb..86e4324a5 100644 --- a/lib/check64bit.cpp +++ b/lib/check64bit.cpp @@ -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); } } } diff --git a/test/test64bit.cpp b/test/test64bit.cpp index 8083f89f9..f703817dc 100644 --- a/test/test64bit.cpp +++ b/test/test64bit.cpp @@ -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"