Improved check: portability message when calling memset on a class with floating point numbers (#5421)

This commit is contained in:
PKEuS 2014-08-08 08:08:21 +02:00
parent a1b7ab277b
commit c4635cf698
3 changed files with 60 additions and 5 deletions

View File

@ -1037,7 +1037,7 @@ void CheckClass::checkMemsetType(const Scope *start, const Token *tok, const Sco
std::list<Variable>::const_iterator var;
for (var = type->varlist.begin(); var != type->varlist.end(); ++var) {
if (var->isReference()) {
if (var->isReference() && !var->isStatic()) {
memsetErrorReference(tok, tok->str(), type->classDef->str());
continue;
}
@ -1056,6 +1056,10 @@ void CheckClass::checkMemsetType(const Scope *start, const Token *tok, const Sco
// check for known type
else if (typeScope && typeScope != type)
checkMemsetType(start, tok, typeScope, allocation, parsedTypes);
// check for float
else if ((var->typeStartToken()->str() == "float" || var->typeStartToken()->str() == "double") && _settings->isEnabled("portability"))
memsetErrorFloat(tok, tok->str(), type->classDef->str());
}
}
}
@ -1093,7 +1097,14 @@ void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const
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.");
reportError(tok, Severity::error, "memsetClassReference", "Using '" + memfunc + "' on " + type + " that contains a reference.");
}
void CheckClass::memsetErrorFloat(const Token *tok, const std::string &memfunc, const std::string &type)
{
reportError(tok, Severity::portability, "memsetClassFloat", "Using '" + memfunc + "' on " + type + " which contains a floating point number.\n"
"Using '" + memfunc + "' on " + type + " which contains a floating point number. This is not portable because memset() sets each byte of a block of memory to a specific value and"
" the actual representation of a floating-point value is implementation defined.");
}

View File

@ -144,6 +144,7 @@ private:
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 memsetErrorFloat(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);
@ -169,6 +170,8 @@ private:
c.operatorEqVarError(0, "classname", "", false);
c.unusedPrivateFunctionError(0, "classname", "funcname");
c.memsetError(0, "memfunc", "classname", "class");
c.memsetErrorReference(0, "memfunc", "class");
c.memsetErrorFloat(0, "memfunc", "class");
c.mallocOnClassWarning(0, "malloc", 0);
c.mallocOnClassError(0, "malloc", 0, "std::string");
c.operatorEqReturnError(0, "class");

View File

@ -73,8 +73,9 @@ private:
TEST_CASE(memsetOnStruct);
TEST_CASE(memsetVector);
TEST_CASE(memsetOnClass);
TEST_CASE(memsetOnInvalid); // Ticket #5425: Crash upon invalid
TEST_CASE(memsetOnStdPodType); // #5901 - std::uint8_t
TEST_CASE(memsetOnInvalid); // Ticket #5425: Crash upon invalid
TEST_CASE(memsetOnStdPodType); // Ticket #5901 - std::uint8_t
TEST_CASE(memsetOnFloat); // Ticket #5421
TEST_CASE(mallocOnClass);
TEST_CASE(this_subtraction); // warn about "this-x"
@ -2007,12 +2008,14 @@ private:
ASSERT_EQUALS("[test.cpp:3]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
}
void checkNoMemset(const char code[], bool load_std_cfg = false) {
void checkNoMemset(const char code[], bool load_std_cfg = false, bool portability = false) {
// Clear the error log
errout.str("");
Settings settings;
settings.addEnabled("warning");
if (portability)
settings.addEnabled("portability");
if (load_std_cfg) {
LOAD_LIB_2(settings.library, "std.cfg");
}
@ -2470,6 +2473,44 @@ private:
ASSERT_EQUALS("", errout.str());
}
void memsetOnFloat() {
checkNoMemset("struct A {\n"
" float f;\n"
"};\n"
"void f() {\n"
" A a;\n"
" memset(&a, 0, sizeof(A));\n"
"}", false, true);
ASSERT_EQUALS("[test.cpp:6]: (portability) Using 'memset' on struct which contains a floating point number.\n", errout.str());
checkNoMemset("struct A {\n"
" float f[4];\n"
"};\n"
"void f() {\n"
" A a;\n"
" memset(&a, 0, sizeof(A));\n"
"}", false, true);
ASSERT_EQUALS("[test.cpp:6]: (portability) Using 'memset' on struct which contains a floating point number.\n", errout.str());
checkNoMemset("struct A {\n"
" float* f;\n"
"};\n"
"void f() {\n"
" A a;\n"
" memset(&a, 0, sizeof(A));\n"
"}", false, true);
ASSERT_EQUALS("", errout.str());
checkNoMemset("struct A {\n"
" float f;\n"
"};\n"
"void f() {\n"
" A a;\n"
" memset(&a, 0, sizeof(A));\n"
"}", false, false);
ASSERT_EQUALS("", errout.str());
}
void mallocOnClass() {
checkNoMemset("class C { C() {} };\n"
"void foo(C*& p) {\n"