Fixed #8542 (False positive: noOperatorEq)

This commit is contained in:
Daniel Marjamäki 2018-05-05 07:46:58 +02:00
parent 31ac889d38
commit 64b85b474c
3 changed files with 20 additions and 8 deletions

View File

@ -340,11 +340,14 @@ void CheckClass::copyconstructors()
} }
if (!funcCopyCtor || funcCopyCtor->isDefault()) { if (!funcCopyCtor || funcCopyCtor->isDefault()) {
bool unknown = false; bool unknown = false;
if (!isNonCopyable(scope, &unknown)) if (!isNonCopyable(scope, &unknown) && !unknown)
noCopyConstructorError(scope, funcCopyCtor, allocatedVars.begin()->second, unknown); noCopyConstructorError(scope, funcCopyCtor, allocatedVars.begin()->second, unknown);
} }
if (!funcOperatorEq || funcOperatorEq->isDefault()) if (!funcOperatorEq || funcOperatorEq->isDefault()) {
noOperatorEqError(scope, funcOperatorEq, allocatedVars.begin()->second); bool unknown = false;
if (!isNonCopyable(scope, &unknown) && !unknown)
noOperatorEqError(scope, funcOperatorEq, allocatedVars.begin()->second, unknown);
}
if (!funcDestructor || funcDestructor->isDefault()) { if (!funcDestructor || funcDestructor->isDefault()) {
const Token * mustDealloc = nullptr; const Token * mustDealloc = nullptr;
for (std::map<unsigned int, const Token*>::const_iterator it = allocatedVars.begin(); it != allocatedVars.end(); ++it) { for (std::map<unsigned int, const Token*>::const_iterator it = allocatedVars.begin(); it != allocatedVars.end(); ++it) {
@ -452,9 +455,9 @@ void CheckClass::noCopyConstructorError(const Scope *scope, bool isdefault, cons
reportError(alloc, Severity::style, "noCopyConstructor", noMemberErrorMessage(scope, "copy constructor", isdefault), CWE398, inconclusive); reportError(alloc, Severity::style, "noCopyConstructor", noMemberErrorMessage(scope, "copy constructor", isdefault), CWE398, inconclusive);
} }
void CheckClass::noOperatorEqError(const Scope *scope, bool isdefault, const Token *alloc) void CheckClass::noOperatorEqError(const Scope *scope, bool isdefault, const Token *alloc, bool inconclusive)
{ {
reportError(alloc, Severity::style, "noOperatorEq", noMemberErrorMessage(scope, "operator=", isdefault), CWE398, false); reportError(alloc, Severity::style, "noOperatorEq", noMemberErrorMessage(scope, "operator=", isdefault), CWE398, inconclusive);
} }
void CheckClass::noDestructorError(const Scope *scope, bool isdefault, const Token *alloc) void CheckClass::noDestructorError(const Scope *scope, bool isdefault, const Token *alloc)

View File

@ -169,7 +169,7 @@ private:
//void copyConstructorMallocError(const Token *cctor, const Token *alloc, const std::string& var_name); //void copyConstructorMallocError(const Token *cctor, const Token *alloc, const std::string& var_name);
void copyConstructorShallowCopyError(const Token *tok, const std::string& varname); void copyConstructorShallowCopyError(const Token *tok, const std::string& varname);
void noCopyConstructorError(const Scope *scope, bool isdefault, const Token *alloc, bool inconclusive); void noCopyConstructorError(const Scope *scope, bool isdefault, const Token *alloc, bool inconclusive);
void noOperatorEqError(const Scope *scope, bool isdefault, const Token *alloc); void noOperatorEqError(const Scope *scope, bool isdefault, const Token *alloc, bool inconclusive);
void noDestructorError(const Scope *scope, bool isdefault, const Token *alloc); void noDestructorError(const Scope *scope, bool isdefault, const Token *alloc);
void uninitVarError(const Token *tok, bool isprivate, 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 operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive);
@ -205,7 +205,7 @@ private:
//c.copyConstructorMallocError(nullptr, 0, "var"); //c.copyConstructorMallocError(nullptr, 0, "var");
c.copyConstructorShallowCopyError(nullptr, "var"); c.copyConstructorShallowCopyError(nullptr, "var");
c.noCopyConstructorError(nullptr, false, nullptr, false); c.noCopyConstructorError(nullptr, false, nullptr, false);
c.noOperatorEqError(nullptr, false, nullptr); c.noOperatorEqError(nullptr, false, nullptr, false);
c.noDestructorError(nullptr, false, nullptr); c.noDestructorError(nullptr, false, nullptr);
c.uninitVarError(nullptr, false, "classname", "varname", false); c.uninitVarError(nullptr, false, "classname", "varname", false);
c.operatorEqVarError(nullptr, "classname", emptyString, false); c.operatorEqVarError(nullptr, "classname", emptyString, false);

View File

@ -736,7 +736,7 @@ private:
" ~F();\n" " ~F();\n"
" F& operator=(const F&f);\n" " F& operator=(const F&f);\n"
"};"); "};");
ASSERT_EQUALS("[test.cpp:5]: (style, inconclusive) Class 'F' does not have a copy constructor which is recommended since it has dynamic memory/resource allocation(s).\n", errout.str()); ASSERT_EQUALS("", errout.str());
checkCopyConstructor("class E { E(E&); };\n" // non-copyable checkCopyConstructor("class E { E(E&); };\n" // non-copyable
"class F : E\n" "class F : E\n"
@ -855,6 +855,15 @@ private:
" ~F();\n" " ~F();\n"
"};"); "};");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// base class deletes operator=
checkCopyConstructor("struct F : NonCopyable {\n"
" char* c;\n"
" F() { c = malloc(100); }\n"
" F(const F &f);\n"
" ~F();\n"
"};");
ASSERT_EQUALS("", errout.str());
} }
void noDestructor() { void noDestructor() {