| 1838 | } |
| 1839 | |
| 1840 | bool isOppositeCond(bool isNot, const Token * const cond1, const Token * const cond2, const Settings& settings, bool pure, bool followVar, ErrorPath* errors) |
| 1841 | { |
| 1842 | if (!cond1 || !cond2) |
| 1843 | return false; |
| 1844 | |
| 1845 | if (isSameExpression(true, cond1, cond2, settings, pure, followVar, errors)) |
| 1846 | return false; |
| 1847 | |
| 1848 | if (!isNot && cond1->str() == "&&" && cond2->str() == "&&") { |
| 1849 | for (const Token* tok1: { |
| 1850 | cond1->astOperand1(), cond1->astOperand2() |
| 1851 | }) { |
| 1852 | for (const Token* tok2: { |
| 1853 | cond2->astOperand1(), cond2->astOperand2() |
| 1854 | }) { |
| 1855 | if (isSameExpression(true, tok1, tok2, settings, pure, followVar, errors)) { |
| 1856 | if (isOppositeCond(isNot, tok1->astSibling(), tok2->astSibling(), settings, pure, followVar, errors)) |
| 1857 | return true; |
| 1858 | } |
| 1859 | } |
| 1860 | } |
| 1861 | } |
| 1862 | |
| 1863 | if (cond1->str() != cond2->str() && (cond1->str() == "||" || cond2->str() == "||")) { |
| 1864 | const Token* orCond = nullptr; |
| 1865 | const Token* otherCond = nullptr; |
| 1866 | if (cond1->str() == "||") { |
| 1867 | orCond = cond1; |
| 1868 | otherCond = cond2; |
| 1869 | } |
| 1870 | if (cond2->str() == "||") { |
| 1871 | orCond = cond2; |
| 1872 | otherCond = cond1; |
| 1873 | } |
| 1874 | return isOppositeCond(isNot, orCond->astOperand1(), otherCond, settings, pure, followVar, errors) && |
| 1875 | isOppositeCond(isNot, orCond->astOperand2(), otherCond, settings, pure, followVar, errors); |
| 1876 | } |
| 1877 | |
| 1878 | if (cond1->str() == "!") { |
| 1879 | if (cond2->str() == "!=") { |
| 1880 | if (cond2->astOperand1() && cond2->astOperand1()->str() == "0") |
| 1881 | return isSameExpression(true, cond1->astOperand1(), cond2->astOperand2(), settings, pure, followVar, errors); |
| 1882 | if (cond2->astOperand2() && cond2->astOperand2()->str() == "0") |
| 1883 | return isSameExpression(true, cond1->astOperand1(), cond2->astOperand1(), settings, pure, followVar, errors); |
| 1884 | } |
| 1885 | if (!isUsedAsBool(cond2, settings)) |
| 1886 | return false; |
| 1887 | return isSameExpression(true, cond1->astOperand1(), cond2, settings, pure, followVar, errors); |
| 1888 | } |
| 1889 | |
| 1890 | if (cond2->str() == "!") |
| 1891 | return isOppositeCond(isNot, cond2, cond1, settings, pure, followVar, errors); |
| 1892 | |
| 1893 | if (!isNot) { |
| 1894 | if (cond1->str() == "==" && cond2->str() == "==") { |
| 1895 | if (isSameExpression(true, cond1->astOperand1(), cond2->astOperand1(), settings, pure, followVar, errors)) |
| 1896 | return isDifferentKnownValues(cond1->astOperand2(), cond2->astOperand2()); |
| 1897 | if (isSameExpression(true, cond1->astOperand2(), cond2->astOperand2(), settings, pure, followVar, errors)) |
no test coverage detected