Fix false positives when class might inherit from VCL TObject class

This commit is contained in:
Daniel Marjamäki 2021-06-13 18:56:04 +02:00
parent 5dae162780
commit 03445c01c1
2 changed files with 54 additions and 0 deletions

View File

@ -79,6 +79,28 @@ static bool isVariableCopyNeeded(const Variable &var)
(var.valueType() && var.valueType()->type >= ValueType::Type::CHAR); (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) 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); const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive);
for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { for (const Scope * scope : mSymbolDatabase->classAndStructScopes) {
if (isVcl(mSettings) && isVclTypeInit(scope->definedType))
continue;
const bool unusedTemplate = Token::simpleMatch(scope->classDef->previous(), ">"); const bool unusedTemplate = Token::simpleMatch(scope->classDef->previous(), ">");
bool usedInUnion = false; bool usedInUnion = false;

View File

@ -47,6 +47,20 @@ private:
checkClass.constructors(); 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 { void run() OVERRIDE {
settings.severity.enable(Severity::style); settings.severity.enable(Severity::style);
settings.severity.enable(Severity::warning); settings.severity.enable(Severity::warning);
@ -176,6 +190,7 @@ private:
TEST_CASE(privateCtor2); // If constructor is private.. TEST_CASE(privateCtor2); // If constructor is private..
TEST_CASE(function); // Function is not variable TEST_CASE(function); // Function is not variable
TEST_CASE(uninitVarPublished); // Borland C++: Variables in the published section are auto-initialized 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(uninitOperator); // No FP about uninitialized 'operator[]'
TEST_CASE(uninitFunction1); // No FP when initialized in function TEST_CASE(uninitFunction1); // No FP when initialized in function
TEST_CASE(uninitFunction2); // No FP when initialized in function TEST_CASE(uninitFunction2); // No FP when initialized in function
@ -3163,6 +3178,20 @@ private:
ASSERT_EQUALS("", errout.str()); 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() { void uninitOperator() {
check("class Fred\n" check("class Fred\n"
"{\n" "{\n"