| 2922 | template<class F, |
| 2923 | REQUIRES("F must be a function that returns a Token class", |
| 2924 | std::is_convertible<decltype(std::declval<F>()()), const Token*> )> |
| 2925 | static bool isExpressionChangedAt(const F& getExprTok, |
| 2926 | const Token* tok, |
| 2927 | int indirect, |
| 2928 | const nonneg int exprid, |
| 2929 | bool globalvar, |
| 2930 | const Settings& settings, |
| 2931 | int depth) |
| 2932 | { |
| 2933 | if (depth < 0) |
| 2934 | return true; |
| 2935 | if (!tok) |
| 2936 | return false; |
| 2937 | if (!tok->isMutableExpr()) |
| 2938 | return false; |
| 2939 | if (tok->exprId() != exprid || (!tok->varId() && !tok->isName())) { |
| 2940 | if (globalvar && Token::Match(tok, "%name% (") && |
| 2941 | (!(tok->function() && (tok->function()->isAttributePure() || tok->function()->isAttributeConst())))) { |
| 2942 | if (!Token::simpleMatch(tok->astParent(), ".")) |
| 2943 | return true; |
| 2944 | const auto yield = astContainerYield(tok->astParent()->astOperand1(), settings.library); |
| 2945 | if (yield != Library::Container::Yield::SIZE && yield != Library::Container::Yield::EMPTY && |
| 2946 | yield != Library::Container::Yield::BUFFER && yield != Library::Container::Yield::BUFFER_NT) |
| 2947 | // TODO: Is global variable really changed by function call? |
| 2948 | return true; |
| 2949 | } |
| 2950 | nonneg int i = 1; |
| 2951 | bool aliased = false; |
| 2952 | // If we can't find the expression then assume it is an alias |
| 2953 | auto expr = getExprTok(); |
| 2954 | if (!expr && !(tok->valueType() && tok->valueType()->pointer == 0 && tok->valueType()->reference == Reference::None)) |
| 2955 | aliased = true; |
| 2956 | if (!aliased && expr && expr->varId() && tok->isCast() && tok->valueType() && tok->valueType()->reference != Reference::None && |
| 2957 | Token::Match(tok->astOperand2() ? tok->astOperand2() : tok->astOperand1(), "%varid%", expr->varId())) |
| 2958 | aliased = true; |
| 2959 | if (!aliased) |
| 2960 | aliased = isAliasOf(tok, expr, &i); |
| 2961 | if (!aliased) |
| 2962 | return false; |
| 2963 | i += indirect; |
| 2964 | if (tok->valueType() && tok->valueType()->pointer) |
| 2965 | i = std::min(i, tok->valueType()->pointer); |
| 2966 | if (isVariableChanged(tok, i, settings, depth)) |
| 2967 | return true; |
| 2968 | // TODO: Try to traverse the lambda function |
| 2969 | if (Token::Match(tok, "%var% (")) |
| 2970 | return true; |
| 2971 | return false; |
| 2972 | } |
| 2973 | return (isVariableChanged(tok, indirect, settings, depth)); |
| 2974 | } |
| 2975 | |
| 2976 | bool isExpressionChangedAt(const Token* expr, |
| 2977 | const Token* tok, |
no test coverage detected