| 1641 | }; |
| 1642 | using ExprIdMap = std::map<ExprIdKey, nonneg int>; |
| 1643 | void setParentExprId(Token* tok, ExprIdMap& exprIdMap, nonneg int &id) { |
| 1644 | for (;;) { |
| 1645 | if (!tok->astParent() || tok->astParent()->isControlFlowKeyword()) |
| 1646 | break; |
| 1647 | const Token* op1 = tok->astParent()->astOperand1(); |
| 1648 | if (op1 && op1->exprId() == 0 && !Token::Match(op1, "[{[]")) |
| 1649 | break; |
| 1650 | const Token* op2 = tok->astParent()->astOperand2(); |
| 1651 | if (op2 && op2->exprId() == 0 && |
| 1652 | !((tok->astParent()->astParent() && tok->astParent()->isAssignmentOp() && tok->astParent()->astParent()->isAssignmentOp()) || |
| 1653 | isLambdaCaptureList(op2) || |
| 1654 | (op2->str() == "(" && isLambdaCaptureList(op2->astOperand1())) || |
| 1655 | Token::simpleMatch(op2, "{ }") || |
| 1656 | (Token::simpleMatch(tok->astParent(), "[") && op2->str() == "{"))) |
| 1657 | break; |
| 1658 | |
| 1659 | if (tok->astParent()->isExpandedMacro() || Token::Match(tok->astParent(), "++|--")) { |
| 1660 | tok->astParent()->exprId(id); |
| 1661 | ++id; |
| 1662 | tok = tok->astParent(); |
| 1663 | continue; |
| 1664 | } |
| 1665 | |
| 1666 | ExprIdKey key; |
| 1667 | key.parentOp = tok->astParent()->str(); |
| 1668 | key.operand1 = getExprIdForOperand(op1); |
| 1669 | key.operand2 = getExprIdForOperand(op2); |
| 1670 | |
| 1671 | if (tok->astParent()->isCast() && tok->astParent()->str() == "(") { |
| 1672 | const Token* typeStartToken; |
| 1673 | const Token* typeEndToken; |
| 1674 | if (tok->astParent()->astOperand2()) { |
| 1675 | typeStartToken = tok->astParent()->astOperand1(); |
| 1676 | typeEndToken = tok; |
| 1677 | } else { |
| 1678 | typeStartToken = tok->astParent()->next(); |
| 1679 | typeEndToken = tok->astParent()->link(); |
| 1680 | } |
| 1681 | std::string type; |
| 1682 | for (const Token* t = typeStartToken; precedes(t, typeEndToken); t = t->next()) { |
| 1683 | type += " " + t->str(); |
| 1684 | } |
| 1685 | key.parentOp += type; |
| 1686 | } |
| 1687 | |
| 1688 | if (key.operand1 > key.operand2 && key.operand2 && |
| 1689 | Token::Match(tok->astParent(), "%or%|%oror%|+|*|&|&&|^|==|!=")) { |
| 1690 | // In C++ the order of operands of + might matter |
| 1691 | if (!tok->isCpp() || |
| 1692 | key.parentOp != "+" || |
| 1693 | !tok->astParent()->valueType() || |
| 1694 | tok->astParent()->valueType()->isIntegral() || |
| 1695 | tok->astParent()->valueType()->isFloat() || |
| 1696 | tok->astParent()->valueType()->pointer > 0) |
| 1697 | std::swap(key.operand1, key.operand2); |
| 1698 | } |
| 1699 | |
| 1700 | const auto it = exprIdMap.find(key); |
no test coverage detected