| 200 | //--------------------------------------------------------------------------- |
| 201 | |
| 202 | void CheckClassImpl::constructors() |
| 203 | { |
| 204 | const bool printStyle = mSettings.severity.isEnabled(Severity::style); |
| 205 | const bool printWarnings = mSettings.severity.isEnabled(Severity::warning); |
| 206 | if (!printStyle && !printWarnings && !mSettings.isPremiumEnabled("uninitMemberVar")) |
| 207 | return; |
| 208 | |
| 209 | logChecker("CheckClass::checkConstructors"); // style,warning |
| 210 | |
| 211 | const bool printInconclusive = mSettings.certainty.isEnabled(Certainty::inconclusive); |
| 212 | for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { |
| 213 | if (mSettings.hasLib("vcl") && isVclTypeInit(scope->definedType)) |
| 214 | continue; |
| 215 | |
| 216 | const bool unusedTemplate = Token::simpleMatch(scope->classDef->previous(), ">"); |
| 217 | |
| 218 | const bool usedInUnion = std::any_of(mSymbolDatabase->scopeList.cbegin(), mSymbolDatabase->scopeList.cend(), [&](const Scope& unionScope) { |
| 219 | if (unionScope.type != ScopeType::eUnion) |
| 220 | return false; |
| 221 | return std::any_of(unionScope.varlist.cbegin(), unionScope.varlist.cend(), [&](const Variable& var) { |
| 222 | return var.type() && var.type()->classScope == scope; |
| 223 | }); |
| 224 | }); |
| 225 | |
| 226 | // There are no constructors. |
| 227 | std::set<const Variable*> diagVars; |
| 228 | if (scope->numConstructors == 0 && printStyle && !usedInUnion) { |
| 229 | // If there is a private variable, there should be a constructor.. |
| 230 | int needInit = 0, haveInit = 0; |
| 231 | std::vector<const Variable*> uninitVars; |
| 232 | for (const Variable &var : scope->varlist) { |
| 233 | if (var.isPrivate() && !var.isStatic() && |
| 234 | (!var.isClass() || (var.type() && var.type()->needInitialization == Type::NeedInitialization::True))) { |
| 235 | ++needInit; |
| 236 | if (!var.isInit() && !var.hasDefault() && var.nameToken()->scope() == scope) // don't warn for anonymous union members |
| 237 | uninitVars.emplace_back(&var); |
| 238 | else |
| 239 | ++haveInit; |
| 240 | } |
| 241 | } |
| 242 | if (needInit > haveInit) { |
| 243 | if (haveInit == 0) |
| 244 | noConstructorError(scope->classDef, scope->className, scope->classDef->str() == "struct"); |
| 245 | else |
| 246 | for (const Variable* uv : uninitVars) { |
| 247 | uninitVarError(uv->typeStartToken(), uv->scope()->className, uv->name()); |
| 248 | diagVars.emplace(uv); |
| 249 | } |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | if (!printWarnings) |
| 254 | continue; |
| 255 | |
| 256 | std::vector<Usage> usageList = createUsageList(scope); |
| 257 | |
| 258 | for (const Function &func : scope->functionList) { |
| 259 | if (!(func.isConstructor() && (func.hasBody() || (func.isDefault() && func.type == FunctionType::eConstructor))) && |