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:
parent
4a9176f83c
commit
cf3515ee61
|
@ -145,6 +145,13 @@ void CheckClass::constructors()
|
||||||
if (!func.hasBody() || !(func.isConstructor() || func.type == Function::eOperatorEqual))
|
if (!func.hasBody() || !(func.isConstructor() || func.type == Function::eOperatorEqual))
|
||||||
continue;
|
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
|
// Mark all variables not used
|
||||||
clearAllVar(usage);
|
clearAllVar(usage);
|
||||||
|
|
||||||
|
@ -218,6 +225,9 @@ void CheckClass::constructors()
|
||||||
if (classNameUsed)
|
if (classNameUsed)
|
||||||
operatorEqVarError(func.token, scope->className, var.name(), inconclusive);
|
operatorEqVarError(func.token, scope->className, var.name(), inconclusive);
|
||||||
} else if (func.access != Private || mSettings->standards.cpp >= Standards::CPP11) {
|
} 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();
|
const Scope *varType = var.typeScope();
|
||||||
if (!varType || varType->type != Scope::eUnion) {
|
if (!varType || varType->type != Scope::eUnion) {
|
||||||
if (func.type == Function::eConstructor &&
|
if (func.type == Function::eConstructor &&
|
||||||
|
|
|
@ -194,6 +194,8 @@ private:
|
||||||
TEST_CASE(uninitAssignmentWithOperator); // ticket #7429
|
TEST_CASE(uninitAssignmentWithOperator); // ticket #7429
|
||||||
TEST_CASE(uninitCompoundAssignment); // ticket #7429
|
TEST_CASE(uninitCompoundAssignment); // ticket #7429
|
||||||
TEST_CASE(uninitComparisonAssignment); // 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());
|
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"
|
" class LocalClass : public copy_protected {\n"
|
||||||
" public:\n"
|
" public:\n"
|
||||||
" LocalClass() : copy_protected(1), dataLength_(0) {}\n"
|
" LocalClass() : copy_protected(1), dataLength_(0) {}\n"
|
||||||
|
@ -2180,9 +2183,12 @@ private:
|
||||||
" double bitsInData_;\n"
|
" double bitsInData_;\n"
|
||||||
" } obj;\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"
|
" class LocalClass : ::copy_protected {\n"
|
||||||
" public:\n"
|
" public:\n"
|
||||||
" LocalClass() : copy_protected(1), dataLength_(0) {}\n"
|
" LocalClass() : copy_protected(1), dataLength_(0) {}\n"
|
||||||
|
@ -2190,7 +2196,9 @@ private:
|
||||||
" double bitsInData_;\n"
|
" double bitsInData_;\n"
|
||||||
" } obj;\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
|
void uninitVar21() { // ticket #2947
|
||||||
|
@ -3849,6 +3857,36 @@ private:
|
||||||
"};");
|
"};");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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)
|
REGISTER_TEST(TestConstructors)
|
||||||
|
|
Loading…
Reference in New Issue