| 2636 | } |
| 2637 | |
| 2638 | bool isVariableChanged(const Token *tok, int indirect, const Settings &settings, int depth) |
| 2639 | { |
| 2640 | if (!tok) |
| 2641 | return false; |
| 2642 | if (!tok->isMutableExpr()) |
| 2643 | return false; |
| 2644 | |
| 2645 | if (isConstVarExpression(tok)) |
| 2646 | return false; |
| 2647 | |
| 2648 | const Token *tok2 = tok; |
| 2649 | int derefs = 0; |
| 2650 | while ((tok2->astParent() && tok2->astParent()->isUnaryOp("*")) || |
| 2651 | (Token::simpleMatch(tok2->astParent(), ".") && !Token::Match(tok2->astParent()->astParent(), "[(,]")) || |
| 2652 | (tok2->astParent() && tok2->astParent()->isUnaryOp("&") && Token::simpleMatch(tok2->astParent()->astParent(), ".") && tok2->astParent()->astParent()->originalName()=="->") || |
| 2653 | (Token::simpleMatch(tok2->astParent(), "[") && tok2 == tok2->astParent()->astOperand1()) || |
| 2654 | (Token::simpleMatch(tok2->astParent(), "(") && tok2->astParent()->isCast())) { |
| 2655 | if (tok2->astParent() && (tok2->astParent()->isUnaryOp("*") || (astIsLHS(tok2) && tok2->astParent()->originalName() == "->" && !hasOverloadedMemberAccess(tok2)))) |
| 2656 | derefs++; |
| 2657 | if (derefs > indirect) |
| 2658 | break; |
| 2659 | if (tok2->astParent() && tok2->astParent()->isUnaryOp("&") && Token::simpleMatch(tok2->astParent()->astParent(), ".") && tok2->astParent()->astParent()->originalName()=="->") |
| 2660 | tok2 = tok2->astParent(); |
| 2661 | tok2 = tok2->astParent(); |
| 2662 | } |
| 2663 | |
| 2664 | if (tok2->astParent() && tok2->astParent()->isUnaryOp("&")) { |
| 2665 | const Token* parent = tok2->astParent(); |
| 2666 | while (parent->astParent() && parent->astParent()->isCast()) |
| 2667 | parent = parent->astParent(); |
| 2668 | if (parent->astParent() && parent->astParent()->isUnaryOp("*")) |
| 2669 | tok2 = parent->astParent(); |
| 2670 | } |
| 2671 | |
| 2672 | while ((Token::simpleMatch(tok2, ":") && Token::simpleMatch(tok2->astParent(), "?")) || |
| 2673 | (Token::simpleMatch(tok2->astParent(), ":") && Token::simpleMatch(tok2->astParent()->astParent(), "?"))) |
| 2674 | tok2 = tok2->astParent(); |
| 2675 | |
| 2676 | if (indirect == 0 && tok2->astParent() && tok2->astParent()->tokType() == Token::eIncDecOp) |
| 2677 | return true; |
| 2678 | |
| 2679 | auto skipRedundantPtrOp = [](const Token* tok, const Token* parent) { |
| 2680 | const Token* gparent = parent ? parent->astParent() : nullptr; |
| 2681 | while (parent && gparent && ((parent->isUnaryOp("*") && gparent->isUnaryOp("&")) || (parent->isUnaryOp("&") && gparent->isUnaryOp("*")))) { |
| 2682 | tok = gparent; |
| 2683 | parent = gparent->astParent(); |
| 2684 | if (parent) |
| 2685 | gparent = parent->astParent(); |
| 2686 | } |
| 2687 | return tok; |
| 2688 | }; |
| 2689 | tok2 = skipRedundantPtrOp(tok2, tok2->astParent()); |
| 2690 | |
| 2691 | if (tok2->astParent() && tok2->astParent()->isAssignmentOp()) { |
| 2692 | if (astIsLHS(tok2)) |
| 2693 | return true; |
| 2694 | // Check if assigning to a non-const lvalue |
| 2695 | const Variable * var = getLHSVariable(tok2->astParent()); |