| 1174 | } |
| 1175 | |
| 1176 | void CheckUnusedVarImpl::checkFunctionVariableUsage() |
| 1177 | { |
| 1178 | if (!mSettings.severity.isEnabled(Severity::style) && !mSettings.checkLibrary && !mSettings.isPremiumEnabled("unusedVariable")) |
| 1179 | return; |
| 1180 | |
| 1181 | logChecker("CheckUnusedVar::checkFunctionVariableUsage"); // style |
| 1182 | |
| 1183 | // Parse all executing scopes.. |
| 1184 | const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 1185 | |
| 1186 | auto reportLibraryCfgError = [this](const Token* tok, const std::string& typeName) { |
| 1187 | if (mSettings.checkLibrary) { |
| 1188 | reportError(tok, |
| 1189 | Severity::information, |
| 1190 | "checkLibraryCheckType", |
| 1191 | "--check-library: Provide <type-checks><unusedvar> configuration for " + typeName); |
| 1192 | } |
| 1193 | }; |
| 1194 | |
| 1195 | // only check functions |
| 1196 | for (const Scope * scope : symbolDatabase->functionScopes) { |
| 1197 | // Bailout when there are lambdas or inline functions |
| 1198 | // TODO: Handle lambdas and inline functions properly |
| 1199 | const Token* lambdaOrInlineStart{}; |
| 1200 | const bool hasLambdaOrInline = scope->hasInlineOrLambdaFunction(&lambdaOrInlineStart); |
| 1201 | |
| 1202 | const Token *nextStructuredBindingTok = nullptr; |
| 1203 | std::vector<std::pair<const Token*, const Token*>> unusedStructuredBindingTokens; |
| 1204 | size_t structuredBindingTokCount = 0; |
| 1205 | std::set<const Variable*> diagUnreadVariable; // prevent duplicate warnings |
| 1206 | |
| 1207 | for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { |
| 1208 | if (nextStructuredBindingTok) { |
| 1209 | tok = nextStructuredBindingTok; |
| 1210 | } else { |
| 1211 | if (structuredBindingTokCount > 0 && structuredBindingTokCount == unusedStructuredBindingTokens.size()) { |
| 1212 | for (const auto &pair : unusedStructuredBindingTokens) { |
| 1213 | unreadVariableError(pair.first, pair.second->expressionString(), false); |
| 1214 | } |
| 1215 | } |
| 1216 | structuredBindingTokCount = 0; |
| 1217 | unusedStructuredBindingTokens.clear(); |
| 1218 | } |
| 1219 | nextStructuredBindingTok = nullptr; |
| 1220 | |
| 1221 | if (findLambdaEndToken(tok)) |
| 1222 | // todo: handle lambdas |
| 1223 | break; |
| 1224 | if (Token::simpleMatch(tok, "try {")) |
| 1225 | // todo: check try blocks |
| 1226 | tok = tok->linkAt(1); |
| 1227 | const Token *varDecl = nullptr; |
| 1228 | if (tok->variable() && tok->variable()->nameToken() == tok) { |
| 1229 | const Token * eq = tok->next(); |
| 1230 | if (isStructuredBindingVariable(tok->variable())) { |
| 1231 | structuredBindingTokCount++; |
| 1232 | while (!Token::simpleMatch(eq, "]")) { |
| 1233 | eq = eq->next(); |