Exemple #1
0
static bool astHasAutoResult(const Token *tok)
{
    if (tok->astOperand1() && !astHasAutoResult(tok->astOperand1()))
        return false;
    if (tok->astOperand2() && !astHasAutoResult(tok->astOperand2()))
        return false;

    if (tok->isOp())
        return true;

    if (tok->isLiteral())
        return true;

    if (tok->isName()) {
        // TODO: check function calls, struct members, arrays, etc also
        if (!tok->variable())
            return false;
        if (tok->variable()->isStlType() && !Token::Match(tok->astParent(), "<<|>>"))
            return true;
        if (tok->variable()->isClass() || tok->variable()->isPointer() || tok->variable()->isReference()) // TODO: Properly handle pointers/references to classes in symbol database
            return false;

        return true;
    }

    return false;
}
static bool astHasAutoResult(const Token *tok)
{
    if (tok->astOperand1() && !astHasAutoResult(tok->astOperand1()))
        return false;
    if (tok->astOperand2() && !astHasAutoResult(tok->astOperand2()))
        return false;

    if (tok->isOp()) {
        if ((tok->str() == "<<" || tok->str() == ">>") && tok->astOperand1()) {
            const Token* tok2 = tok->astOperand1();
            while (tok2 && tok2->str() == "*" && !tok2->astOperand2())
                tok2 = tok2->astOperand1();
            return tok2 && tok2->variable() && !tok2->variable()->isClass() && !tok2->variable()->isStlType(); // Class or unknown type on LHS: Assume it is a stream
        }
        return true;
    }

    if (tok->isLiteral())
        return true;

    if (tok->isName()) {
        // TODO: check function calls, struct members, arrays, etc also
        if (!tok->variable())
            return false;
        if (tok->variable()->isStlType())
            return true;
        if (tok->variable()->isClass() || tok->variable()->isPointer() || tok->variable()->isReference()) // TODO: Properly handle pointers/references to classes in symbol database
            return false;

        return true;
    }

    return false;
}
Exemple #3
0
void CheckAutoVariables::returnReference()
{
    const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();

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

        const Token *tok = scope->function->tokenDef;

        // have we reached a function that returns a reference?
        if (tok->previous() && tok->previous()->str() == "&") {
            for (const Token *tok2 = scope->classStart->next(); tok2 && tok2 != scope->classEnd; tok2 = tok2->next()) {
                if (tok2->str() != "return")
                    continue;

                // return..
                if (Token::Match(tok2, "return %var% ;")) {
                    // is the returned variable a local variable?
                    if (isAutoVar(tok2->next())) {
                        const Variable *var1 = tok2->next()->variable();
                        // If reference variable is used, check what it references
                        if (Token::Match(var1->nameToken(), "%var% [=(]")) {
                            const Token *tok3 = var1->nameToken()->tokAt(2);
                            if (!Token::Match(tok3, "%var% [);.]"))
                                continue;

                            // Only report error if variable that is referenced is
                            // a auto variable
                            if (!isAutoVar(tok3))
                                continue;
                        }

                        // report error..
                        errorReturnReference(tok2);
                    }
                }

                // return reference to temporary..
                else if (Token::Match(tok2, "return %var% (") &&
                         Token::simpleMatch(tok2->linkAt(2), ") ;")) {
                    if (returnTemporary(tok2->next())) {
                        // report error..
                        errorReturnTempReference(tok2);
                    }
                }

                // Return reference to a literal or the result of a calculation
                else if (tok2->astOperand1() && (tok2->astOperand1()->isCalculation() || tok2->next()->isLiteral()) && astHasAutoResult(tok2->astOperand1())) {
                    errorReturnTempReference(tok2);
                }
            }
        }
    }
}