From e492932f19386bebc57c4ee02ce3b220b4bb4481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 2 Apr 2018 15:26:15 +0200 Subject: [PATCH] Improve check: Variable is not initialized in private constructor (C++11 or later) --- lib/checkclass.cpp | 10 +++++----- lib/checkclass.h | 4 ++-- test/testconstructors.cpp | 21 ++++++++++++++++++++- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index f56df18f9..7b7ad48ae 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -220,7 +220,7 @@ void CheckClass::constructors() if (classNameUsed) operatorEqVarError(func->token, scope->className, var->name(), inconclusive); - } else if (func->access != Private) { + } else if (func->access != Private || _settings->standards.cpp >= Standards::CPP11) { const Scope *varType = var->typeScope(); if (!varType || varType->type != Scope::eUnion) { if (func->type == Function::eConstructor && @@ -230,9 +230,9 @@ void CheckClass::constructors() func->functionScope->classStart->link() == func->functionScope->classStart->next()) { // don't warn about user defined default constructor when there are other constructors if (printInconclusive) - uninitVarError(func->token, scope->className, var->name(), true); + uninitVarError(func->token, func->access == Private, scope->className, var->name(), true); } else - uninitVarError(func->token, scope->className, var->name(), inconclusive); + uninitVarError(func->token, func->access == Private, scope->className, var->name(), inconclusive); } } } @@ -829,9 +829,9 @@ void CheckClass::noExplicitConstructorError(const Token *tok, const std::string reportError(tok, Severity::style, "noExplicitConstructor", message + "\n" + verbose, CWE398, false); } -void CheckClass::uninitVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive) +void CheckClass::uninitVarError(const Token *tok, bool isprivate, const std::string &classname, const std::string &varname, bool inconclusive) { - reportError(tok, Severity::warning, "uninitMemberVar", "Member variable '" + classname + "::" + varname + "' is not initialized in the constructor.", CWE398, inconclusive); + reportError(tok, Severity::warning, isprivate ? "uninitMemberVarPrivate" : "uninitMemberVar", "Member variable '" + classname + "::" + varname + "' is not initialized in the constructor.", CWE398, inconclusive); } void CheckClass::operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive) diff --git a/lib/checkclass.h b/lib/checkclass.h index d07452e1f..7956e0c10 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -164,7 +164,7 @@ private: //void copyConstructorMallocError(const Token *cctor, const Token *alloc, const std::string& var_name); void copyConstructorShallowCopyError(const Token *tok, const std::string& varname); void noCopyConstructorError(const Token *tok, const std::string &classname, bool isStruct); - void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive); + void uninitVarError(const Token *tok, bool isprivate, const std::string &classname, const std::string &varname, bool inconclusive); void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive); void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname); void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type); @@ -196,7 +196,7 @@ private: //c.copyConstructorMallocError(nullptr, 0, "var"); c.copyConstructorShallowCopyError(nullptr, "var"); c.noCopyConstructorError(nullptr, "class", false); - c.uninitVarError(nullptr, "classname", "varname", false); + c.uninitVarError(nullptr, false, "classname", "varname", false); c.operatorEqVarError(nullptr, "classname", emptyString, false); c.unusedPrivateFunctionError(nullptr, "classname", "funcname"); c.memsetError(nullptr, "memfunc", "classname", "class"); diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp index b85657125..6f6afd0bd 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -1092,6 +1092,18 @@ private: void initvar_private_constructor() { + settings.standards.cpp = Standards::CPP11; + check("class Fred\n" + "{\n" + "private:\n" + " int var;\n" + " Fred();\n" + "};\n" + "Fred::Fred()\n" + "{ }"); + ASSERT_EQUALS("[test.cpp:7]: (warning) Member variable 'Fred::var' is not initialized in the constructor.\n", errout.str()); + + settings.standards.cpp = Standards::CPP03; check("class Fred\n" "{\n" "private:\n" @@ -2897,15 +2909,22 @@ private: " char data[42];\n" "};"); ASSERT_EQUALS("", errout.str()); - } void privateCtor1() { + settings.standards.cpp = Standards::CPP03; check("class Foo {\n" " int foo;\n" " Foo() { }\n" "};"); ASSERT_EQUALS("", errout.str()); + + settings.standards.cpp = Standards::CPP11; + check("class Foo {\n" + " int foo;\n" + " Foo() { }\n" + "};"); + ASSERT_EQUALS("[test.cpp:3]: (warning) Member variable 'Foo::foo' is not initialized in the constructor.\n", errout.str()); } void privateCtor2() {