Example #1
0
bool astIsIntegral(const Token *tok, bool unknown)
{
    // TODO: handle arrays
    if (tok->isNumber())
        return MathLib::isInt(tok->str());

    if (tok->isName()) {
        if (tok->variable())
            return tok->variable()->isIntegralType();

        return unknown;
    }
    if (tok->str() == "(") {
        // cast
        if (Token::Match(tok, "( const| float|double )"))
            return false;

        // Function call
        if (tok->previous()->function()) {
            if (Token::Match(tok->previous()->function()->retDef, "float|double"))
                return false;
            else if (Token::Match(tok->previous()->function()->retDef, "bool|char|short|int|long"))
                return true;
        }

        if (tok->strAt(-1) == "sizeof")
            return true;

        return unknown;
    }

    if (tok->astOperand2() && (tok->str() == "." || tok->str() == "::"))
        return astIsIntegral(tok->astOperand2(), unknown);

    if (tok->astOperand1() && tok->str() != "?")
        return astIsIntegral(tok->astOperand1(), unknown);

    return unknown;
}
Example #2
0
bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const std::set<std::string> &constFunctions)
{
    if (tok1 == nullptr && tok2 == nullptr)
        return true;
    if (tok1 == nullptr || tok2 == nullptr)
        return false;
    if (cpp) {
        if (tok1->str() == "." && tok1->astOperand1() && tok1->astOperand1()->str() == "this")
            tok1 = tok1->astOperand2();
        if (tok2->str() == "." && tok2->astOperand1() && tok2->astOperand1()->str() == "this")
            tok2 = tok2->astOperand2();
    }
    if (tok1->varId() != tok2->varId() || tok1->str() != tok2->str() || tok1->originalName() != tok2->originalName()) {
        if ((Token::Match(tok1,"<|>")   && Token::Match(tok2,"<|>")) ||
            (Token::Match(tok1,"<=|>=") && Token::Match(tok2,"<=|>="))) {
            return isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand2(), constFunctions) &&
                   isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand1(), constFunctions);
        }
        return false;
    }
    if (macro && (tok1->isExpandedMacro() || tok2->isExpandedMacro()))
        return false;
    if (tok1->isName() && tok1->next()->str() == "(" && tok1->str() != "sizeof") {
        if (!tok1->function() && !Token::Match(tok1->previous(), ".|::") && constFunctions.find(tok1->str()) == constFunctions.end() && !tok1->isAttributeConst() && !tok1->isAttributePure())
            return false;
        else if (tok1->function() && !tok1->function()->isConst() && !tok1->function()->isAttributeConst() && !tok1->function()->isAttributePure())
            return false;
    }
    // templates/casts
    if ((Token::Match(tok1, "%name% <") && tok1->next()->link()) ||
        (Token::Match(tok2, "%name% <") && tok2->next()->link())) {

        // non-const template function that is not a dynamic_cast => return false
        if (Token::simpleMatch(tok1->next()->link(), "> (") &&
            !(tok1->function() && tok1->function()->isConst()) &&
            tok1->str() != "dynamic_cast")
            return false;

        // some template/cast stuff.. check that the template arguments are same
        const Token *t1 = tok1->next();
        const Token *t2 = tok2->next();
        const Token *end1 = t1->link();
        const Token *end2 = t2->link();
        while (t1 && t2 && t1 != end1 && t2 != end2) {
            if (t1->str() != t2->str())
                return false;
            t1 = t1->next();
            t2 = t2->next();
        }
        if (t1 != end1 || t2 != end2)
            return false;
    }
    if (tok1->tokType() == Token::eIncDecOp || tok1->isAssignmentOp())
        return false;
    // bailout when we see ({..})
    if (tok1->str() == "{")
        return false;
    if (tok1->str() == "(" && tok1->previous() && !tok1->previous()->isName()) { // cast => assert that the casts are equal
        const Token *t1 = tok1->next();
        const Token *t2 = tok2->next();
        while (t1 && t2 && t1->str() == t2->str() && (t1->isName() || t1->str() == "*")) {
            t1 = t1->next();
            t2 = t2->next();
        }
        if (!t1 || !t2 || t1->str() != ")" || t2->str() != ")")
            return false;
    }
    bool noncommuative_equals =
        isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand1(), constFunctions);
    noncommuative_equals = noncommuative_equals &&
                           isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand2(), constFunctions);

    if (noncommuative_equals)
        return true;

    const bool commutative = tok1->astOperand1() && tok1->astOperand2() && Token::Match(tok1, "%or%|%oror%|+|*|&|&&|^|==|!=");
    bool commuative_equals = commutative &&
                             isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand1(), constFunctions);
    commuative_equals = commuative_equals &&
                        isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand2(), constFunctions);

    // in c++, "a"+b might be different to b+"a"
    if (cpp && commuative_equals && tok1->str() == "+" &&
        (tok1->astOperand1()->tokType() == Token::eString || tok1->astOperand2()->tokType() == Token::eString)) {
        const Token * const other = tok1->astOperand1()->tokType() != Token::eString ? tok1->astOperand1() : tok1->astOperand2();
        return other && astIsIntegral(other,false);
    }

    return commuative_equals;
}