From eb82a89758567fcdbdd2f0d12834f0f5f5c63d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 25 Apr 2010 11:55:57 +0200 Subject: [PATCH] ExecutionPath: Better handling of if --- lib/checkbufferoverrun.cpp | 7 ++++ lib/checkmemoryleak.cpp | 7 ++++ lib/checkother.cpp | 14 ++++++++ lib/executionpath.cpp | 70 ++++++++++++++++++++++++++++++-------- lib/executionpath.h | 17 ++++++--- test/testother.cpp | 9 +++++ 6 files changed, 105 insertions(+), 19 deletions(-) mode change 100644 => 100755 lib/executionpath.cpp diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 63ef213df..1667b3818 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -1709,6 +1709,13 @@ private: return new ExecutionPathBufferOverrun(*this); } + /** is other execution path equal? */ + bool is_equal(const ExecutionPath *e) const + { + const ExecutionPathBufferOverrun *c = static_cast(e); + return (value == c->value); + } + /** @brief buffer information */ const std::map &arrayInfo; diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index ba961f5c3..ebf8f0e26 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -2722,6 +2722,13 @@ private: { } + /** is other execution path equal? */ + bool is_equal(const ExecutionPath *e) const + { + const CheckLocalLeaks *c = static_cast(e); + return (allocated == c->allocated && varname == c->varname); + } + /** Is variable allocated? */ bool allocated; diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 82126afda..89311f052 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1691,6 +1691,13 @@ private: /** no implementation => compiler error if used by accident */ void operator=(const CheckNullpointer &); + /** is other execution path equal? */ + bool is_equal(const ExecutionPath *e) const + { + const CheckNullpointer *c = static_cast(e); + return (varname == c->varname && null == c->null); + } + /** variable name for this check (empty => dummy check) */ const std::string varname; @@ -1864,6 +1871,13 @@ private: { } + /** is other execution path equal? */ + bool is_equal(const ExecutionPath *e) const + { + const CheckUninitVar *c = static_cast(e); + return (varname == c->varname && pointer == c->pointer && array == c->array && alloc == c->alloc && strncpy_ == c->strncpy_); + } + /** variable name for this check */ const std::string varname; diff --git a/lib/executionpath.cpp b/lib/executionpath.cpp old mode 100644 new mode 100755 index c08c840a7..35e27b278 --- a/lib/executionpath.cpp +++ b/lib/executionpath.cpp @@ -20,16 +20,12 @@ #include "executionpath.h" #include "token.h" #include +#include // default : bail out if the condition is has variable handling bool ExecutionPath::parseCondition(const Token &tok, std::list & checks) { - if (Token::Match(tok.tokAt(-3), "!!else if (")) - { - ++ifinfo; - } - unsigned int parlevel = 0; for (const Token *tok2 = &tok; tok2; tok2 = tok2->next()) { @@ -45,10 +41,19 @@ bool ExecutionPath::parseCondition(const Token &tok, std::list break; if (tok2->varId() != 0) { - if (ifinfo > 1) - return true; - else - bailOutVar(checks, tok2->varId()); + bailOutVar(checks, tok2->varId()); + for (std::list::iterator it = checks.begin(); it != checks.end();) + { + if ((*it)->varId > 0 && (*it)->numberOfIf >= 1) + { + delete *it; + checks.erase(it++); + } + else + { + ++it; + } + } } } @@ -182,6 +187,9 @@ static void checkExecutionPaths_(const Token *tok, std::list &c if (tok->str() == "if") { + // what variable ids should the numberOfIf be counted for? + std::set countif; + std::list newchecks; while (tok->str() == "if") { @@ -211,16 +219,41 @@ static void checkExecutionPaths_(const Token *tok, std::list &c // Recursively check into the if .. { + std::set countif2; std::list c; - std::list::iterator it; - for (it = checks.begin(); it != checks.end(); ++it) - c.push_back((*it)->copy()); + if (checks.size() == 1) + c.push_back(checks.front()->copy()); + else if (!checks.empty()) + { + std::list::const_iterator it; + it = checks.begin(); + while (++it != checks.end()) + { + c.push_back((*it)->copy()); + countif2.insert((*it)->varId); + } + } checkExecutionPaths_(tok->next(), c); while (!c.empty()) { - newchecks.push_back(c.back()); + bool duplicate = false; + std::list::const_iterator it; + for (it = checks.begin(); it != checks.end(); ++it) + { + if (*(*it) == *c.back()) + { + duplicate = true; + countif2.erase((*it)->varId); + break; + } + } + if (!duplicate) + newchecks.push_back(c.back()); c.pop_back(); } + + // Add countif2 ids to countif.. + countif.insert(countif2.begin(), countif2.end()); } // goto "}" @@ -245,9 +278,16 @@ static void checkExecutionPaths_(const Token *tok, std::list &c } } + // Add newchecks to checks.. + std::copy(newchecks.begin(), newchecks.end(), std::back_inserter(checks)); + + // Increase numberOfIf std::list::iterator it; - for (it = newchecks.begin(); it != newchecks.end(); ++it) - checks.push_back(*it); + for (it = checks.begin(); it != checks.end(); ++it) + { + if (countif.find((*it)->varId) != countif.end()) + (*it)->numberOfIf++; + } } diff --git a/lib/executionpath.h b/lib/executionpath.h index 6be60bce1..18f54d975 100644 --- a/lib/executionpath.h +++ b/lib/executionpath.h @@ -35,11 +35,13 @@ private: void operator=(const ExecutionPath &); protected: - const unsigned int varId; Check * const owner; + /** Are two execution paths equal? */ + virtual bool is_equal(const ExecutionPath *) const = 0; + public: - ExecutionPath(Check *c, unsigned int id) : varId(id), owner(c), ifinfo(0) + ExecutionPath(Check *c, unsigned int id) : varId(id), owner(c), numberOfIf(0) { } virtual ~ExecutionPath() @@ -48,8 +50,10 @@ public: /** Implement this in each derived class. This function must create a copy of the current instance */ virtual ExecutionPath *copy() = 0; - /** Some kind of if-information */ - unsigned int ifinfo; + /** number of if blocks */ + unsigned int numberOfIf; + + const unsigned int varId; /** * bail out all execution paths @@ -109,6 +113,11 @@ public: /** going out of scope - all execution paths end */ virtual void end(const std::list & /*checks*/, const Token * /*tok*/) const { } + + bool operator==(const ExecutionPath &e) const + { + return bool(varId == e.varId && is_equal(&e)); + } }; diff --git a/test/testother.cpp b/test/testother.cpp index ee30d1ab5..970161558 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -1456,6 +1456,15 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: p\n", errout.str()); + checkUninitVar("static void foo(int x)\n" + "{\n" + " int a;\n" + " if (x==1);\n" + " if (x==2);\n" + " x = a;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: a\n", errout.str()); + checkUninitVar("int foo()\n" "{\n" " int i;\n"