From c2a15ac2869a25d6850c514ddba9ce9e413708e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 23 Jul 2015 19:01:12 +0200 Subject: [PATCH] Removed ExecutionPath --- Makefile | 6 +- cppcheck.cbp | 2 - lib/cppcheck.vcxproj | 2 - lib/cppcheck.vcxproj.filters | 6 - lib/executionpath.cpp | 491 ----------------------------------- lib/executionpath.h | 137 ---------- lib/lib.pri | 2 - 7 files changed, 1 insertion(+), 645 deletions(-) delete mode 100644 lib/executionpath.cpp delete mode 100644 lib/executionpath.h diff --git a/Makefile b/Makefile index 66ffdab5d..8ba71fb8a 100644 --- a/Makefile +++ b/Makefile @@ -144,7 +144,6 @@ LIBOBJ = $(SRCDIR)/check.o \ $(SRCDIR)/checkvaarg.o \ $(SRCDIR)/cppcheck.o \ $(SRCDIR)/errorlogger.o \ - $(SRCDIR)/executionpath.o \ $(SRCDIR)/library.o \ $(SRCDIR)/mathlib.o \ $(SRCDIR)/path.o \ @@ -343,7 +342,7 @@ $(SRCDIR)/checkpostfixoperator.o: lib/checkpostfixoperator.cpp lib/cxx11emu.h li $(SRCDIR)/checksizeof.o: lib/checksizeof.cpp lib/cxx11emu.h lib/checksizeof.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/symboldatabase.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/checksizeof.o $(SRCDIR)/checksizeof.cpp -$(SRCDIR)/checkstl.o: lib/checkstl.cpp lib/cxx11emu.h lib/checkstl.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/executionpath.h lib/symboldatabase.h lib/utils.h lib/checknullpointer.h +$(SRCDIR)/checkstl.o: lib/checkstl.cpp lib/cxx11emu.h lib/checkstl.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/symboldatabase.h lib/utils.h lib/checknullpointer.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/checkstl.o $(SRCDIR)/checkstl.cpp $(SRCDIR)/checkstring.o: lib/checkstring.cpp lib/cxx11emu.h lib/checkstring.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/symboldatabase.h lib/utils.h @@ -370,9 +369,6 @@ $(SRCDIR)/cppcheck.o: lib/cppcheck.cpp lib/cxx11emu.h lib/cppcheck.h lib/config. $(SRCDIR)/errorlogger.o: lib/errorlogger.cpp lib/cxx11emu.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/path.h lib/cppcheck.h lib/settings.h lib/library.h lib/mathlib.h lib/token.h lib/valueflow.h lib/standards.h lib/timer.h lib/check.h lib/tokenize.h lib/tokenlist.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/errorlogger.o $(SRCDIR)/errorlogger.cpp -$(SRCDIR)/executionpath.o: lib/executionpath.cpp lib/cxx11emu.h lib/executionpath.h lib/config.h lib/token.h lib/valueflow.h lib/mathlib.h lib/symboldatabase.h lib/utils.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/executionpath.o $(SRCDIR)/executionpath.cpp - $(SRCDIR)/library.o: lib/library.cpp lib/cxx11emu.h lib/library.h lib/config.h lib/mathlib.h lib/token.h lib/valueflow.h lib/path.h lib/tokenlist.h lib/symboldatabase.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/library.o $(SRCDIR)/library.cpp diff --git a/cppcheck.cbp b/cppcheck.cbp index b3a9a3790..041957fa8 100644 --- a/cppcheck.cbp +++ b/cppcheck.cbp @@ -144,8 +144,6 @@ - - diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index 6c7362bdf..ccb9e1fa9 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -65,7 +65,6 @@ - @@ -112,7 +111,6 @@ - diff --git a/lib/cppcheck.vcxproj.filters b/lib/cppcheck.vcxproj.filters index f3b851586..d68db1f03 100644 --- a/lib/cppcheck.vcxproj.filters +++ b/lib/cppcheck.vcxproj.filters @@ -65,9 +65,6 @@ Source Files - - Source Files - Source Files @@ -193,9 +190,6 @@ Header Files - - Header Files - Header Files diff --git a/lib/executionpath.cpp b/lib/executionpath.cpp deleted file mode 100644 index dd54bbc02..000000000 --- a/lib/executionpath.cpp +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2015 Daniel Marjamäki and Cppcheck team. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "executionpath.h" -#include "token.h" -#include "symboldatabase.h" -#include -#include -#include -#include - - - -// default : bail out if the condition is has variable handling -bool ExecutionPath::parseCondition(const Token &tok, std::list & checks) -{ - unsigned int parlevel = 0; - for (const Token *tok2 = &tok; tok2; tok2 = tok2->next()) { - if (tok2->str() == "(") - ++parlevel; - else if (tok2->str() == ")") { - if (parlevel == 0) - break; - --parlevel; - } else if (Token::Match(tok2, "[;{}]")) - break; - if (tok2->varId() != 0) { - 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; - } - } - - - return false; -} - - -void ExecutionPath::print() const -{ - std::cout << " varId=" << varId - << " numberOfIf=" << numberOfIf - << "\n"; -} - -// I use this function when debugging ExecutionPaths with GDB -/* -static void printchecks(const std::list &checks) -{ - for (std::list::const_iterator it = checks.begin(); it != checks.end(); ++it) - (*it)->print(); -} -*/ - - - -/** - * @brief Parse If/Switch body recursively. - * @param tok First token in body. - * @param checks The current checks - * @param newchecks new checks - * @param countif The countif set - count number of if for each execution path - */ -static void parseIfSwitchBody(const Token * const tok, - const std::list &checks, - std::list &newchecks, - std::set &countif) -{ - std::set countif2; - std::list c; - if (!checks.empty()) { - std::list::const_iterator it; - for (it = checks.begin(); it != checks.end(); ++it) { - if ((*it)->numberOfIf == 0) - c.push_back((*it)->copy()); - if ((*it)->varId != 0) - countif2.insert((*it)->varId); - } - } - ExecutionPath::checkScope(tok, c); - while (!c.empty()) { - if (c.back()->varId == 0) { - delete c.back(); - c.pop_back(); - continue; - } - - bool duplicate = false; - std::list::const_iterator it; - for (it = checks.begin(); it != checks.end(); ++it) { - if (*(*it) == *c.back() && (*it)->numberOfIf == c.back()->numberOfIf) { - duplicate = true; - countif2.erase((*it)->varId); - break; - } - } - if (!duplicate) - newchecks.push_back(c.back()); - else - delete c.back(); - c.pop_back(); - } - - // Add countif2 ids to countif.. countif. - countif.insert(countif2.begin(), countif2.end()); -} - - -void ExecutionPath::checkScope(const Token *tok, std::list &checks) -{ - if (!tok || tok->str() == "}" || checks.empty()) - return; - - const std::auto_ptr check(checks.front()->copy()); - - for (; tok; tok = tok->next()) { - // might be a noreturn function.. - if (Token::simpleMatch(tok->tokAt(-2), ") ; }") && - Token::Match(tok->linkAt(-2)->tokAt(-2), "[;{}] %name% (") && - tok->linkAt(-2)->previous()->varId() == 0) { - ExecutionPath::bailOut(checks); - return; - } - - // ({ is not handled well - if (Token::simpleMatch(tok, "( {")) { - ExecutionPath::bailOut(checks); - return; - } - - if (Token::simpleMatch(tok, "union {")) { - tok = tok->next()->link(); - continue; - } - - if (tok->str() == "}") - return; - - if (tok->str() == "break") { - ExecutionPath::bailOut(checks); - return; - } - - if (Token::simpleMatch(tok, "while (")) { - // parse condition - if (checks.size() > 10 || check->parseCondition(*tok->tokAt(2), checks)) { - ExecutionPath::bailOut(checks); - return; - } - - // skip "while (fgets()!=NULL)" - if (Token::simpleMatch(tok, "while ( fgets (")) { - const Token *tok2 = tok->linkAt(3); - if (Token::simpleMatch(tok2, ") ) {")) { - tok = tok2->linkAt(2); - if (!tok) - break; - continue; - } - } - } - - // goto/setjmp/longjmp => bailout - else if (Token::Match(tok, "goto|setjmp|longjmp")) { - ExecutionPath::bailOut(checks); - return; - } - - // ?: => bailout - if (tok->str() == "?") { - for (const Token *tok2 = tok; tok2 && tok2->str() != ";"; tok2 = tok2->next()) { - if (tok2->varId() > 0) - ExecutionPath::bailOutVar(checks, tok2->varId()); - } - } - - // for/while/switch/do .. bail out - else if (Token::Match(tok, "for|while|switch|do")) { - // goto { - const Token *tok2 = tok->next(); - if (tok2 && tok2->str() == "(") - tok2 = tok2->link(); - if (tok2 && tok2->str() == ")") - tok2 = tok2->next(); - if (!tok2 || tok2->str() != "{") { - ExecutionPath::bailOut(checks); - return; - } - - if (tok->str() == "switch") { - // parse condition - if (checks.size() > 10 || check->parseCondition(*tok->next(), checks)) { - ExecutionPath::bailOut(checks); - return; - } - - // what variable ids should the if be counted for? - std::set countif; - - std::list newchecks; - - for (const Token* tok3 = tok2->next(); tok3; tok3 = tok3->next()) { - if (tok3->str() == "{") - tok3 = tok3->link(); - else if (tok3->str() == "}") - break; - else if (tok3->str() == "case" && - !Token::Match(tok3, "case %num% : ; case")) { - parseIfSwitchBody(tok3, checks, newchecks, countif); - } - } - - // Add newchecks to checks.. - std::copy(newchecks.begin(), newchecks.end(), std::back_inserter(checks)); - - // Increase numberOfIf - std::list::iterator it; - for (it = checks.begin(); it != checks.end(); ++it) { - if (countif.find((*it)->varId) != countif.end()) - (*it)->numberOfIf++; - } - } - // no switch - else { - for (const Token *tok3 = tok; tok3 && tok3 != tok2; tok3 = tok3->next()) { - if (tok3->varId()) - ExecutionPath::bailOutVar(checks, tok3->varId()); - } - - // it is not certain that a for/while will be executed: - for (std::list::iterator it = checks.begin(); it != checks.end();) { - if ((*it)->numberOfIf > 0) { - delete *it; - checks.erase(it++); - } else - ++it; - } - - // #2231 - loop body only contains a conditional initialization.. - if (Token::simpleMatch(tok2->next(), "if (")) { - // Start { for the if block - const Token *tok3 = tok2->linkAt(2); - if (Token::simpleMatch(tok3,") {")) { - tok3 = tok3->next(); - - // End } for the if block - const Token *tok4 = tok3->link(); - if (Token::Match(tok3, "{ %name% =") && - Token::simpleMatch(tok4, "} }") && - Token::simpleMatch(tok4->tokAt(-2), "break ;")) { - // Is there a assignment and then a break? - const Token *t = Token::findsimplematch(tok3, ";"); - if (t && t->tokAt(3) == tok4) { - for (std::list::iterator it = checks.begin(); it != checks.end(); ++it) { - if ((*it)->varId == tok3->next()->varId()) { - (*it)->numberOfIf++; - break; - } - } - tok = tok2->link(); - continue; - } - } - } - } - - // parse loop bodies - check->parseLoopBody(tok2->next(), checks); - } - - // skip { .. } - tok2 = tok2->link(); - - // if "do { .. } while ( .." , goto end of while.. - if (Token::simpleMatch(tok, "do {") && Token::simpleMatch(tok2, "} while (")) - tok2 = tok2->linkAt(2); - - // bail out all variables if the scope contains a "return" - // bail out all variables used in this for/while/switch/do - for (; tok && tok != tok2; tok = tok->next()) { - if (tok->str() == "return") - ExecutionPath::bailOut(checks); - if (tok->varId()) - ExecutionPath::bailOutVar(checks, tok->varId()); - } - - continue; - } - - // bailout used variables in '; FOREACH ( .. ) { .. }' - else if (tok->str() != "if" && Token::Match(tok->previous(), "[;{}] %name% (")) { - // goto { - const Token *tok2 = tok->next()->link()->next(); - if (tok2 && tok2->str() == "{") { - // goto "}" - tok2 = tok2->link(); - - // bail out all variables used in "{ .. }" - for (; tok && tok != tok2; tok = tok->next()) { - if (tok->varId()) - ExecutionPath::bailOutVar(checks, tok->varId()); - } - if (!tok) - break; - } - } - - // .. ) { ... } => bail out - if (tok->str() == ")" && tok->next() && tok->next()->str() == "{") { - ExecutionPath::bailOut(checks); - return; - } - - if ((tok->str() == "abort" || tok->str() == "exit") && - tok->next() && tok->next()->str() == "(") { - ExecutionPath::bailOut(checks); - return; - } - - // don't parse into "struct type { .." - if (Token::Match(tok, "struct|union|class %type% {|:")) { - while (tok && tok->str() != "{" && tok->str() != ";") - tok = tok->next(); - tok = tok ? tok->link() : 0; - if (!tok) { - ExecutionPath::bailOut(checks); - return; - } - } - - if (Token::simpleMatch(tok, "= {")) { - // GCC struct initialization.. bail out - if (Token::Match(tok->tokAt(2), ". %name% =")) { - ExecutionPath::bailOut(checks); - return; - } - - const Token * const end = tok->next()->link(); - while (tok && tok != end) { - if (Token::Match(tok, "[{,] & %var% [,}]")) - ExecutionPath::bailOutVar(checks, tok->tokAt(2)->varId()); - tok = tok->next(); - } - if (!tok) { - ExecutionPath::bailOut(checks); - return; - } - continue; - } - - // ; { ... } - if (Token::Match(tok->previous(), "[;{}:] {")) { - ExecutionPath::checkScope(tok->next(), checks); - tok = tok->link(); - continue; - } - - if (tok->str() == "if" && tok->next() && tok->next()->str() == "(") { - // what variable ids should the numberOfIf be counted for? - std::set countif; - - std::list newchecks; - while (tok->str() == "if" && tok->next() && tok->next()->str() == "(") { - // goto "(" - tok = tok->next(); - - // parse condition - if (checks.size() > 10 || check->parseCondition(*tok->next(), checks)) { - ExecutionPath::bailOut(checks); - ExecutionPath::bailOut(newchecks); - return; - } - - // goto ")" - tok = tok->link(); - - // goto "{" - tok = tok->next(); - - if (!tok || tok->str() != "{") { - ExecutionPath::bailOut(checks); - ExecutionPath::bailOut(newchecks); - return; - } - - // Recursively check into the if .. - parseIfSwitchBody(tok->next(), checks, newchecks, countif); - - // goto "}" - tok = tok->link(); - - // there is no else => break out - if (!tok->next() || tok->next()->str() != "else") - break; - - // parse next "if".. - tok = tok->tokAt(2); - if (!tok) { - ExecutionPath::bailOut(newchecks); - return; - } - if (tok->str() == "if") - continue; - - // there is no "if".. - ExecutionPath::checkScope(tok->next(), checks); - tok = tok->link(); - if (!tok) { - ExecutionPath::bailOut(newchecks); - return; - } - } - - // Add newchecks to checks.. - std::copy(newchecks.begin(), newchecks.end(), std::back_inserter(checks)); - - // Increase numberOfIf - std::list::iterator it; - for (it = checks.begin(); it != checks.end(); ++it) { - if (countif.find((*it)->varId) != countif.end()) - (*it)->numberOfIf++; - } - - // Delete checks that have numberOfIf >= 2 - for (it = checks.begin(); it != checks.end();) { - if ((*it)->varId > 0 && (*it)->numberOfIf >= 2) { - delete *it; - checks.erase(it++); - } else { - ++it; - } - } - } - - tok = check->parse(*tok, checks); - if (!tok || checks.empty()) - return; - - // return/throw ends all execution paths - if (tok->str() == "return" || - tok->str() == "throw" || - tok->str() == "continue" || - tok->str() == "break") { - ExecutionPath::bailOut(checks); - } - } -} - -void checkExecutionPaths(const SymbolDatabase *symbolDatabase, ExecutionPath *c) -{ - for (std::list::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) { - if (i->type != Scope::eFunction || !i->classStart) - continue; - - // Check function - std::list checks; - checks.push_back(c->copy()); - ExecutionPath::checkScope(i->classStart, checks); - - c->end(checks, i->classEnd); - - // Cleanup - while (!checks.empty()) { - delete checks.back(); - checks.pop_back(); - } - } -} diff --git a/lib/executionpath.h b/lib/executionpath.h deleted file mode 100644 index f35dbce44..000000000 --- a/lib/executionpath.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2015 Daniel Marjamäki and Cppcheck team. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -//--------------------------------------------------------------------------- -#ifndef executionpathH -#define executionpathH -//--------------------------------------------------------------------------- - -#include -#include "config.h" - -class Token; -class Check; -class SymbolDatabase; - -/** - * Base class for Execution Paths checking - * An execution path is a linear list of statements. There are no "if"/.. to worry about. - **/ -class CPPCHECKLIB ExecutionPath { -private: - /** No implementation */ - ExecutionPath(); - ExecutionPath& operator=(const ExecutionPath &); - -protected: - Check * const owner; - - /** Are two execution paths equal? */ - virtual bool is_equal(const ExecutionPath *) const = 0; - -public: - ExecutionPath(Check *c, unsigned int id) : owner(c), numberOfIf(0), varId(id) { - } - - virtual ~ExecutionPath() { - } - - /** Implement this in each derived class. This function must create a copy of the current instance */ - virtual ExecutionPath *copy() = 0; - - /** print checkdata */ - void print() const; - - /** number of if blocks */ - unsigned int numberOfIf; - - const unsigned int varId; - - /** - * bail out all execution paths - * @param checks the execution paths to bail out on - **/ - static void bailOut(std::list &checks) { - while (!checks.empty()) { - delete checks.back(); - checks.pop_back(); - } - } - - /** - * bail out execution paths with given variable id - * @param checks the execution paths to bail out on - * @param varid the specific variable id - **/ - static void bailOutVar(std::list &checks, const unsigned int varid) { - if (varid == 0) - return; - - std::list::iterator it = checks.begin(); - while (it != checks.end()) { - if ((*it)->varId == varid) { - delete *it; - checks.erase(it++); - } else { - ++it; - } - } - } - - /** - * Parse tokens at given location - * @param tok token to parse - * @param checks The execution paths. All execution paths in the list are executed in the current scope. - * @return the token before the "next" token. - **/ - virtual const Token *parse(const Token &tok, std::list &checks) const = 0; - - /** - * Parse condition - * @param tok first token in condition. - * @param checks The execution paths. All execution paths in the list are executed in the current scope - * @return true => bail out all checking - **/ - virtual bool parseCondition(const Token &tok, std::list &checks); - - /** - * Parse loop body - * @param tok the first token in the loop body (the token after the {) - * @param checks The execution paths - */ - virtual void parseLoopBody(const Token *tok, std::list &checks) const { - (void)tok; - (void)checks; - } - - /** 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)); - } - - static void checkScope(const Token *tok, std::list &checks); -}; - - -void checkExecutionPaths(const SymbolDatabase *symbolDatabase, ExecutionPath *c); - -//--------------------------------------------------------------------------- -#endif // executionpathH diff --git a/lib/lib.pri b/lib/lib.pri index aac8fd73e..bd71969b9 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -35,7 +35,6 @@ HEADERS += $${BASEPATH}check.h \ $${BASEPATH}checkvaarg.h \ $${BASEPATH}cppcheck.h \ $${BASEPATH}errorlogger.h \ - $${BASEPATH}executionpath.h \ $${BASEPATH}library.h \ $${BASEPATH}mathlib.h \ $${BASEPATH}path.h \ @@ -80,7 +79,6 @@ SOURCES += $${BASEPATH}check.cpp \ $${BASEPATH}checkvaarg.cpp \ $${BASEPATH}cppcheck.cpp \ $${BASEPATH}errorlogger.cpp \ - $${BASEPATH}executionpath.cpp \ $${BASEPATH}library.cpp \ $${BASEPATH}mathlib.cpp \ $${BASEPATH}path.cpp \