| 1119 | } |
| 1120 | |
| 1121 | void CheckStlImpl::invalidContainer() |
| 1122 | { |
| 1123 | logChecker("CheckStl::invalidContainer"); |
| 1124 | const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 1125 | InvalidContainerAnalyzer analyzer; |
| 1126 | analyzer.analyze(symbolDatabase); |
| 1127 | for (const Scope * scope : symbolDatabase->functionScopes) { |
| 1128 | for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { |
| 1129 | if (const Token* contTok = getLoopContainer(tok)) { |
| 1130 | const Token* blockStart = tok->linkAt(1)->next(); |
| 1131 | const Token* blockEnd = blockStart->link(); |
| 1132 | if (contTok->exprId() == 0) |
| 1133 | continue; |
| 1134 | if (!astIsContainer(contTok)) |
| 1135 | continue; |
| 1136 | for (const Token* tok2 = blockStart; tok2 != blockEnd; tok2 = tok2->next()) { |
| 1137 | bool bail = false; |
| 1138 | for (const InvalidContainerAnalyzer::Info::Reference& r : analyzer.invalidatesContainer(tok2)) { |
| 1139 | if (!astIsContainer(r.tok)) |
| 1140 | continue; |
| 1141 | if (r.tok->exprId() != contTok->exprId()) |
| 1142 | continue; |
| 1143 | const Scope* s = tok2->scope(); |
| 1144 | if (!s) |
| 1145 | continue; |
| 1146 | if (isReturnScope(s->bodyEnd, mSettings.library)) |
| 1147 | continue; |
| 1148 | invalidContainerLoopError(r.ftok, tok, r.errorPath); |
| 1149 | bail = true; |
| 1150 | break; |
| 1151 | } |
| 1152 | if (bail) |
| 1153 | break; |
| 1154 | } |
| 1155 | } else { |
| 1156 | for (const InvalidContainerAnalyzer::Info::Reference& r : analyzer.invalidatesContainer(tok)) { |
| 1157 | if (!astIsContainer(r.tok)) |
| 1158 | continue; |
| 1159 | std::set<nonneg int> skipVarIds; |
| 1160 | // Skip if the variable is assigned to |
| 1161 | const Token* assignExpr = tok; |
| 1162 | while (assignExpr->astParent()) { |
| 1163 | const bool isRHS = astIsRHS(assignExpr); |
| 1164 | assignExpr = assignExpr->astParent(); |
| 1165 | if (Token::Match(assignExpr, "%assign%")) { |
| 1166 | if (!isRHS) |
| 1167 | assignExpr = nullptr; |
| 1168 | break; |
| 1169 | } |
| 1170 | } |
| 1171 | if (Token::Match(assignExpr, "%assign%") && Token::Match(assignExpr->astOperand1(), "%var%")) |
| 1172 | skipVarIds.insert(assignExpr->astOperand1()->varId()); |
| 1173 | const Token* endToken = endOfExpression(tok); |
| 1174 | const ValueFlow::Value* v = nullptr; |
| 1175 | ErrorPath errorPath; |
| 1176 | PathAnalysis::Info info = |
| 1177 | PathAnalysis{endToken}.forwardFind([&](const PathAnalysis::Info& info) { |
| 1178 | if (!info.tok->variable()) |
no test coverage detected