From 40ddcabab6e8674a3dc549b5221e63c783320805 Mon Sep 17 00:00:00 2001 From: Alexander Mai Date: Sat, 15 Mar 2014 18:22:29 +0100 Subject: [PATCH] Fixed #4461 (Warn about memset/memcpy on class with references as members) --- lib/checkclass.cpp | 20 +++++++++++++++----- lib/checkclass.h | 9 +++++---- test/testclass.cpp | 18 ++++++++++++++++++ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 85fb3dc05..f88a4236c 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1044,8 +1044,12 @@ void CheckClass::checkMemsetType(const Scope *start, const Token *tok, const Sco std::list::const_iterator var; for (var = type->varlist.begin(); var != type->varlist.end(); ++var) { + if (var->isReference()) { + memsetErrorReference(tok, tok->str(), type->classDef->str()); + continue; + } // don't warn if variable static or const, pointer or reference - if (!var->isStatic() && !var->isConst() && !var->isPointer() && !var->isReference()) { + if (!var->isStatic() && !var->isConst() && !var->isPointer()) { const Token *tok1 = var->typeStartToken(); const Scope *typeScope = var->typeScope(); @@ -1090,6 +1094,12 @@ void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const reportError(tok, Severity::error, "memsetClass", "Using '" + memfunc + "' on " + type + " that contains a " + classname + "."); } +void CheckClass::memsetErrorReference(const Token *tok, const std::string &memfunc, const std::string &type) +{ + reportError(tok, Severity::error, "memsetClass", "Using '" + memfunc + "' on " + type + " that contains a reference."); +} + + //--------------------------------------------------------------------------- // ClassCheck: "void operator=(" and "const type & operator=(" //--------------------------------------------------------------------------- @@ -1266,7 +1276,7 @@ void CheckClass::operatorEqToSelf() } } -bool CheckClass::hasAllocation(const Function *func, const Scope* scope) +bool CheckClass::hasAllocation(const Function *func, const Scope* scope) const { // This function is called when no simple check was found for assignment // to self. We are currently looking for: @@ -1573,7 +1583,7 @@ void CheckClass::checkConst() } } -bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) +bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) const { bool again = false; @@ -1661,7 +1671,7 @@ static unsigned int countMinArgs(const Token* argList) return count; } -bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) +bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const { unsigned int args = countParameters(tok); @@ -1691,7 +1701,7 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) return false; } -bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) +bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) const { unsigned int args = countParameters(tok); diff --git a/lib/checkclass.h b/lib/checkclass.h index e5fc04234..33e584d34 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -139,6 +139,7 @@ private: 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); + void memsetErrorReference(const Token *tok, const std::string &memfunc, const std::string &type); void mallocOnClassError(const Token* tok, const std::string &memfunc, const Token* classTok, const std::string &classname); void mallocOnClassWarning(const Token* tok, const std::string &memfunc, const Token* classTok); void operatorEqReturnError(const Token *tok, const std::string &className); @@ -205,13 +206,13 @@ private: void checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last); // operatorEqToSelf helper functions - bool hasAllocation(const Function *func, const Scope* scope); + bool hasAllocation(const Function *func, const Scope* scope) const; static bool hasAssignSelf(const Function *func, const Token *rhs); // checkConst helper functions - bool isMemberVar(const Scope *scope, const Token *tok); - bool isMemberFunc(const Scope *scope, const Token *tok); - bool isConstMemberFunc(const Scope *scope, const Token *tok); + bool isMemberVar(const Scope *scope, const Token *tok) const; + bool isMemberFunc(const Scope *scope, const Token *tok) const; + bool isConstMemberFunc(const Scope *scope, const Token *tok) const; bool checkConstFunc(const Scope *scope, const Function *func, bool& memberAccessed); // constructors helper function diff --git a/test/testclass.cpp b/test/testclass.cpp index 98793d6a7..ab79b3c87 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -2284,6 +2284,24 @@ private: " memset(b,0,4);\n" "}"); ASSERT_EQUALS("", errout.str()); + + // #4461 Warn about memset/memcpy on class with references as members + checkNoMemset("class A {\n" + " std::string &s;\n" + "};\n" + "void f() {\n" + " A a;\n" + " memset(&a, 0, sizeof(a)); \n" + "}"); + ASSERT_EQUALS("[test.cpp:6]: (error) Using 'memset' on class that contains a reference.\n", errout.str()); + checkNoMemset("class A {\n" + " const B&b;\n" + "};\n" + "void f() {\n" + " A a;\n" + " memset(&a, 0, sizeof(a)); \n" + "}"); + ASSERT_EQUALS("[test.cpp:6]: (error) Using 'memset' on class that contains a reference.\n", errout.str()); } void memsetOnInvalid() { // Ticket #5425