| 1217 | //--------------------------------------------------------------------------- |
| 1218 | |
| 1219 | void CheckClassImpl::initializationListUsage() |
| 1220 | { |
| 1221 | if (!mSettings.severity.isEnabled(Severity::performance)) |
| 1222 | return; |
| 1223 | |
| 1224 | logChecker("CheckClass::initializationListUsage"); // performance |
| 1225 | |
| 1226 | for (const Scope *scope : mSymbolDatabase->functionScopes) { |
| 1227 | // Check every constructor |
| 1228 | if (!scope->function || !scope->function->isConstructor()) |
| 1229 | continue; |
| 1230 | |
| 1231 | // Do not warn when a delegate constructor is called |
| 1232 | if (const Token *initList = scope->function->constructorMemberInitialization()) { |
| 1233 | if (Token::Match(initList, ": %name% {|(") && initList->strAt(1) == scope->className) |
| 1234 | continue; |
| 1235 | } |
| 1236 | |
| 1237 | const Scope* owner = scope->functionOf; |
| 1238 | for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { |
| 1239 | if (Token::Match(tok, "%name% (")) // Assignments might depend on this function call or if/for/while/switch statement from now on. |
| 1240 | break; |
| 1241 | if (Token::Match(tok, "try|do {")) |
| 1242 | break; |
| 1243 | if (!Token::Match(tok, "%var% =") || tok->strAt(-1) == "*" || tok->strAt(-1) == ".") |
| 1244 | continue; |
| 1245 | |
| 1246 | const Variable* var = tok->variable(); |
| 1247 | if (!var || var->scope() != owner || var->isStatic()) |
| 1248 | continue; |
| 1249 | if (var->isPointer() || var->isReference() || var->isEnumType()) |
| 1250 | continue; |
| 1251 | if (!WRONG_DATA(!var->valueType(), tok) && var->valueType()->type > ValueType::Type::ITERATOR) |
| 1252 | continue; |
| 1253 | |
| 1254 | // bailout: multi line lambda in rhs => do not warn |
| 1255 | if (findLambdaEndToken(tok->tokAt(2)) && tok->tokAt(2)->findExpressionStartEndTokens().second->linenr() > tok->tokAt(2)->linenr()) |
| 1256 | continue; |
| 1257 | |
| 1258 | // Access local var member in rhs => do not warn |
| 1259 | bool localmember = false; |
| 1260 | visitAstNodes(tok->next()->astOperand2(), |
| 1261 | [&](const Token *rhs) { |
| 1262 | if (rhs->str() == "." && rhs->astOperand1() && rhs->astOperand1()->variable() && rhs->astOperand1()->variable()->isLocal()) |
| 1263 | localmember = true; |
| 1264 | return ChildrenToVisit::op1_and_op2; |
| 1265 | }); |
| 1266 | if (localmember) |
| 1267 | continue; |
| 1268 | |
| 1269 | bool allowed = true; |
| 1270 | visitAstNodes(tok->next()->astOperand2(), |
| 1271 | [&](const Token *tok2) { |
| 1272 | const Variable* var2 = tok2->variable(); |
| 1273 | if (var2) { |
| 1274 | if (var2->scope() == owner && tok2->strAt(-1)!=".") { // Is there a dependency between two member variables? |
| 1275 | allowed = false; |
| 1276 | return ChildrenToVisit::done; |