diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 7de864719..95306ba78 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -2514,14 +2514,24 @@ void CheckOther::checkDoubleFree() closeDirVariables.clear(); } + // If a variable is passed to a function, remove it from the set of previously freed variables - else if (Token::Match(tok, "%var% (") && !Token::Match(tok, "printf|sprintf|snprintf|fprintf")) { - for (const Token* tok2 = tok->tokAt(2); tok2 != tok->linkAt(1); tok2 = tok2->next()) { - if (Token::Match(tok2, "%var%")) { - unsigned int var = tok2->varId(); - if (var) { - freedVariables.erase(var); - closeDirVariables.erase(var); + else if (Token::Match(tok, "%var% (") && !Token::Match(tok, "printf|sprintf|snprintf|fprintf|if|while")) { + + // If this is a new function definition, clear all variables + if (Token::Match(tok->next()->link(), ") {")) { + freedVariables.clear(); + closeDirVariables.clear(); + } + // If it is a function call, then clear those variables in its argument list + else if (Token::Match(tok->next()->link(), ") ;")) { + for (const Token* tok2 = tok->tokAt(2); tok2 != tok->linkAt(1); tok2 = tok2->next()) { + if (Token::Match(tok2, "%var%")) { + unsigned int var = tok2->varId(); + if (var) { + freedVariables.erase(var); + closeDirVariables.erase(var); + } } } } diff --git a/lib/checkother.h b/lib/checkother.h index 5361f43fa..ab8f65327 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -329,6 +329,7 @@ public: c.sizeofForStrncmpError(0); c.sizeofForNumericParameterError(0); c.coutCerrMisusageError(0, "cout"); + c.doubleFreeError(0, "varname"); // style/warning c.cstyleCastError(0); diff --git a/test/testother.cpp b/test/testother.cpp index 08fb6b3bf..662cfc048 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -4679,6 +4679,18 @@ private: " delete[] p;\n" "}"); ASSERT_EQUALS("[test.cpp:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str()); + + check( + "~LineMarker() {" + " delete pxpm;" + "}" + "LineMarker &operator=(const LineMarker &) {" + " delete pxpm;" + " pxpm = NULL;" + " return *this;" + "}" + ); + ASSERT_EQUALS("", errout.str()); } void coutCerrMisusage() {