Fix issue 7372: False positive uninitMemberVar - on template specialization

This fixes the issue by skipping diagnostics when the symbols are incomplete in the constructor.
This commit is contained in:
Paul Fultz II 2019-05-17 20:24:41 +02:00 committed by Daniel Marjamäki
parent 4a9176f83c
commit cf3515ee61
2 changed files with 52 additions and 4 deletions

View File

@ -145,6 +145,13 @@ void CheckClass::constructors()
if (!func.hasBody() || !(func.isConstructor() || func.type == Function::eOperatorEqual))
continue;
// Bail: If initializer list is not recognized as a variable or type then skip since parsing is incomplete
if (func.type == Function::eConstructor) {
const Token *initList = func.constructorMemberInitialization();
if (Token::Match(initList, ": %name% (") && initList->next()->tokType() == Token::eName)
break;
}
// Mark all variables not used
clearAllVar(usage);
@ -218,6 +225,9 @@ void CheckClass::constructors()
if (classNameUsed)
operatorEqVarError(func.token, scope->className, var.name(), inconclusive);
} else if (func.access != Private || mSettings->standards.cpp >= Standards::CPP11) {
// If constructor is not in scope then we maybe using a oonstructor from a different template specialization
if (!precedes(scope->bodyStart, func.tokenDef))
continue;
const Scope *varType = var.typeScope();
if (!varType || varType->type != Scope::eUnion) {
if (func.type == Function::eConstructor &&

View File

@ -194,6 +194,8 @@ private:
TEST_CASE(uninitAssignmentWithOperator); // ticket #7429
TEST_CASE(uninitCompoundAssignment); // ticket #7429
TEST_CASE(uninitComparisonAssignment); // ticket #7429
TEST_CASE(uninitTemplate1); // ticket #7372
}
@ -2172,7 +2174,8 @@ private:
"};");
ASSERT_EQUALS("[test.cpp:4]: (warning) Member variable 'LocalClass::bitsInData_' is not initialized in the constructor.\n", errout.str());
check("Object::MemFunc() {\n"
check("struct copy_protected;\n"
"Object::MemFunc() {\n"
" class LocalClass : public copy_protected {\n"
" public:\n"
" LocalClass() : copy_protected(1), dataLength_(0) {}\n"
@ -2180,9 +2183,12 @@ private:
" double bitsInData_;\n"
" } obj;\n"
"};");
ASSERT_EQUALS("[test.cpp:4]: (warning) Member variable 'LocalClass::bitsInData_' is not initialized in the constructor.\n", errout.str());
ASSERT_EQUALS(
"[test.cpp:5]: (warning) Member variable 'LocalClass::bitsInData_' is not initialized in the constructor.\n",
errout.str());
check("Object::MemFunc() {\n"
check("struct copy_protected;\n"
"Object::MemFunc() {\n"
" class LocalClass : ::copy_protected {\n"
" public:\n"
" LocalClass() : copy_protected(1), dataLength_(0) {}\n"
@ -2190,7 +2196,9 @@ private:
" double bitsInData_;\n"
" } obj;\n"
"};");
ASSERT_EQUALS("[test.cpp:4]: (warning) Member variable 'LocalClass::bitsInData_' is not initialized in the constructor.\n", errout.str());
ASSERT_EQUALS(
"[test.cpp:5]: (warning) Member variable 'LocalClass::bitsInData_' is not initialized in the constructor.\n",
errout.str());
}
void uninitVar21() { // ticket #2947
@ -3849,6 +3857,36 @@ private:
"};");
ASSERT_EQUALS("", errout.str());
}
void uninitTemplate1() {
check("template <class A, class T> class C;\n"
"template <class A>\n"
"class C<A, void> {\n"
" public:\n"
" C() : b(0) { }\n"
" C(A* a) : b(a) { }\n"
" private:\n"
" A* b;\n"
"};\n"
"template <class A, class T>\n"
"class C {\n"
" private:\n"
" A* b;\n"
"};\n");
ASSERT_EQUALS("", errout.str());
check("template<class T> class A{};\n"
"template<class T1, class T2> class B{};\n"
"template<class T1, class T2>\n"
"class A<B<T1, T2>> {\n"
" public:\n"
" A();\n"
" bool m_value;\n"
"};\n"
"template<class T1, class T2>\n"
"A<B<T1, T2>>::A() : m_value(false) {}\n");
ASSERT_EQUALS("", errout.str());
}
};
REGISTER_TEST(TestConstructors)