| 386 | } |
| 387 | |
| 388 | void CheckClassImpl::checkExplicitConstructors() |
| 389 | { |
| 390 | if (!mSettings.severity.isEnabled(Severity::style) && !mSettings.isPremiumEnabled("noExplicitConstructor")) |
| 391 | return; |
| 392 | |
| 393 | logChecker("CheckClass::checkExplicitConstructors"); // style |
| 394 | |
| 395 | for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { |
| 396 | // Do not perform check, if the class/struct has not any constructors |
| 397 | if (scope->numConstructors == 0) |
| 398 | continue; |
| 399 | |
| 400 | // Is class abstract? Maybe this test is over-simplification, but it will suffice for simple cases, |
| 401 | // and it will avoid false positives. |
| 402 | const bool isAbstractClass = std::any_of(scope->functionList.cbegin(), scope->functionList.cend(), [](const Function& func) { |
| 403 | return func.isPure(); |
| 404 | }); |
| 405 | |
| 406 | // Abstract classes can't be instantiated. But if there is C++11 |
| 407 | // "misuse" by derived classes then these constructors must be explicit. |
| 408 | if (isAbstractClass && mSettings.standards.cpp >= Standards::CPP11) |
| 409 | continue; |
| 410 | |
| 411 | for (const Function &func : scope->functionList) { |
| 412 | |
| 413 | // We are looking for constructors, which are meeting following criteria: |
| 414 | // 1) Constructor is declared with a single parameter |
| 415 | // 2) Constructor is not declared as explicit |
| 416 | // 3) It is not a copy/move constructor of non-abstract class |
| 417 | // 4) Constructor is not marked as delete (programmer can mark the default constructor as deleted, which is ok) |
| 418 | if (!func.isConstructor() || func.isDelete() || (!func.hasBody() && func.access == AccessControl::Private)) |
| 419 | continue; |
| 420 | |
| 421 | if (!func.isExplicit() && |
| 422 | func.argCount() > 0 && func.minArgCount() < 2 && |
| 423 | func.type != FunctionType::eCopyConstructor && |
| 424 | func.type != FunctionType::eMoveConstructor && |
| 425 | !(func.templateDef && Token::simpleMatch(func.argumentList.front().typeEndToken(), "...")) && |
| 426 | !isPermissibleConversion(func.argumentList.front().getTypeName())) { |
| 427 | noExplicitConstructorError(func.tokenDef, scope->className, scope->type == ScopeType::eStruct); |
| 428 | } |
| 429 | } |
| 430 | } |
| 431 | } |
| 432 | |
| 433 | static bool hasNonCopyableBase(const Scope *scope, bool *unknown) |
| 434 | { |
no test coverage detected