diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 9fc9bdc7863..dc679863026 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -351,6 +351,8 @@ void CheckClass::constructors() // Variables with default initializers bool hasAnyDefaultInit = false; + bool hasAnySelfInit = false; + const bool cpp14OrLater = mSettings->standards.cpp >= Standards::CPP14; for (Usage& usage : usageList) { const Variable& var = *usage.var; @@ -358,9 +360,11 @@ void CheckClass::constructors() if (var.hasDefault()) { usage.init = true; hasAnyDefaultInit = true; + } else if (cpp14OrLater && !hasAnySelfInit && isInitialized(usage, FunctionType::eConstructor)) { + hasAnySelfInit = true; } } - if (!hasAnyDefaultInit) + if (!hasAnyDefaultInit && !hasAnySelfInit) continue; handleUnionMembers(usageList); @@ -371,8 +375,11 @@ void CheckClass::constructors() continue; const Variable& var = *usage.var; + if (var.typeScope() && var.typeScope()->numConstructors > 0) + continue; + if (diagVars.count(&var) == 0) - uninitVarError(scope->bodyStart, false, FunctionType::eConstructor, var.scope()->className, var.name(), false, false, true); + uninitVarError(var.nameToken(), false, FunctionType::eConstructor, var.scope()->className, var.name(), false, false, true); } } } diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp index 61916e1d0bb..0eb91ba8cca 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -763,12 +763,40 @@ class TestConstructors : public TestFixture { check("struct S {\n" // #14546 " int a = 0, b;\n" "};\n"); - ASSERT_EQUALS("[test.cpp:1:10]: (warning) Member variable 'S::b' has no initializer. [uninitMemberVarNoCtor]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:16]: (warning) Member variable 'S::b' has no initializer. [uninitMemberVarNoCtor]\n", errout_str()); check("struct S {\n" " int a, b;\n" "};\n"); ASSERT_EQUALS("", errout_str()); + + check("struct S {\n" + " explicit S(int);\n" + " S(const S&);\n" + " int i;\n" + "};\n" + "struct T {\n" + " S s;\n" + " int j{};\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); + + const char code[] = "struct S { int i = 0; };\n" // #14697 + "struct T {\n" + " S s;\n" + " int j;\n" + "};\n" + "struct U {\n" + " std::string a;\n" + " int k;\n" + "};\n"; + const Settings s = settingsBuilder(settings).cpp(Standards::CPP11).build(); + check(code, s); + ASSERT_EQUALS("", errout_str()); + check(code); + ASSERT_EQUALS("[test.cpp:4:9]: (warning) Member variable 'T::j' has no initializer. [uninitMemberVarNoCtor]\n" + "[test.cpp:8:9]: (warning) Member variable 'U::k' has no initializer. [uninitMemberVarNoCtor]\n", + errout_str()); } // ticket #4290 "False Positive: style (noConstructor): The class 'foo' does not have a constructor."