| 1595 | } |
| 1596 | |
| 1597 | bool isSameExpression(bool macro, const Token *tok1, const Token *tok2, const Settings& settings, bool pure, bool followVar, ErrorPath* errors) |
| 1598 | { |
| 1599 | if (tok1 == tok2) |
| 1600 | return true; |
| 1601 | if (tok1 == nullptr || tok2 == nullptr) |
| 1602 | return false; |
| 1603 | // tokens needs to be from the same TokenList so no need check standard on both of them |
| 1604 | if (tok1->isCpp()) { |
| 1605 | if (tok1->str() == "." && tok1->astOperand1() && tok1->astOperand1()->str() == "this") |
| 1606 | tok1 = tok1->astOperand2(); |
| 1607 | if (tok2->str() == "." && tok2->astOperand1() && tok2->astOperand1()->str() == "this") |
| 1608 | tok2 = tok2->astOperand2(); |
| 1609 | } |
| 1610 | // Skip double not |
| 1611 | if (Token::simpleMatch(tok1, "!") && Token::simpleMatch(tok1->astOperand1(), "!") && !Token::simpleMatch(tok1->astParent(), "=") && astIsBoolLike(tok2, settings)) { |
| 1612 | return isSameExpression(macro, tok1->astOperand1()->astOperand1(), tok2, settings, pure, followVar, errors); |
| 1613 | } |
| 1614 | if (Token::simpleMatch(tok2, "!") && Token::simpleMatch(tok2->astOperand1(), "!") && !Token::simpleMatch(tok2->astParent(), "=") && astIsBoolLike(tok1, settings)) { |
| 1615 | return isSameExpression(macro, tok1, tok2->astOperand1()->astOperand1(), settings, pure, followVar, errors); |
| 1616 | } |
| 1617 | const bool tok_str_eq = tok1->str() == tok2->str(); |
| 1618 | if (!tok_str_eq && isDifferentKnownValues(tok1, tok2)) |
| 1619 | return false; |
| 1620 | |
| 1621 | const Token *followTok1 = tok1, *followTok2 = tok2; |
| 1622 | while (Token::simpleMatch(followTok1, "::")) |
| 1623 | followTok1 = followTok1->astOperand2() ? followTok1->astOperand2() : followTok1->astOperand1(); |
| 1624 | if (!followTok1) |
| 1625 | followTok1 = tok1; // TODO: remove after #14235 has been fixed |
| 1626 | while (Token::simpleMatch(followTok2, "::")) |
| 1627 | followTok2 = followTok2->astOperand2() ? followTok2->astOperand2() : followTok2->astOperand1(); |
| 1628 | if (!followTok2) |
| 1629 | followTok2 = tok2; |
| 1630 | if (isSameConstantValue(macro, followTok1, followTok2)) |
| 1631 | return true; |
| 1632 | |
| 1633 | // Follow variable |
| 1634 | if (followVar && !tok_str_eq && (followTok1->varId() || followTok2->varId() || followTok1->enumerator() || followTok2->enumerator())) { |
| 1635 | const Token * varTok1 = followVariableExpression(settings, followTok1, followTok2); |
| 1636 | if ((varTok1->str() == followTok2->str()) || isSameConstantValue(macro, varTok1, followTok2)) { |
| 1637 | followVariableExpressionError(followTok1, varTok1, errors); |
| 1638 | return isSameExpression(macro, varTok1, followTok2, settings, true, followVar, errors); |
| 1639 | } |
| 1640 | const Token * varTok2 = followVariableExpression(settings, followTok2, followTok1); |
| 1641 | if ((followTok1->str() == varTok2->str()) || isSameConstantValue(macro, followTok1, varTok2)) { |
| 1642 | followVariableExpressionError(followTok2, varTok2, errors); |
| 1643 | return isSameExpression(macro, followTok1, varTok2, settings, true, followVar, errors); |
| 1644 | } |
| 1645 | if ((varTok1->str() == varTok2->str()) || isSameConstantValue(macro, varTok1, varTok2)) { |
| 1646 | followVariableExpressionError(tok1, varTok1, errors); |
| 1647 | followVariableExpressionError(tok2, varTok2, errors); |
| 1648 | return isSameExpression(macro, varTok1, varTok2, settings, true, followVar, errors); |
| 1649 | } |
| 1650 | } |
| 1651 | // Follow references |
| 1652 | if (!tok_str_eq) { |
| 1653 | const Token* refTok1 = followReferences(tok1, errors); |
| 1654 | const Token* refTok2 = followReferences(tok2, errors); |