recursively check loop, return error token */
| 920 | |
| 921 | /** recursively check loop, return error token */ |
| 922 | const Token* CheckUninitVarImpl::checkLoopBodyRecursive(const Token *start, const Variable& var, const Alloc alloc, const std::string &membervar, bool &bailout, bool &alwaysReturns) const |
| 923 | { |
| 924 | assert(start->str() == "{"); |
| 925 | |
| 926 | const Token *errorToken = nullptr; |
| 927 | |
| 928 | const Token *const end = start->link(); |
| 929 | for (const Token *tok = start->next(); tok != end; tok = tok->next()) { |
| 930 | // skip sizeof / offsetof |
| 931 | if (isUnevaluated(tok)) { |
| 932 | tok = tok->linkAt(1); |
| 933 | continue; |
| 934 | } |
| 935 | |
| 936 | if (Token::Match(tok, "asm ( %str% ) ;")) { |
| 937 | bailout = true; |
| 938 | return nullptr; |
| 939 | } |
| 940 | |
| 941 | // for loop; skip third expression until loop body has been analyzed.. |
| 942 | if (tok->str() == ";" && Token::simpleMatch(tok->astParent(), ";") && Token::simpleMatch(tok->astParent()->astParent(), "(")) { |
| 943 | const Token *top = tok->astParent()->astParent(); |
| 944 | if (!Token::simpleMatch(top->previous(), "for (") || !Token::simpleMatch(top->link(), ") {")) |
| 945 | continue; |
| 946 | const Token *bodyStart = top->link()->next(); |
| 947 | const Token *errorToken1 = checkLoopBodyRecursive(bodyStart, var, alloc, membervar, bailout, alwaysReturns); |
| 948 | if (!errorToken) |
| 949 | errorToken = errorToken1; |
| 950 | bailout |= alwaysReturns; |
| 951 | if (bailout) |
| 952 | return nullptr; |
| 953 | } |
| 954 | // for loop; skip loop body if there is third expression |
| 955 | if (Token::simpleMatch(tok, ") {") && |
| 956 | Token::simpleMatch(tok->link()->previous(), "for (") && |
| 957 | Token::simpleMatch(tok->link()->astOperand2(), ";") && |
| 958 | Token::simpleMatch(tok->link()->astOperand2()->astOperand2(), ";")) { |
| 959 | tok = tok->linkAt(1); |
| 960 | } |
| 961 | |
| 962 | if (tok->str() == "{") { |
| 963 | // switch => bailout |
| 964 | if (tok->scope() && tok->scope()->type == ScopeType::eSwitch) { |
| 965 | bailout = true; |
| 966 | return nullptr; |
| 967 | } |
| 968 | |
| 969 | bool alwaysReturnsUnused = false; |
| 970 | const Token *errorToken1 = checkLoopBodyRecursive(tok, var, alloc, membervar, bailout, alwaysReturnsUnused); |
| 971 | tok = tok->link(); |
| 972 | if (Token::simpleMatch(tok, "} else {")) { |
| 973 | const Token *elseBody = tok->tokAt(2); |
| 974 | const Token *errorToken2 = checkLoopBodyRecursive(elseBody, var, alloc, membervar, bailout, alwaysReturnsUnused); |
| 975 | tok = elseBody->link(); |
| 976 | if (errorToken1 && errorToken2) |
| 977 | return errorToken1; |
| 978 | if (errorToken2) |
| 979 | errorToken = errorToken2; |
nothing calls this directly
no test coverage detected