diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index cccdc77ad..0802f1fb7 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -934,24 +934,37 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::listnext(); tok2; tok2 = tok2->next()) { if (tok2->str() == ";") { + trailingSemicolon = true; if (rhs) tok = tok2; break; } - if (Token::Match(tok2, "[=+(,] %varid%", varid)) { - if (!rhs && Token::Match(tok2, "[(,]")) { - addtoken(&rettail, tok, "use"); - addtoken(&rettail, tok, ";"); + if (!used) { + if (Token::Match(tok2, "[=+(,] %varid%", varid)) { + if (!rhs && Token::Match(tok2, "[(,]")) { + used = true; + addtoken(&rettail, tok, "use"); + addtoken(&rettail, tok, ";"); + } + rhs = true; } - rhs = true; } } - if (!rhs) - addtoken(&rettail, tok, "assign"); + if (!used) { + if (!rhs) + addtoken(&rettail, tok, "assign"); + else { + addtoken(&rettail, tok, "use_"); + if (trailingSemicolon) + addtoken(&rettail, tok, ";"); + } + } continue; } } @@ -1250,12 +1263,15 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::liststrAt(3) != "[" && + tok->strAt(3) != ".") || Token::Match(tok, "<< %varid% ;", varid) || Token::Match(tok, "= strcpy|strcat|memmove|memcpy ( %varid% ,", varid) || Token::Match(tok, "[;{}] %var% [ %varid% ]", varid)) { addtoken(&rettail, tok, "use"); - } else if (Token::Match(tok->previous(), ";|{|}|=|(|,|%op% %varid% [", varid)) { + } else if (Token::Match(tok->previous(), ";|{|}|=|(|,|%op% %varid% [", varid) || + Token::Match(tok->previous(), ";|{|}|=|(|,|%op% %varid% .", varid)) { // warning is written for "dealloc ; use_ ;". // but this use doesn't affect the leak-checking addtoken(&rettail, tok, "use_"); @@ -1828,11 +1844,36 @@ void CheckMemoryLeakInFunction::simplifycode(Token *tok) const } // use use => use - if (Token::simpleMatch(tok2, "use use")) { + while (Token::simpleMatch(tok2, "use use")) { tok2->deleteNext(); done = false; } + // use use_ => use + if (Token::simpleMatch(tok2, "use use_")) { + tok2->deleteNext(); + done = false; + } + + // use_ use => use + if (Token::simpleMatch(tok2, "use_ use")) { + tok2->deleteThis(); + done = false; + } + + // use & use => use + while (Token::simpleMatch(tok2, "use & use")) { + tok2->deleteNext(2); + done = false; + } + + // & use use => use + while (Token::simpleMatch(tok2, "& use use")) { + tok2->deleteThis(); + tok2->deleteThis(); + done = false; + } + // use; if| use; => use; while (Token::Match(tok2, "[;{}] use ; if| use ;")) { Token *t = tok2->tokAt(2); diff --git a/lib/checkmemoryleak.h b/lib/checkmemoryleak.h index 09f7c6d44..465d20e9d 100644 --- a/lib/checkmemoryleak.h +++ b/lib/checkmemoryleak.h @@ -276,6 +276,7 @@ public: * - "use" : unknown usage -> bail out checking of this execution path * - "&use" : the address of the variable is taken * - "::use" : calling member function of class + * - "use_" : content of variable is accessed (used to warn access after dealloc) */ Token *getcode(const Token *tok, std::list callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool classmember, unsigned int sz); diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index b2a7d49c3..e8a8ab0b4 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -500,11 +500,18 @@ private: ASSERT_EQUALS(";;use;;", getcode("char *s; x = {1,s};", "s")); ASSERT_EQUALS(";{};;alloc;;use;", getcode("struct Foo { }; Foo *p; p = malloc(10); const Foo *q; q = p;", "p")); ASSERT_EQUALS(";;alloc;use;", getcode("Fred *fred; p.setFred(fred = new Fred);", "fred")); - ASSERT_EQUALS(";;use;", getcode("struct AB *ab; f(ab->a);", "ab")); + ASSERT_EQUALS(";;useuse_;", getcode("struct AB *ab; f(ab->a);", "ab")); ASSERT_EQUALS(";;use;", getcode("struct AB *ab; ab = pop(ab);", "ab")); // non-use.. - ASSERT_EQUALS(";;", getcode("char *s; s = s + 1;", "s")); + ASSERT_EQUALS(";;use_;", getcode("char *s; c = x + s[0];","s")); + ASSERT_EQUALS(";;use_;", getcode("char *s; c = s[0] + x;","s")); + ASSERT_EQUALS(";;use_;", getcode("type *c; y = x + c->y;","c")); + ASSERT_EQUALS(";;use_;", getcode("type *c; y = c->y + x;","c")); + ASSERT_EQUALS(";;use_;", getcode("char *s; s = s + 1;", "s")); + + // use reference + ASSERT_EQUALS(";;callfunc&use;", getcode("struct AB *ab; f(&ab);", "ab")); // reference ASSERT_EQUALS(";", getcode("char *p; char * & ref = p; p = malloc(10);", "p")); @@ -664,6 +671,10 @@ private: // use.. ASSERT_EQUALS("; use ; }", simplifycode("; use use ; }")); + ASSERT_EQUALS("; use ; }", simplifycode("; use use_ ; }")); + ASSERT_EQUALS("; use ; }", simplifycode("; use_ use ; }")); + ASSERT_EQUALS("; use ; }", simplifycode("; &use use ; }")); + ASSERT_EQUALS("; use ; }", simplifycode("; use &use ; }")); ASSERT_EQUALS("; alloc ; dealloc ; }", simplifycode("; alloc ; use ; use ; if use ; dealloc ; }")); // if, else..