| 954 | } |
| 955 | |
| 956 | bool extractForLoopValues(const Token *forToken, |
| 957 | nonneg int &varid, |
| 958 | bool &knownInitValue, |
| 959 | MathLib::bigint &initValue, |
| 960 | bool &partialCond, |
| 961 | MathLib::bigint &stepValue, |
| 962 | MathLib::bigint &lastValue) |
| 963 | { |
| 964 | if (!Token::simpleMatch(forToken, "for (") || !Token::simpleMatch(forToken->next()->astOperand2(), ";")) |
| 965 | return false; |
| 966 | const Token *initExpr = forToken->next()->astOperand2()->astOperand1(); |
| 967 | const Token *condExpr = forToken->next()->astOperand2()->astOperand2()->astOperand1(); |
| 968 | const Token *incExpr = forToken->next()->astOperand2()->astOperand2()->astOperand2(); |
| 969 | if (!initExpr || !initExpr->isBinaryOp() || initExpr->str() != "=" || !Token::Match(initExpr->astOperand1(), "%var%")) |
| 970 | return false; |
| 971 | std::vector<MathLib::bigint> minInitValue = |
| 972 | getMinValue(makeIntegralInferModel(), initExpr->astOperand2()->values()); |
| 973 | if (minInitValue.empty()) { |
| 974 | const ValueFlow::Value* v = initExpr->astOperand2()->getMinValue(true); |
| 975 | if (v) |
| 976 | minInitValue.push_back(v->intvalue); |
| 977 | } |
| 978 | if (minInitValue.empty()) |
| 979 | return false; |
| 980 | varid = initExpr->astOperand1()->varId(); |
| 981 | knownInitValue = initExpr->astOperand2()->hasKnownIntValue(); |
| 982 | initValue = minInitValue.front(); |
| 983 | partialCond = Token::Match(condExpr, "%oror%|&&"); |
| 984 | visitAstNodes(condExpr, [varid, &condExpr](const Token *tok) { |
| 985 | if (Token::Match(tok, "%oror%|&&")) |
| 986 | return ChildrenToVisit::op1_and_op2; |
| 987 | if (Token::Match(tok, "<|<=") && tok->isBinaryOp() && tok->astOperand1()->varId() == varid && tok->astOperand2()->hasKnownIntValue()) { |
| 988 | if (Token::Match(condExpr, "%oror%|&&") || tok->astOperand2()->getKnownIntValue() < condExpr->astOperand2()->getKnownIntValue()) |
| 989 | condExpr = tok; |
| 990 | } |
| 991 | return ChildrenToVisit::none; |
| 992 | }); |
| 993 | if (!Token::Match(condExpr, "<|<=") || !condExpr->isBinaryOp() || condExpr->astOperand1()->varId() != varid || !condExpr->astOperand2()->hasKnownIntValue()) |
| 994 | return false; |
| 995 | if (!incExpr || !incExpr->isUnaryOp("++") || incExpr->astOperand1()->varId() != varid) |
| 996 | return false; |
| 997 | stepValue = 1; |
| 998 | if (condExpr->str() == "<") |
| 999 | lastValue = condExpr->astOperand2()->getKnownIntValue() - 1; |
| 1000 | else |
| 1001 | lastValue = condExpr->astOperand2()->getKnownIntValue(); |
| 1002 | return true; |
| 1003 | } |
| 1004 | |
| 1005 | |
| 1006 | static const Token * getVariableInitExpression(const Variable * var) |
no test coverage detected