Example #1
0
void Check64BitPortability::pointerassignment()
{
    if (!_settings->isEnabled("portability"))
        return;

    const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();

    // Check return values
    const std::size_t functions = symbolDatabase->functionScopes.size();
    for (std::size_t i = 0; i < functions; ++i) {
        const Scope * scope = symbolDatabase->functionScopes[i];
        if (scope->function == 0 || !scope->function->hasBody()) // We only look for functions with a body
            continue;

        bool retPointer = false;
        if (scope->function->token->strAt(-1) == "*") // Function returns a pointer
            retPointer = true;
        else if (Token::Match(scope->function->token->previous(), "int|long|DWORD")) // Function returns an integer
            ;
        else
            continue;

        for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
            // skip nested functions
            if (tok->str() == "{") {
                if (tok->scope()->type == Scope::ScopeType::eFunction)
                    tok = tok->link();
            }

            if (tok->str() != "return")
                continue;

            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);
        }
    }

    // Check assignments
    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 (tok->str() != "=")
                continue;

            const ValueType *lhstype = tok->astOperand1() ? tok->astOperand1()->valueType() : nullptr;
            const ValueType *rhstype = tok->astOperand2() ? tok->astOperand2()->valueType() : nullptr;
            if (!lhstype || !rhstype)
                continue;

            // Assign integer to pointer..
            if (lhstype->pointer >= 1U &&
                !tok->astOperand2()->isNumber() &&
                rhstype->pointer == 0U &&
                rhstype->originalTypeName.empty() &&
                rhstype->type == ValueType::Type::INT)
                assignmentIntegerToAddressError(tok);

            // Assign pointer to integer..
            if (rhstype->pointer >= 1U &&
                lhstype->pointer == 0U &&
                lhstype->originalTypeName.empty() &&
                lhstype->type == ValueType::Type::INT)
                assignmentAddressToIntegerError(tok);
        }
    }
}
Example #2
0
void Check64BitPortability::pointerassignment()
{
    if (!_settings->isEnabled("portability"))
        return;

    const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();

    // Check return values
    const std::size_t functions = symbolDatabase->functionScopes.size();
    for (std::size_t i = 0; i < functions; ++i) {
        const Scope * scope = symbolDatabase->functionScopes[i];
        if (scope->function == 0 || !scope->function->hasBody) // We only look for functions with a body
            continue;

        bool retPointer = false;
        if (scope->function->token->strAt(-1) == "*") // Function returns a pointer
            retPointer = true;
        else if (Token::Match(scope->function->token->previous(), "int|long|DWORD")) // Function returns an integer
            ;
        else
            continue;

        for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
            if (Token::Match(tok, "return %var%|%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) && 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 (Token::Match(tok2, "%type% (")) {
                        type = NO;
                        break;
                    } else if (tok2->str() == ";")
                        break;
                }

                if (retPointer && (type == INT || type == PTRDIFF))
                    returnIntegerError(tok);
                else if (!retPointer && type == PTR)
                    returnPointerError(tok);
            }
        }
    }

    // Check assignments
    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% = %var% [;+]")) {

                const Variable *var1(tok->next()->variable());
                const Variable *var2(tok->tokAt(3)->variable());

                if (isaddr(var1) && isint(var2) && tok->strAt(4) != "+")
                    assignmentIntegerToAddressError(tok->next());

                else if (isint(var1) && isaddr(var2) && !tok->tokAt(3)->isPointerCompare()) {
                    // assigning address => warning
                    // some trivial addition => warning
                    if (Token::Match(tok->tokAt(4), "+ %any% !!;"))
                        continue;

                    assignmentAddressToIntegerError(tok->next());
                }
            }
        }
    }
}