diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 1504b4822..786f1e5a7 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -79,6 +79,28 @@ static bool isVariableCopyNeeded(const Variable &var) (var.valueType() && var.valueType()->type >= ValueType::Type::CHAR); } +static bool isVcl(const Settings *settings) +{ + for (const std::string &library: settings->libraries) { + if (library == "vcl") + return true; + } + return false; +} + +static bool isVclTypeInit(const Type *type) +{ + if (!type) + return false; + for (const Type::BaseInfo &baseInfo: type->derivedFrom) { + if (!baseInfo.type) + return true; + if (isVclTypeInit(baseInfo.type)) + return true; + } + return false; +} + //--------------------------------------------------------------------------- CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) @@ -101,6 +123,9 @@ void CheckClass::constructors() const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive); for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { + if (isVcl(mSettings) && isVclTypeInit(scope->definedType)) + continue; + const bool unusedTemplate = Token::simpleMatch(scope->classDef->previous(), ">"); bool usedInUnion = false; diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp index 9d147c6c8..2a0d4a789 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -47,6 +47,20 @@ private: checkClass.constructors(); } + void check(const char code[], const Settings &s) { + // Clear the error buffer.. + errout.str(""); + + // Tokenize.. + Tokenizer tokenizer(&s, this); + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + // Check class constructors.. + CheckClass checkClass(&tokenizer, &s, this); + checkClass.constructors(); + } + void run() OVERRIDE { settings.severity.enable(Severity::style); settings.severity.enable(Severity::warning); @@ -176,6 +190,7 @@ private: TEST_CASE(privateCtor2); // If constructor is private.. TEST_CASE(function); // Function is not variable TEST_CASE(uninitVarPublished); // Borland C++: Variables in the published section are auto-initialized + TEST_CASE(uninitVarInheritClassInit); // Borland C++: if class inherits from TObject, all variables are initialized TEST_CASE(uninitOperator); // No FP about uninitialized 'operator[]' TEST_CASE(uninitFunction1); // No FP when initialized in function TEST_CASE(uninitFunction2); // No FP when initialized in function @@ -3163,6 +3178,20 @@ private: ASSERT_EQUALS("", errout.str()); } + void uninitVarInheritClassInit() { + Settings s; + s.libraries.emplace_back("vcl"); + + check("class Fred: public TObject\n" + "{\n" + "public:\n" + " Fred() { }\n" + "private:\n" + " int x;\n" + "};", s); + ASSERT_EQUALS("", errout.str()); + } + void uninitOperator() { check("class Fred\n" "{\n"