예제 #1
0
void CheckCondition::oppositeInnerCondition()
{
    if (!_settings->isEnabled("warning"))
        return;

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

    for (std::list<Scope>::const_iterator scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
        if (scope->type != Scope::eIf)
            continue;

        if (!Token::simpleMatch(scope->classDef->linkAt(1), ") {"))
            continue;

        bool nonlocal = false; // nonlocal variable used in condition
        std::set<unsigned int> vars; // variables used in condition
        for (const Token *cond = scope->classDef->linkAt(1); cond != scope->classDef; cond = cond->previous()) {
            if (cond->varId()) {
                vars.insert(cond->varId());
                const Variable *var = cond->variable();
                nonlocal |= (var && (!var->isLocal() || var->isStatic()) && !var->isArgument());
                // TODO: if var is pointer check what it points at
                nonlocal |= (var && (var->isPointer() || var->isReference()));
            } else if (cond->isName()) {
                // varid is 0. this is possibly a nonlocal variable..
                nonlocal |= Token::Match(cond->astParent(), "%cop%|(");
            }
        }

        // parse until inner condition is reached..
        const Token *ifToken = nullptr;
        for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
            if (Token::simpleMatch(tok, "if (")) {
                ifToken = tok;
                break;
            }
            if (Token::Match(tok, "%type% (") && nonlocal) // function call -> bailout if there are nonlocal variables
                break;
            else if ((tok->varId() && vars.find(tok->varId()) != vars.end()) ||
                     (!tok->varId() && nonlocal)) {
                if (Token::Match(tok, "%name% ++|--|="))
                    break;
                if (Token::Match(tok, "%name% [")) {
                    const Token *tok2 = tok->linkAt(1);
                    while (Token::simpleMatch(tok2, "] ["))
                        tok2 = tok2->linkAt(1);
                    if (Token::simpleMatch(tok2, "] ="))
                        break;
                }
                if (Token::Match(tok->previous(), "++|--|& %name%"))
                    break;
                if (tok->variable() &&
                    Token::Match(tok, "%name% . %name% (") &&
                    !tok->variable()->isConst()) {
                    const Function* function = tok->tokAt(2)->function();
                    if (!function || !function->isConst())
                        break;
                }
                if (Token::Match(tok->previous(), "[(,] %name% [,)]")) {
                    // is variable unchanged? default is false..
                    bool unchanged = false;

                    // locate start parentheses in function call..
                    unsigned int argumentNumber = 0;
                    const Token *start = tok->previous();
                    while (start && start->str() == ",") {
                        start = start->astParent();
                        ++argumentNumber;
                    }

                    start = start ? start->previous() : nullptr;
                    if (start && start->function()) {
                        const Variable *arg = start->function()->getArgumentVar(argumentNumber);
                        if (arg && !arg->isPointer() && !arg->isReference())
                            unchanged = true;
                    }

                    if (!unchanged)
                        break;
                }
            }
        }
        if (!ifToken)
            continue;

        // Condition..
        const Token *cond1 = scope->classDef->next()->astOperand2();
        const Token *cond2 = ifToken->next()->astOperand2();

        if (isOppositeCond(false, cond1, cond2, _settings->library.functionpure))
            oppositeInnerConditionError(scope->classDef, cond2);
    }
}
예제 #2
0
void CheckCondition::oppositeInnerCondition()
{
    if (!_settings->isEnabled(Settings::WARNING))
        return;

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

    for (std::list<Scope>::const_iterator scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
        if (scope->type != Scope::eIf)
            continue;

        if (!Token::simpleMatch(scope->classDef->linkAt(1), ") {"))
            continue;

        bool nonlocal = false; // nonlocal variable used in condition
        std::set<unsigned int> vars; // variables used in condition
        for (const Token *cond = scope->classDef->linkAt(1); cond != scope->classDef; cond = cond->previous()) {
            if (cond->varId()) {
                vars.insert(cond->varId());
                const Variable *var = cond->variable();
                nonlocal |= (var && (!var->isLocal() || var->isStatic()) && !var->isArgument());
                // TODO: if var is pointer check what it points at
                nonlocal |= (var && (var->isPointer() || var->isReference()));
            } else if (!nonlocal && cond->isName()) {
                // varid is 0. this is possibly a nonlocal variable..
                nonlocal = Token::Match(cond->astParent(), "%cop%|(");
            }
        }

        // parse until inner condition is reached..
        const Token *ifToken = nullptr;
        for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
            if (Token::simpleMatch(tok, "if (")) {
                ifToken = tok;
                break;
            }
            if (Token::Match(tok, "%type% (") && nonlocal) // function call -> bailout if there are nonlocal variables
                break;
            // bailout if loop is seen.
            // TODO: handle loops.
            if (Token::Match(tok, "for|while|do"))
                break;
            if ((tok->varId() && vars.find(tok->varId()) != vars.end()) ||
                (!tok->varId() && nonlocal)) {
                if (Token::Match(tok, "%name% %assign%|++|--"))
                    break;
                if (Token::Match(tok, "%name% [")) {
                    const Token *tok2 = tok->linkAt(1);
                    while (Token::simpleMatch(tok2, "] ["))
                        tok2 = tok2->linkAt(1);
                    if (Token::Match(tok2, "] %assign%|++|--"))
                        break;
                }
                if (Token::Match(tok->previous(), "++|--|& %name%"))
                    break;
                if (tok->variable() &&
                    !tok->variable()->isConst() &&
                    Token::Match(tok, "%name% . %name% (")) {
                    const Function* function = tok->tokAt(2)->function();
                    if (!function || !function->isConst())
                        break;
                }
                if (Token::Match(tok->previous(), "[(,] %name% [,)]") && isParameterChanged(tok))
                    break;
            }
        }
        if (!ifToken)
            continue;

        // Condition..
        const Token *cond1 = scope->classDef->next()->astOperand2();
        const Token *cond2 = ifToken->next()->astOperand2();

        if (isOppositeCond(false, _tokenizer->isCPP(), cond1, cond2, _settings->library, true))
            oppositeInnerConditionError(scope->classDef, cond2);
    }
}