Skip to content

Commit 03445c0

Browse files
committed
Fix false positives when class might inherit from VCL TObject class
1 parent 5dae162 commit 03445c0

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

lib/checkclass.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,28 @@ static bool isVariableCopyNeeded(const Variable &var)
7979
(var.valueType() && var.valueType()->type >= ValueType::Type::CHAR);
8080
}
8181

82+
static bool isVcl(const Settings *settings)
83+
{
84+
for (const std::string &library: settings->libraries) {
85+
if (library == "vcl")
86+
return true;
87+
}
88+
return false;
89+
}
90+
91+
static bool isVclTypeInit(const Type *type)
92+
{
93+
if (!type)
94+
return false;
95+
for (const Type::BaseInfo &baseInfo: type->derivedFrom) {
96+
if (!baseInfo.type)
97+
return true;
98+
if (isVclTypeInit(baseInfo.type))
99+
return true;
100+
}
101+
return false;
102+
}
103+
82104
//---------------------------------------------------------------------------
83105

84106
CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
@@ -101,6 +123,9 @@ void CheckClass::constructors()
101123

102124
const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive);
103125
for (const Scope * scope : mSymbolDatabase->classAndStructScopes) {
126+
if (isVcl(mSettings) && isVclTypeInit(scope->definedType))
127+
continue;
128+
104129
const bool unusedTemplate = Token::simpleMatch(scope->classDef->previous(), ">");
105130

106131
bool usedInUnion = false;

test/testconstructors.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,20 @@ class TestConstructors : public TestFixture {
4747
checkClass.constructors();
4848
}
4949

50+
void check(const char code[], const Settings &s) {
51+
// Clear the error buffer..
52+
errout.str("");
53+
54+
// Tokenize..
55+
Tokenizer tokenizer(&s, this);
56+
std::istringstream istr(code);
57+
tokenizer.tokenize(istr, "test.cpp");
58+
59+
// Check class constructors..
60+
CheckClass checkClass(&tokenizer, &s, this);
61+
checkClass.constructors();
62+
}
63+
5064
void run() OVERRIDE {
5165
settings.severity.enable(Severity::style);
5266
settings.severity.enable(Severity::warning);
@@ -176,6 +190,7 @@ class TestConstructors : public TestFixture {
176190
TEST_CASE(privateCtor2); // If constructor is private..
177191
TEST_CASE(function); // Function is not variable
178192
TEST_CASE(uninitVarPublished); // Borland C++: Variables in the published section are auto-initialized
193+
TEST_CASE(uninitVarInheritClassInit); // Borland C++: if class inherits from TObject, all variables are initialized
179194
TEST_CASE(uninitOperator); // No FP about uninitialized 'operator[]'
180195
TEST_CASE(uninitFunction1); // No FP when initialized in function
181196
TEST_CASE(uninitFunction2); // No FP when initialized in function
@@ -3163,6 +3178,20 @@ class TestConstructors : public TestFixture {
31633178
ASSERT_EQUALS("", errout.str());
31643179
}
31653180

3181+
void uninitVarInheritClassInit() {
3182+
Settings s;
3183+
s.libraries.emplace_back("vcl");
3184+
3185+
check("class Fred: public TObject\n"
3186+
"{\n"
3187+
"public:\n"
3188+
" Fred() { }\n"
3189+
"private:\n"
3190+
" int x;\n"
3191+
"};", s);
3192+
ASSERT_EQUALS("", errout.str());
3193+
}
3194+
31663195
void uninitOperator() {
31673196
check("class Fred\n"
31683197
"{\n"

0 commit comments

Comments
 (0)