Esempio n. 1
0
void CheckCondition::alwaysTrueFalse()
{
    if (!_settings->isEnabled("style"))
        return;

    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];
        for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
            if (!Token::Match(tok, "%comp%|!"))
                continue;
            if (tok->link()) // don't write false positives when templates are used
                continue;
            if (tok->values.size() != 1U)
                continue;
            if (tok->values.front().valueKind != ValueFlow::Value::Known)
                continue;

            if (tok->astParent() && Token::Match(tok->astParent()->previous(), "%name% ("))
                alwaysTrueFalseError(tok, tok->values.front().intvalue != 0);
        }
    }
}
void CheckCondition::alwaysTrueFalse()
{
    if (!_settings->isEnabled("style"))
        return;

    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];
        for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
            if (!Token::Match(tok, "%comp%|!"))
                continue;
            if (tok->link()) // don't write false positives when templates are used
                continue;
            if (tok->values.size() != 1U)
                continue;
            if (!tok->values.front().isKnown())
                continue;
            if (!tok->astParent() || !Token::Match(tok->astParent()->previous(), "%name% ("))
                continue;

            // Don't warn in assertions. Condition is often 'always true' by intention.
            // If platform,defines,etc cause 'always false' then that is not dangerous neither.
            const std::string &str = tok->astParent()->previous()->str();
            if (str.find("assert")!=std::string::npos || str.find("ASSERT")!=std::string::npos)
                continue;

            // Don't warn when there are expanded macros..
            bool isExpandedMacro = false;
            std::stack<const Token*> tokens;
            tokens.push(tok);
            while (!tokens.empty()) {
                const Token *tok2 = tokens.top();
                tokens.pop();
                if (!tok2)
                    continue;
                tokens.push(tok2->astOperand1());
                tokens.push(tok2->astOperand2());
                if (tok2->isExpandedMacro()) {
                    isExpandedMacro = true;
                    break;
                }
            }
            if (isExpandedMacro)
                continue;

            alwaysTrueFalseError(tok, tok->values.front().intvalue != 0);
        }
    }
}
Esempio n. 3
0
void CheckCondition::alwaysTrueFalse()
{
    if (!_settings->isEnabled("style"))
        return;

    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];
        for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {

            const bool constValCond = Token::Match(tok->tokAt(-2), "if|while ( %num%|%char% )") && !Token::Match(tok,"0|1"); // just one number or char inside if|while
            const bool constValExpr = Token::Match(tok, "%num%|%char%") && tok->astParent() && Token::Match(tok->astParent(),"&&|%oror%|?"); // just one number or char in boolean expression
            const bool compExpr = Token::Match(tok, "%comp%|!"); // a compare expression

            if (!(constValCond || constValExpr || compExpr))
                continue;
            if (tok->link()) // don't write false positives when templates are used
                continue;
            if (tok->values.size() != 1U)
                continue;
            if (!tok->values.front().isKnown())
                continue;

            // Don't warn in assertions. Condition is often 'always true' by intention.
            // If platform,defines,etc cause 'always false' then that is not dangerous neither.
            bool assertFound = false;
            for (const Token * tok2 = tok->astParent(); tok2 ; tok2 = tok2->astParent()) { // move backwards and try to find "assert"
                if (tok2->str() == "(" && tok2->astOperand2()) {
                    const std::string& str = tok2->previous()->str();
                    if ((str.find("assert")!=std::string::npos || str.find("ASSERT")!=std::string::npos))
                        assertFound = true;
                    break;
                }
            }
            if (assertFound)
                continue;

            // Don't warn when there are expanded macros..
            bool isExpandedMacro = false;
            std::stack<const Token*> tokens;
            tokens.push(tok);
            while (!tokens.empty()) {
                const Token *tok2 = tokens.top();
                tokens.pop();
                if (!tok2)
                    continue;
                tokens.push(tok2->astOperand1());
                tokens.push(tok2->astOperand2());
                if (tok2->isExpandedMacro()) {
                    isExpandedMacro = true;
                    break;
                }
            }
            if (isExpandedMacro)
                continue;

            alwaysTrueFalseError(tok, tok->values.front().intvalue != 0);
        }
    }
}