From 8eb92001b393c2047a8b0f21529c1f9d25ad996e Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Wed, 2 Feb 2011 07:40:08 +0100 Subject: [PATCH 01/40] Fixed #2530 (Tokenizer: Remove redundant 'MyClass::' inside MyClass class declaration) --- lib/tokenize.cpp | 60 +++++++++++++++++++++++++++++++++++++ lib/tokenize.h | 5 ++++ test/testsimplifytokens.cpp | 10 +++++++ 3 files changed, 75 insertions(+) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 4c57f4016..8cc0b6945 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2382,6 +2382,9 @@ bool Tokenizer::tokenize(std::istream &code, // remove __attribute__((?)) simplifyAttribute(); + // remove unnecessary member qualification.. + removeUnnecessaryQualification(); + // remove Microsoft MFC.. simplifyMicrosoftMFC(); @@ -9325,3 +9328,60 @@ void Tokenizer::simplifyOperatorName() } } } + +// remove unnecessary member qualification.. +struct ClassInfo +{ + std::string className; + Token *end; +}; + +void Tokenizer::removeUnnecessaryQualification() +{ + std::stack classInfo; + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (Token::Match(tok, "class|struct %type% :|{")) + { + tok = tok->next(); + ClassInfo info; + info.className = tok->str(); + tok = tok->next(); + while (tok && tok->str() != "{") + tok = tok->next(); + if (!tok) + return; + info.end = tok->link(); + classInfo.push(info); + } + else if (!classInfo.empty()) + { + if (tok == classInfo.top().end) + classInfo.pop(); + else if (tok->str() == classInfo.top().className && + Token::Match(tok, "%type% :: %type% (") && + Token::Match(tok->tokAt(3)->link(), ") const| {|;")) + { + std::list locationList; + ErrorLogger::ErrorMessage::FileLocation loc; + loc.line = tok->linenr(); + loc.setfile(file(tok)); + locationList.push_back(loc); + + const ErrorLogger::ErrorMessage errmsg(locationList, + Severity::portability, + "Extra qualification \'" + tok->str() + "::\' unnecessary and considered an error by many compilers.", + "portability"); + + if (_errorLogger) + _errorLogger->reportErr(errmsg); + else + Check::reportError(errmsg); + + tok->deleteThis(); + tok->deleteThis(); + } + } + } +} + diff --git a/lib/tokenize.h b/lib/tokenize.h index 5662d7843..e9a280698 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -519,6 +519,11 @@ public: */ void simplifyBuiltinExpect(); + /** + * Remove unnecessary member qualification + */ + void removeUnnecessaryQualification(); + /** * Remove Microsoft MFC 'DECLARE_MESSAGE_MAP()' */ diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index e298bcfd0..9ba7bc197 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -315,6 +315,8 @@ private: TEST_CASE(redundant_semicolon); TEST_CASE(simplifyFunctionReturn); + + TEST_CASE(removeUnnecessaryQualification); } std::string tok(const char code[], bool simplify = true) @@ -6408,6 +6410,14 @@ private: "} ;"; ASSERT_EQUALS(expected, tok(code, false)); } + + void removeUnnecessaryQualification() + { + const char code[] = "class Fred { Fred::Fred() {} };"; + const char expected[] = "class Fred { Fred ( ) { } } ;"; + ASSERT_EQUALS(expected, tok(code, false)); + ASSERT_EQUALS("[test.cpp:1]: (portability) Extra qualification 'Fred::' unnecessary and considered an error by many compilers.\n", errout.str()); + } }; REGISTER_TEST(TestSimplifyTokens) From c3ad3f78e90e24674137cfe685b21e0a920321f6 Mon Sep 17 00:00:00 2001 From: Greg Hewgill Date: Wed, 2 Feb 2011 21:57:08 +1300 Subject: [PATCH 02/40] test case to check whether instances are sorted --- test/testcppcheck.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/testcppcheck.cpp b/test/testcppcheck.cpp index af6e33883..3aaff3c35 100644 --- a/test/testcppcheck.cpp +++ b/test/testcppcheck.cpp @@ -66,9 +66,21 @@ private: void run() { + TEST_CASE(instancesSorted); TEST_CASE(getErrorMessages); } + void instancesSorted() + { + for (std::list::iterator i = Check::instances().begin(); i != Check::instances().end(); ++i) { + std::list::iterator j = i; + ++j; + if (j != Check::instances().end()) { + ASSERT_EQUALS(true, (*i)->name() < (*j)->name()); + } + } + } + void getErrorMessages() { ErrorLogger2 errorLogger; From be195a72c97122c5685e818ea612e6e577141761 Mon Sep 17 00:00:00 2001 From: Greg Hewgill Date: Wed, 2 Feb 2011 22:29:10 +1300 Subject: [PATCH 03/40] initialise Check::_name in constructor rather than relying on virtual Check::name() --- lib/check.h | 14 +++++++++----- lib/checkautovariables.h | 6 +++--- lib/checkbufferoverrun.h | 6 +++--- lib/checkclass.cpp | 2 +- lib/checkclass.h | 4 ++-- lib/checkexceptionsafety.h | 6 +++--- lib/checkmemoryleak.h | 24 ++++++++++++------------ lib/checknullpointer.h | 6 +++--- lib/checkobsoletefunctions.h | 6 +++--- lib/checkother.h | 6 +++--- lib/checkpostfixoperator.h | 6 +++--- lib/checkstl.h | 6 +++--- lib/checkuninitvar.h | 6 +++--- lib/checkunusedfunctions.h | 6 +++--- 14 files changed, 54 insertions(+), 50 deletions(-) diff --git a/lib/check.h b/lib/check.h index c11eb8f5d..f5e5d6370 100644 --- a/lib/check.h +++ b/lib/check.h @@ -39,16 +39,16 @@ class Check { public: /** This constructor is used when registering the CheckClass */ - Check() - : _tokenizer(0), _settings(0), _errorLogger(0) + Check(const std::string &aname) + : _name(aname), _tokenizer(0), _settings(0), _errorLogger(0) { instances().push_back(this); instances().sort(); } /** This constructor is used when running checks. */ - Check(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : _tokenizer(tokenizer), _settings(settings), _errorLogger(errorLogger) + Check(const std::string &aname, const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) + : _name(aname), _tokenizer(tokenizer), _settings(settings), _errorLogger(errorLogger) { } virtual ~Check() @@ -98,7 +98,10 @@ public: virtual void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) = 0; /** class name, used to generate documentation */ - virtual std::string name() const = 0; + std::string name() const + { + return _name; + } /** get information about this class, used to generate documentation */ virtual std::string classInfo() const = 0; @@ -114,6 +117,7 @@ public: } protected: + const std::string _name; const Tokenizer * const _tokenizer; const Settings * const _settings; ErrorLogger * const _errorLogger; diff --git a/lib/checkautovariables.h b/lib/checkautovariables.h index 97df17ccf..a1faf1450 100644 --- a/lib/checkautovariables.h +++ b/lib/checkautovariables.h @@ -34,12 +34,12 @@ class CheckAutoVariables : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckAutoVariables() : Check() + CheckAutoVariables() : Check(myName()) { } /** This constructor is used when running checks. */ CheckAutoVariables(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(tokenizer, settings, errorLogger) + : Check(myName(), tokenizer, settings, errorLogger) { } void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) @@ -98,7 +98,7 @@ private: c.errorReturnTempPointer(0); } - std::string name() const + std::string myName() const { return "Auto Variables"; } diff --git a/lib/checkbufferoverrun.h b/lib/checkbufferoverrun.h index c2e77a20b..fe8ca2645 100644 --- a/lib/checkbufferoverrun.h +++ b/lib/checkbufferoverrun.h @@ -50,12 +50,12 @@ class CheckBufferOverrun : public Check public: /** This constructor is used when registering the CheckClass */ - CheckBufferOverrun() : Check() + CheckBufferOverrun() : Check(myName()) { } /** This constructor is used when running checks. */ CheckBufferOverrun(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(tokenizer, settings, errorLogger) + : Check(myName(), tokenizer, settings, errorLogger) { } void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) @@ -209,7 +209,7 @@ public: c.pointerOutOfBounds(0, "array"); } - std::string name() const + std::string myName() const { return "Bounds checking"; } diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index fc96af0cc..0991e795f 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -42,7 +42,7 @@ CheckClass instance; //--------------------------------------------------------------------------- CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(tokenizer, settings, errorLogger), + : Check(myName(), tokenizer, settings, errorLogger), symbolDatabase(NULL) { diff --git a/lib/checkclass.h b/lib/checkclass.h index dd5f15883..cc550c36b 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -36,7 +36,7 @@ class CheckClass : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckClass() : Check(), symbolDatabase(NULL) + CheckClass() : Check(myName()), symbolDatabase(NULL) { } /** @brief This constructor is used when running checks. */ @@ -144,7 +144,7 @@ private: c.checkConstError(0, "class", "function"); } - std::string name() const + std::string myName() const { return "Class"; } diff --git a/lib/checkexceptionsafety.h b/lib/checkexceptionsafety.h index 584cf78d6..af92597f5 100644 --- a/lib/checkexceptionsafety.h +++ b/lib/checkexceptionsafety.h @@ -43,12 +43,12 @@ class CheckExceptionSafety : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckExceptionSafety() : Check() + CheckExceptionSafety() : Check(myName()) { } /** This constructor is used when running checks. */ CheckExceptionSafety(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(tokenizer, settings, errorLogger) + : Check(myName(), tokenizer, settings, errorLogger) { } /** Checks that uses the simplified token list */ @@ -86,7 +86,7 @@ private: } /** Short description of class (for --doc) */ - std::string name() const + std::string myName() const { return "Exception Safety"; } diff --git a/lib/checkmemoryleak.h b/lib/checkmemoryleak.h index d535ea4cb..7ba6a53b4 100644 --- a/lib/checkmemoryleak.h +++ b/lib/checkmemoryleak.h @@ -172,12 +172,12 @@ class CheckMemoryLeakInFunction : private Check, public CheckMemoryLeak { public: /** @brief This constructor is used when registering this class */ - CheckMemoryLeakInFunction() : Check(), CheckMemoryLeak(0, 0), symbolDatabase(NULL) + CheckMemoryLeakInFunction() : Check(myName()), CheckMemoryLeak(0, 0), symbolDatabase(NULL) { } /** @brief This constructor is used when running checks */ CheckMemoryLeakInFunction(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) - : Check(tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog) + : Check(myName(), tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog) { // get the symbol database if (tokenizr) @@ -329,7 +329,7 @@ public: * Get name of class (--doc) * @return name of class */ - std::string name() const + std::string myName() const { return "Memory leaks (function variables)"; } @@ -364,11 +364,11 @@ public: class CheckMemoryLeakInClass : private Check, private CheckMemoryLeak { public: - CheckMemoryLeakInClass() : Check(), CheckMemoryLeak(0, 0) + CheckMemoryLeakInClass() : Check(myName()), CheckMemoryLeak(0, 0) { } CheckMemoryLeakInClass(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) - : Check(tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog) + : Check(myName(), tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog) { } void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) @@ -396,7 +396,7 @@ private: void getErrorMessages(ErrorLogger * /*errorLogger*/, const Settings * /*settings*/) { } - std::string name() const + std::string myName() const { return "Memory leaks (class variables)"; } @@ -414,11 +414,11 @@ private: class CheckMemoryLeakStructMember : private Check, private CheckMemoryLeak { public: - CheckMemoryLeakStructMember() : Check(), CheckMemoryLeak(0, 0) + CheckMemoryLeakStructMember() : Check(myName()), CheckMemoryLeak(0, 0) { } CheckMemoryLeakStructMember(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) - : Check(tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog) + : Check(myName(), tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog) { } void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) @@ -434,7 +434,7 @@ private: void getErrorMessages(ErrorLogger * /*errorLogger*/, const Settings * /*settings*/) { } - std::string name() const + std::string myName() const { return "Memory leaks (struct members)"; } @@ -452,11 +452,11 @@ private: class CheckMemoryLeakNoVar : private Check, private CheckMemoryLeak { public: - CheckMemoryLeakNoVar() : Check(), CheckMemoryLeak(0, 0) + CheckMemoryLeakNoVar() : Check(myName()), CheckMemoryLeak(0, 0) { } CheckMemoryLeakNoVar(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) - : Check(tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog) + : Check(myName(), tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog) { } void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) @@ -474,7 +474,7 @@ private: void getErrorMessages(ErrorLogger * /*errorLogger*/, const Settings * /*settings*/) { } - std::string name() const + std::string myName() const { return "Memory leaks (address not taken)"; } diff --git a/lib/checknullpointer.h b/lib/checknullpointer.h index c1b134e91..1f23bcf87 100644 --- a/lib/checknullpointer.h +++ b/lib/checknullpointer.h @@ -37,12 +37,12 @@ class CheckNullPointer : public Check { public: /** @brief This constructor is used when registering the CheckNullPointer */ - CheckNullPointer() : Check() + CheckNullPointer() : Check(myName()) { } /** @brief This constructor is used when running checks. */ CheckNullPointer(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(tokenizer, settings, errorLogger) + : Check(myName(), tokenizer, settings, errorLogger) { } /** @brief Run checks against the normal token list */ @@ -112,7 +112,7 @@ public: } /** Name of check */ - std::string name() const + std::string myName() const { return "Null pointer"; } diff --git a/lib/checkobsoletefunctions.h b/lib/checkobsoletefunctions.h index 3ee4f88f3..706803aa8 100644 --- a/lib/checkobsoletefunctions.h +++ b/lib/checkobsoletefunctions.h @@ -38,14 +38,14 @@ class CheckObsoleteFunctions : public Check { public: /** This constructor is used when registering the CheckObsoleteFunctions */ - CheckObsoleteFunctions() : Check() + CheckObsoleteFunctions() : Check(myName()) { initObsoleteFunctions(); } /** This constructor is used when running checks. */ CheckObsoleteFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(tokenizer, settings, errorLogger) + : Check(myName(), tokenizer, settings, errorLogger) { initObsoleteFunctions(); } @@ -125,7 +125,7 @@ private: } } - std::string name() const + std::string myName() const { return "Obsolete functions"; } diff --git a/lib/checkother.h b/lib/checkother.h index bace5a82e..bc5b1db35 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -37,12 +37,12 @@ class CheckOther : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckOther() : Check() + CheckOther() : Check(myName()) { } /** @brief This constructor is used when running checks. */ CheckOther(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(tokenizer, settings, errorLogger) + : Check(myName(), tokenizer, settings, errorLogger) { } /** @brief Run checks against the normal token list */ @@ -245,7 +245,7 @@ public: c.clarifyCalculationError(0); } - std::string name() const + std::string myName() const { return "Other"; } diff --git a/lib/checkpostfixoperator.h b/lib/checkpostfixoperator.h index 2840df19e..e7e4651fb 100644 --- a/lib/checkpostfixoperator.h +++ b/lib/checkpostfixoperator.h @@ -35,12 +35,12 @@ class CheckPostfixOperator : public Check { public: /** This constructor is used when registering the CheckPostfixOperator */ - CheckPostfixOperator() : Check() + CheckPostfixOperator() : Check(myName()) { } /** This constructor is used when running checks. */ CheckPostfixOperator(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(tokenizer, settings, errorLogger) + : Check(myName(), tokenizer, settings, errorLogger) { } void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) @@ -62,7 +62,7 @@ private: c.postfixOperatorError(0); } - std::string name() const + std::string myName() const { return "Using postfix operators"; } diff --git a/lib/checkstl.h b/lib/checkstl.h index e232eedcd..ebd6938b1 100644 --- a/lib/checkstl.h +++ b/lib/checkstl.h @@ -35,12 +35,12 @@ class CheckStl : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckStl() : Check() + CheckStl() : Check(myName()) { } /** This constructor is used when running checks. */ CheckStl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(tokenizer, settings, errorLogger) + : Check(myName(), tokenizer, settings, errorLogger) { } /** Simplified checks. The token list is simplified. */ @@ -173,7 +173,7 @@ private: c.redundantIfRemoveError(0); } - std::string name() const + std::string myName() const { return "STL usage"; } diff --git a/lib/checkuninitvar.h b/lib/checkuninitvar.h index 78465d821..8ab4844ed 100644 --- a/lib/checkuninitvar.h +++ b/lib/checkuninitvar.h @@ -37,12 +37,12 @@ class CheckUninitVar : public Check { public: /** @brief This constructor is used when registering the CheckUninitVar */ - CheckUninitVar() : Check() + CheckUninitVar() : Check(myName()) { } /** @brief This constructor is used when running checks. */ CheckUninitVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(tokenizer, settings, errorLogger) + : Check(myName(), tokenizer, settings, errorLogger) { } /** @brief Run checks against the normal token list */ @@ -87,7 +87,7 @@ public: c.uninitvarError(0, "varname"); } - std::string name() const + std::string myName() const { return "Uninitialized variables"; } diff --git a/lib/checkunusedfunctions.h b/lib/checkunusedfunctions.h index 066faafd6..6d408bcdb 100644 --- a/lib/checkunusedfunctions.h +++ b/lib/checkunusedfunctions.h @@ -33,12 +33,12 @@ class CheckUnusedFunctions: public Check { public: /** @brief This constructor is used when registering the CheckUnusedFunctions */ - CheckUnusedFunctions() : Check() + CheckUnusedFunctions() : Check(myName()) { } /** @brief This constructor is used when running checks. */ CheckUnusedFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(tokenizer, settings, errorLogger) + : Check(myName(), tokenizer, settings, errorLogger) { } // Parse current tokens and determine.. @@ -69,7 +69,7 @@ private: } - std::string name() const + std::string myName() const { return "Unused functions"; } From bea36d1f83fea4035b9b4140144661945493feec Mon Sep 17 00:00:00 2001 From: Greg Hewgill Date: Wed, 2 Feb 2011 22:56:14 +1300 Subject: [PATCH 04/40] use instances of less to compare pointers for list::sort() --- lib/check.h | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/check.h b/lib/check.h index f5e5d6370..c6e2bfa25 100644 --- a/lib/check.h +++ b/lib/check.h @@ -39,12 +39,7 @@ class Check { public: /** This constructor is used when registering the CheckClass */ - Check(const std::string &aname) - : _name(aname), _tokenizer(0), _settings(0), _errorLogger(0) - { - instances().push_back(this); - instances().sort(); - } + Check(const std::string &aname); /** This constructor is used when running checks. */ Check(const std::string &aname, const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) @@ -159,17 +154,28 @@ protected: private: - /** compare the names of Check classes, used when sorting the Check descendants */ - bool operator<(const Check *other) const - { - return (name() < other->name()); - } - /** disabled assignment operator */ void operator=(const Check &); }; +namespace std { + /** compare the names of Check classes, used when sorting the Check descendants */ + template <> struct less { + bool operator()(const Check *p1, const Check *p2) const + { + return (p1->name() < p2->name()); + } + }; +} + +inline Check::Check(const std::string &aname) + : _name(aname), _tokenizer(0), _settings(0), _errorLogger(0) +{ + instances().push_back(this); + instances().sort(std::less()); +} + /// @} #endif From fe57d50328878bd71bf01f796b7fb88400731122 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Wed, 2 Feb 2011 13:28:14 +0200 Subject: [PATCH 05/40] Expose --xml-version=version cmd line option. Make the --xml-version=version command line option public by adding it to the command line help. --- cli/cmdlineparser.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index c3eaa5764..46e26703d 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -608,6 +608,9 @@ void CmdLineParser::PrintHelp() " -v, --verbose More detailed error reports\n" " --version Print out version number\n" " --xml Write results in xml to error stream.\n" + " --xml-version=[version]\n" + " Select the XML file version. Currently versions 1 and 2\n" + " are available. The default version is 1." "\n" "Example usage:\n" " # Recursively check the current folder. Print the progress on the screen and\n" From 1118b132b962fa79efc243d21636b9bddea520f8 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Wed, 2 Feb 2011 13:33:57 +0200 Subject: [PATCH 06/40] =?UTF-8?q?Add=20couple=20of=20tests=20for=20xml-ver?= =?UTF-8?q?sion=20cmd=C2=A0line=20option.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/testcmdlineparser.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 009be82f0..8ab68a941 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -84,6 +84,8 @@ private: TEST_CASE(xmlver2); TEST_CASE(xmlver2both); TEST_CASE(xmlver2both2); + TEST_CASE(xmlverunknown); + TEST_CASE(xmlverinvalid); TEST_CASE(errorlist1); TEST_CASE(errorlistverbose1) TEST_CASE(errorlistverbose2) @@ -618,6 +620,24 @@ private: ASSERT_EQUALS(2, settings._xml_version); } + void xmlverunknown() + { + REDIRECT; + const char *argv[] = {"cppcheck", "--xml", "--xml-version=3", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(!parser.ParseFromArgs(4, argv)); + } + + void xmlverinvalid() + { + REDIRECT; + const char *argv[] = {"cppcheck", "--xml", "--xml-version=a", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(!parser.ParseFromArgs(4, argv)); + } + void errorlist1() { REDIRECT; From 1da88de93243680676a9e9aba27924ca0d87ba9e Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Wed, 2 Feb 2011 14:04:50 +0200 Subject: [PATCH 07/40] Imrove --xml-version option parsing. Allow --xml-version parsing to recognize also version 1 and print errors about invalid values. --- cli/cmdlineparser.cpp | 23 ++++++++++++++++++++--- test/testcmdlineparser.cpp | 12 ++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 46e26703d..9c1bf264f 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -210,11 +210,28 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) else if (strcmp(argv[i], "--xml") == 0) _settings->_xml = true; - // Write results in xml2 format - else if (strcmp(argv[i], "--xml-version=2") == 0) + // Define the XML file version (and enable XML output) + else if (strncmp(argv[i], "--xml-version=", 14) == 0) { + std::string numberString(argv[i]); + numberString = numberString.substr(14); + + std::istringstream iss(numberString); + if (!(iss >> _settings->_xml_version)) + { + PrintMessage("cppcheck: argument to '--xml-version' is not a number"); + return false; + } + + if (_settings->_xml_version < 0 || _settings->_xml_version > 2) + { + // We only have xml versions 1 and 2 + PrintMessage("cppcheck: --xml-version can only be 1 or 2."); + return false; + } + + // Enable also XML if version is set _settings->_xml = true; - _settings->_xml_version = 2; } // Only print something when there are errors diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 8ab68a941..ec9561b15 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -81,6 +81,7 @@ private: TEST_CASE(templatesGcc); TEST_CASE(templatesVs); TEST_CASE(xml); + TEST_CASE(xmlver1); TEST_CASE(xmlver2); TEST_CASE(xmlver2both); TEST_CASE(xmlver2both2); @@ -587,6 +588,17 @@ private: ASSERT_EQUALS(1, settings._xml_version); } + void xmlver1() + { + REDIRECT; + const char *argv[] = {"cppcheck", "--xml-version=1", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(parser.ParseFromArgs(3, argv)); + ASSERT(settings._xml); + ASSERT_EQUALS(1, settings._xml_version); + } + void xmlver2() { REDIRECT; From 6401271ceb85ff93a697b2c09fb4765a560fb7a3 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Mon, 31 Jan 2011 15:25:51 +0200 Subject: [PATCH 08/40] Add CLI support for ignoring paths. Add support for giving list of ignored paths from CLI. This way user can define paths one doesn't want to check (like generated code). This first simple implementation only does exact matching, no support for wildcards etc. And matching is always agains dir names. If the filtered dir name is part of the checked filename then the file is ignored. Ticket #1690 (Ability to exclude files and directories from checks) --- cli/cli.pro | 3 + cli/cmdlineparser.cpp | 38 +++++++++ cli/cmdlineparser.h | 9 +++ cli/cppcheckexecutor.cpp | 31 ++++++-- cli/pathmatch.cpp | 45 +++++++++++ cli/pathmatch.h | 63 +++++++++++++++ test/test.pro | 150 ++++++++++++++++++----------------- test/testcmdlineparser.cpp | 61 ++++++++++++++ test/testpathmatch.cpp | 158 +++++++++++++++++++++++++++++++++++++ 9 files changed, 480 insertions(+), 78 deletions(-) create mode 100644 cli/pathmatch.cpp create mode 100644 cli/pathmatch.h create mode 100644 test/testpathmatch.cpp diff --git a/cli/cli.pro b/cli/cli.pro index 85702b9fb..e04e4e158 100644 --- a/cli/cli.pro +++ b/cli/cli.pro @@ -17,12 +17,15 @@ SOURCES += main.cpp \ filelister.cpp \ filelister_unix.cpp \ filelister_win32.cpp \ + pathmatch.cpp \ threadexecutor.cpp + HEADERS += cppcheckexecutor.h \ cmdlineparser.h \ filelister.h \ filelister_unix.h \ filelister_win32.h \ + pathmatch.h \ threadexecutor.h CONFIG(release, debug|release) { diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index c3eaa5764..340ca5ae0 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -327,6 +327,41 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) AddFilesToList(12 + argv[i], _pathnames); } + // Ignored paths + else if (strncmp(argv[i], "-i", 2) == 0) + { + std::string path; + + // "-i path/" + if (strcmp(argv[i], "-i") == 0) + { + ++i; + if (i >= argc) + { + PrintMessage("cppcheck: argument to '-i' is missing"); + return false; + } + path = argv[i]; + } + + // "-Ipath/" + else + { + path = 2 + argv[i]; + } + + if (!path.empty()) + { + path = Path::fromNativeSeparators(path); + + // If path doesn't end with / or \, add it + if (path[path.length()-1] != '/') + path += '/'; + + _ignoredPaths.push_back(path); + } + } + // Report progress else if (strcmp(argv[i], "--report-progress") == 0) { @@ -589,6 +624,9 @@ void CmdLineParser::PrintHelp() " -I [dir] Give include path. Give several -I parameters to give\n" " several paths. First given path is checked first. If\n" " paths are relative to source files, this is not needed\n" + " -i [dir] Give path to ignore. Give several -i parameters to ignore\n" + " several paths. If any part of the checked path matches the\n" + " given dir the path is ignored and not checked.\n" " --inline-suppr Enable inline suppressions. Use them by placing one or\n" " more comments, like: // cppcheck-suppress warningId\n" " on the lines before the warning to suppress.\n" diff --git a/cli/cmdlineparser.h b/cli/cmdlineparser.h index 7a60e24a6..bfc047cb9 100644 --- a/cli/cmdlineparser.h +++ b/cli/cmdlineparser.h @@ -92,6 +92,14 @@ public: return _exitAfterPrint; } + /** + * Return a list of paths user wants to ignore. + */ + std::vector GetIgnoredPaths() const + { + return _ignoredPaths; + } + protected: /** @@ -111,6 +119,7 @@ private: bool _showErrorMessages; bool _exitAfterPrint; std::vector _pathnames; + std::vector _ignoredPaths; }; /// @} diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index fdb886471..de1756d3f 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -25,6 +25,7 @@ #include "cmdlineparser.h" #include "filelister.h" #include "path.h" +#include "pathmatch.h" CppCheckExecutor::CppCheckExecutor() { @@ -87,19 +88,39 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c std::vector::const_iterator iter; for (iter = pathnames.begin(); iter != pathnames.end(); ++iter) getFileLister()->recursiveAddFiles(filenames, Path::toNativeSeparators(iter->c_str())); - - for (iter = filenames.begin(); iter != filenames.end(); ++iter) - cppcheck->addFile(*iter); } - if (filenames.empty()) + if (!filenames.empty()) + { + PathMatch matcher(parser.GetIgnoredPaths()); + // Ignore files + std::vector::iterator iter = filenames.end(); + do + { + --iter; + if (matcher.Match(*iter)) + filenames.erase(iter); + } + while (iter != filenames.begin()); + } + else { std::cout << "cppcheck: error: could not find or open any of the paths given." << std::endl; return false; } + + if (!filenames.empty()) + { + std::vector::iterator iter; + for (iter = filenames.begin(); iter != filenames.end(); ++iter) + cppcheck->addFile(*iter); + + return true; + } else { - return true; + std::cout << "cppcheck: error: no files to check - all paths ignored." << std::endl; + return false; } } diff --git a/cli/pathmatch.cpp b/cli/pathmatch.cpp new file mode 100644 index 000000000..115b34d5a --- /dev/null +++ b/cli/pathmatch.cpp @@ -0,0 +1,45 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2011 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 "pathmatch.h" + +PathMatch::PathMatch(const std::vector &masks) + : _masks(masks) +{ +} + +bool PathMatch::Match(const std::string &path) +{ + std::vector::const_iterator iterMask; + for (iterMask = _masks.begin(); iterMask != _masks.end(); ++iterMask) + { + std::string findpath(path); + if (findpath[findpath.length() - 1] != '/') + findpath = RemoveFilename(findpath); + + if (findpath.find(*iterMask) != std::string::npos) + return true; + } + return false; +} + +std::string PathMatch::RemoveFilename(const std::string &path) +{ + const size_t ind = path.find_last_of('/'); + return path.substr(0, ind + 1); +} diff --git a/cli/pathmatch.h b/cli/pathmatch.h new file mode 100644 index 000000000..5e1a0566c --- /dev/null +++ b/cli/pathmatch.h @@ -0,0 +1,63 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2011 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 PATHMATCH_H +#define PATHMATCH_H + +#include +#include + +/// @addtogroup CLI +/// @{ + +/** + * @brief Simple path matching for ignoring paths in CLI. + */ +class PathMatch +{ +public: + + /** + * The constructor. + * @param masks List of masks. + */ + PathMatch(const std::vector &masks); + + /** + * @brief Match path against list of masks. + * @param path Path to match. + * @return true if any of the masks match the path, false otherwise. + */ + bool Match(const std::string &path); + +protected: + + /** + * @brief Remove filename part from the path. + * @param path Path to edit. + * @return path without filename part. + */ + std::string RemoveFilename(const std::string &path); + +private: + std::vector _masks; +}; + +/// @} + +#endif // PATHMATCH_H diff --git a/test/test.pro b/test/test.pro index 0196222ed..b786428cf 100644 --- a/test/test.pro +++ b/test/test.pro @@ -1,73 +1,77 @@ - -TEMPLATE = app -TARGET = test -DEPENDPATH += . -INCLUDEPATH += . ../cli ../lib -OBJECTS_DIR = temp -CONFIG += warn_on console -CONFIG -= qt app_bundle -win32 { - LIBS += -lshlwapi -} - -BASEPATH = ../externals/tinyxml/ -include(../externals/tinyxml/tinyxml.pri) -BASEPATH = ../lib/ -include(../lib/lib.pri) - -# cli/* -SOURCES += ../cli/cmdlineparser.cpp \ - ../cli/cppcheckexecutor.cpp \ - ../cli/filelister.cpp \ - ../cli/filelister_unix.cpp \ - ../cli/filelister_win32.cpp \ - ../cli/threadexecutor.cpp -HEADERS += ../cli/cmdlineparser.h \ - ../cli/cppcheckexecutor.h \ - ../cli/filelister.h \ - ../cli/filelister_unix.h \ - ../cli/filelister_win32.h \ - ../cli/threadexecutor.h - -# test/* -HEADERS += options.h redirect.h testsuite.h -SOURCES += options.cpp \ - testautovariables.cpp \ - testbufferoverrun.cpp \ - testcharvar.cpp \ - testclass.cpp \ - testcmdlineparser.cpp \ - testconstructors.cpp \ - testcppcheck.cpp \ - testdivision.cpp \ - testerrorlogger.cpp \ - testexceptionsafety.cpp \ - testincompletestatement.cpp \ - testmathlib.cpp \ - testmemleak.cpp \ - testnullpointer.cpp \ - testobsoletefunctions.cpp \ - testoptions.cpp \ - testother.cpp \ - testpath.cpp \ - testpostfixoperator.cpp \ - testpreprocessor.cpp \ - testrunner.cpp \ - testsettings.cpp \ - testsimplifytokens.cpp \ - teststl.cpp \ - testsuite.cpp \ - testthreadexecutor.cpp \ - testtoken.cpp \ - testtokenize.cpp \ - testuninitvar.cpp \ - testunusedfunctions.cpp \ - testunusedprivfunc.cpp \ - testunusedvar.cpp - -# Change Visual Studio compiler (CL) warning level to W4 -contains(QMAKE_CXX, cl) { - QMAKE_CXXFLAGS_WARN_ON -= -W3 - QMAKE_CXXFLAGS_WARN_ON += -W4 - DEFINES += _CRT_SECURE_NO_WARNINGS -} + +TEMPLATE = app +TARGET = test +DEPENDPATH += . +INCLUDEPATH += . ../cli ../lib +OBJECTS_DIR = temp +CONFIG += warn_on console +CONFIG -= qt app_bundle +win32 { + LIBS += -lshlwapi +} + +BASEPATH = ../externals/tinyxml/ +include(../externals/tinyxml/tinyxml.pri) +BASEPATH = ../lib/ +include(../lib/lib.pri) + +# cli/* +SOURCES += ../cli/cmdlineparser.cpp \ + ../cli/cppcheckexecutor.cpp \ + ../cli/filelister.cpp \ + ../cli/filelister_unix.cpp \ + ../cli/filelister_win32.cpp \ + ../cli/pathmatch.cpp \ + ../cli/threadexecutor.cpp \ + testpathmatch.cpp +HEADERS += ../cli/cmdlineparser.h \ + ../cli/cppcheckexecutor.h \ + ../cli/filelister.h \ + ../cli/filelister_unix.h \ + ../cli/filelister_win32.h \ + ../cli/pathmatch.h \ + ../cli/threadexecutor.h + +# test/* +HEADERS += options.h redirect.h testsuite.h +SOURCES += options.cpp \ + testautovariables.cpp \ + testbufferoverrun.cpp \ + testcharvar.cpp \ + testclass.cpp \ + testcmdlineparser.cpp \ + testconstructors.cpp \ + testcppcheck.cpp \ + testdivision.cpp \ + testerrorlogger.cpp \ + testexceptionsafety.cpp \ + testincompletestatement.cpp \ + testmathlib.cpp \ + testmemleak.cpp \ + testnullpointer.cpp \ + testobsoletefunctions.cpp \ + testoptions.cpp \ + testother.cpp \ + testpath.cpp \ + testpathmatch.cpp \ + testpostfixoperator.cpp \ + testpreprocessor.cpp \ + testrunner.cpp \ + testsettings.cpp \ + testsimplifytokens.cpp \ + teststl.cpp \ + testsuite.cpp \ + testthreadexecutor.cpp \ + testtoken.cpp \ + testtokenize.cpp \ + testuninitvar.cpp \ + testunusedfunctions.cpp \ + testunusedprivfunc.cpp \ + testunusedvar.cpp + +# Change Visual Studio compiler (CL) warning level to W4 +contains(QMAKE_CXX, cl) { + QMAKE_CXXFLAGS_WARN_ON -= -W3 + QMAKE_CXXFLAGS_WARN_ON += -W4 + DEFINES += _CRT_SECURE_NO_WARNINGS +} diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 009be82f0..f030ffa1f 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -87,6 +87,11 @@ private: TEST_CASE(errorlist1); TEST_CASE(errorlistverbose1) TEST_CASE(errorlistverbose2) + TEST_CASE(ignorepathsnopath) + TEST_CASE(ignorepaths1) + TEST_CASE(ignorepaths2) + TEST_CASE(ignorepaths3) + TEST_CASE(ignorepaths4) TEST_CASE(unknownParam); } @@ -647,6 +652,62 @@ private: ASSERT(settings._verbose); } + void ignorepathsnopath() + { + REDIRECT; + const char *argv[] = {"cppcheck", "-i"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(!parser.ParseFromArgs(2, argv)); + ASSERT_EQUALS(0, parser.GetIgnoredPaths().size()); + } + + void ignorepaths1() + { + REDIRECT; + const char *argv[] = {"cppcheck", "-isrc", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(parser.ParseFromArgs(3, argv)); + ASSERT_EQUALS(1, parser.GetIgnoredPaths().size()); + ASSERT_EQUALS("src/", parser.GetIgnoredPaths()[0]); + } + + void ignorepaths2() + { + REDIRECT; + const char *argv[] = {"cppcheck", "-i", "src", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(parser.ParseFromArgs(4, argv)); + ASSERT_EQUALS(1, parser.GetIgnoredPaths().size()); + ASSERT_EQUALS("src/", parser.GetIgnoredPaths()[0]); + } + + void ignorepaths3() + { + REDIRECT; + const char *argv[] = {"cppcheck", "-isrc", "-imodule", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(parser.ParseFromArgs(4, argv)); + ASSERT_EQUALS(2, parser.GetIgnoredPaths().size()); + ASSERT_EQUALS("src/", parser.GetIgnoredPaths()[0]); + ASSERT_EQUALS("module/", parser.GetIgnoredPaths()[1]); + } + + void ignorepaths4() + { + REDIRECT; + const char *argv[] = {"cppcheck", "-i", "src", "-i", "module", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(parser.ParseFromArgs(6, argv)); + ASSERT_EQUALS(2, parser.GetIgnoredPaths().size()); + ASSERT_EQUALS("src/", parser.GetIgnoredPaths()[0]); + ASSERT_EQUALS("module/", parser.GetIgnoredPaths()[1]); + } + void unknownParam() { REDIRECT; diff --git a/test/testpathmatch.cpp b/test/testpathmatch.cpp new file mode 100644 index 000000000..7b78dc0bc --- /dev/null +++ b/test/testpathmatch.cpp @@ -0,0 +1,158 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2011 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 "testsuite.h" +#include "pathmatch.h" + +class TestPathMatch : public TestFixture +{ +public: + TestPathMatch() : TestFixture("TestPathMatch") + { } + +private: + + void run() + { + TEST_CASE(emptymaskemptyfile); + TEST_CASE(emptymaskpath1); + TEST_CASE(emptymaskpath2); + TEST_CASE(emptymaskpath3); + TEST_CASE(onemaskemptypath); + TEST_CASE(onemasksamepath); + TEST_CASE(onemasksamepathwithfile); + TEST_CASE(onemasklongerpath1); + TEST_CASE(onemasklongerpath2); + TEST_CASE(onemasklongerpath3); + } + + void emptymaskemptyfile() + { + std::vector masks; + PathMatch match(masks); + ASSERT(!match.Match("")); + } + + void emptymaskpath1() + { + std::vector masks; + PathMatch match(masks); + ASSERT(!match.Match("src/")); + } + + void emptymaskpath2() + { + std::vector masks; + PathMatch match(masks); + ASSERT(!match.Match("../src/")); + } + + void emptymaskpath3() + { + std::vector masks; + PathMatch match(masks); + ASSERT(!match.Match("/home/user/code/src/")); + } + + void onemaskemptypath() + { + std::vector masks; + masks.push_back("src/"); + PathMatch match(masks); + ASSERT(!match.Match("")); + } + + void onemasksamepath() + { + std::vector masks; + masks.push_back("src/"); + PathMatch match(masks); + ASSERT(match.Match("src/")); + } + + void onemasksamepathwithfile() + { + std::vector masks; + masks.push_back("src/"); + PathMatch match(masks); + ASSERT(match.Match("src/file.txt")); + } + + void onemasklongerpath1() + { + std::vector masks; + masks.push_back("src/"); + PathMatch match(masks); + ASSERT(match.Match("/tmp/src/")); + } + + void onemasklongerpath2() + { + std::vector masks; + masks.push_back("src/"); + PathMatch match(masks); + ASSERT(match.Match("src/module/")); + } + + void onemasklongerpath3() + { + std::vector masks; + masks.push_back("src/"); + PathMatch match(masks); + ASSERT(match.Match("project/src/module/")); + } + + void twomasklongerpath1() + { + std::vector masks; + masks.push_back("src/"); + masks.push_back("module/"); + PathMatch match(masks); + ASSERT(!match.Match("project/")); + } + + void twomasklongerpath2() + { + std::vector masks; + masks.push_back("src/"); + masks.push_back("module/"); + PathMatch match(masks); + ASSERT(match.Match("project/src/")); + } + + void twomasklongerpath3() + { + std::vector masks; + masks.push_back("src/"); + masks.push_back("module/"); + PathMatch match(masks); + ASSERT(match.Match("project/module/")); + } + + void twomasklongerpath4() + { + std::vector masks; + masks.push_back("src/"); + masks.push_back("module/"); + PathMatch match(masks); + ASSERT(match.Match("project/src/module/")); + } + +}; + +REGISTER_TEST(TestPathMatch) From 3fc0d0f03e8622bd22688bf0c408c4f763a36ea1 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Tue, 1 Feb 2011 13:34:05 +0200 Subject: [PATCH 09/40] Run dmake to update Makefile. --- Makefile | 14 +++++++++++--- test/testpathmatch.cpp | 2 ++ tools/dmake.cpp | 4 ++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 09aadde1c..5391b67ea 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,7 @@ CLIOBJ = cli/cmdlineparser.o \ cli/filelister_unix.o \ cli/filelister_win32.o \ cli/main.o \ + cli/pathmatch.o \ cli/threadexecutor.o TESTOBJ = test/options.o \ @@ -74,6 +75,7 @@ TESTOBJ = test/options.o \ test/testoptions.o \ test/testother.o \ test/testpath.o \ + test/testpathmatch.o \ test/testpostfixoperator.o \ test/testpreprocessor.o \ test/testrunner.o \ @@ -103,8 +105,8 @@ cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ) all: cppcheck testrunner -testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/filelister.o cli/filelister_unix.o - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o testrunner $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) -lpcre cli/threadexecutor.o cli/cmdlineparser.o cli/filelister.o cli/filelister_unix.o $(LDFLAGS) +testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/filelister.o cli/filelister_unix.o cli/pathmatch.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o testrunner $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) -lpcre cli/threadexecutor.o cli/cmdlineparser.o cli/filelister.o cli/filelister_unix.o cli/pathmatch.o $(LDFLAGS) test: all ./testrunner @@ -206,7 +208,7 @@ lib/tokenize.o: lib/tokenize.cpp lib/tokenize.h lib/token.h lib/mathlib.h lib/se cli/cmdlineparser.o: cli/cmdlineparser.cpp lib/cppcheck.h lib/settings.h lib/errorlogger.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h lib/timer.h cli/cmdlineparser.h lib/path.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/cmdlineparser.o cli/cmdlineparser.cpp -cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cppcheckexecutor.h lib/errorlogger.h lib/settings.h lib/cppcheck.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h cli/threadexecutor.h cli/cmdlineparser.h cli/filelister.h lib/path.h +cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cppcheckexecutor.h lib/errorlogger.h lib/settings.h lib/cppcheck.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h cli/threadexecutor.h cli/cmdlineparser.h cli/filelister.h lib/path.h cli/pathmatch.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/cppcheckexecutor.o cli/cppcheckexecutor.cpp cli/filelister.o: cli/filelister.cpp cli/filelister.h cli/filelister_win32.h cli/filelister_unix.h @@ -221,6 +223,9 @@ cli/filelister_win32.o: cli/filelister_win32.cpp cli/filelister.h cli/filelister cli/main.o: cli/main.cpp cli/cppcheckexecutor.h lib/errorlogger.h lib/settings.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/main.o cli/main.cpp +cli/pathmatch.o: cli/pathmatch.cpp cli/pathmatch.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/pathmatch.o cli/pathmatch.cpp + cli/threadexecutor.o: cli/threadexecutor.cpp cli/threadexecutor.h lib/settings.h lib/errorlogger.h lib/cppcheck.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/threadexecutor.o cli/threadexecutor.cpp @@ -284,6 +289,9 @@ test/testother.o: test/testother.cpp lib/tokenize.h lib/checkother.h lib/check.h test/testpath.o: test/testpath.cpp test/testsuite.h lib/errorlogger.h test/redirect.h lib/path.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Icli -Iexternals -c -o test/testpath.o test/testpath.cpp +test/testpathmatch.o: test/testpathmatch.cpp test/testsuite.h lib/errorlogger.h test/redirect.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Icli -Iexternals -c -o test/testpathmatch.o test/testpathmatch.cpp + test/testpostfixoperator.o: test/testpostfixoperator.cpp lib/tokenize.h lib/checkpostfixoperator.h lib/check.h lib/token.h lib/settings.h lib/errorlogger.h test/testsuite.h test/redirect.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Icli -Iexternals -c -o test/testpostfixoperator.o test/testpostfixoperator.cpp diff --git a/test/testpathmatch.cpp b/test/testpathmatch.cpp index 7b78dc0bc..dadeef311 100644 --- a/test/testpathmatch.cpp +++ b/test/testpathmatch.cpp @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +#include +#include #include "testsuite.h" #include "pathmatch.h" diff --git a/tools/dmake.cpp b/tools/dmake.cpp index 434a4128c..7e688f33c 100644 --- a/tools/dmake.cpp +++ b/tools/dmake.cpp @@ -230,8 +230,8 @@ int main(int argc, char **argv) fout << "cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ)\n"; fout << "\t$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o cppcheck $(CLIOBJ) $(LIBOBJ) $(EXTOBJ) -lpcre $(LDFLAGS)\n\n"; fout << "all:\tcppcheck testrunner\n\n"; - fout << "testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/filelister.o cli/filelister_unix.o\n"; - fout << "\t$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o testrunner $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) -lpcre cli/threadexecutor.o cli/cmdlineparser.o cli/filelister.o cli/filelister_unix.o $(LDFLAGS)\n\n"; + fout << "testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/filelister.o cli/filelister_unix.o cli/pathmatch.o\n"; + fout << "\t$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o testrunner $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) -lpcre cli/threadexecutor.o cli/cmdlineparser.o cli/filelister.o cli/filelister_unix.o cli/pathmatch.o $(LDFLAGS)\n\n"; fout << "test:\tall\n"; fout << "\t./testrunner\n\n"; fout << "check:\tall\n"; From 84a988ec505b9d1073857335fc8f6a3c7a0a8412 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Tue, 1 Feb 2011 21:37:46 +0200 Subject: [PATCH 10/40] Update VS2008/VS2010 project files. --- cli/cppcheck.vcproj | 6 +++++- cli/cppcheck.vcxproj | 4 +++- cli/cppcheck.vcxproj.filters | 6 ++++++ test/test.vcproj | 10 ++++++++-- test/test.vcxproj | 5 ++++- test/test.vcxproj.filters | 9 +++++++++ 6 files changed, 35 insertions(+), 5 deletions(-) diff --git a/cli/cppcheck.vcproj b/cli/cppcheck.vcproj index 541363475..37ce7c22a 100755 --- a/cli/cppcheck.vcproj +++ b/cli/cppcheck.vcproj @@ -3,7 +3,7 @@ ProjectType="Visual C++" Version="9,00" Name="cppcheck" - ProjectGUID="{7E69D6C6-32B2-32E1-BF56-A5BFBAF5E61F}" + ProjectGUID="{56B0F403-02CE-3F89-9A1B-E03F21240A63}" Keyword="Qt4VSv1.0"> + + - {42BC0E8E-9175-3B2D-B8B3-9EC5C36EF49A} + {A6DACC3F-847F-3498-9415-164FBC746D6B} cppcheck Qt4VSv1.0 @@ -140,6 +140,7 @@ + @@ -176,6 +177,7 @@ + diff --git a/cli/cppcheck.vcxproj.filters b/cli/cppcheck.vcxproj.filters index 4e6b80eca..de87f16e1 100644 --- a/cli/cppcheck.vcxproj.filters +++ b/cli/cppcheck.vcxproj.filters @@ -84,6 +84,9 @@ Source Files + + Source Files + Source Files @@ -188,6 +191,9 @@ Header Files + + Header Files + Header Files diff --git a/test/test.vcproj b/test/test.vcproj index 45d3f2948..e4b4589c6 100755 --- a/test/test.vcproj +++ b/test/test.vcproj @@ -3,7 +3,7 @@ ProjectType="Visual C++" Version="9,00" Name="test" - ProjectGUID="{48110A35-C2BB-3F1C-A741-C15295041A2D}" + ProjectGUID="{5B7869EA-A1CB-3E73-8569-5B385608779E}" Keyword="Qt4VSv1.0"> + + + - {081168BA-E630-3D82-8EDB-A19028999479} + {D0001948-3B19-3314-8BEE-3B92350BC5B5} test Qt4VSv1.0 @@ -140,6 +140,7 @@ + @@ -161,6 +162,7 @@ + @@ -209,6 +211,7 @@ + diff --git a/test/test.vcxproj.filters b/test/test.vcxproj.filters index 84b2d7672..027fb94a8 100644 --- a/test/test.vcxproj.filters +++ b/test/test.vcxproj.filters @@ -80,6 +80,9 @@ Source Files + + Source Files + Source Files @@ -143,6 +146,9 @@ Source Files + + Source Files + Source Files @@ -283,6 +289,9 @@ Header Files + + Header Files + Header Files From 51a1f6453187883057796ba89fd8b45f3fdc7848 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Tue, 1 Feb 2011 21:50:22 +0200 Subject: [PATCH 11/40] Don't check empty paths for path ignore. --- cli/pathmatch.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/pathmatch.cpp b/cli/pathmatch.cpp index 115b34d5a..25ed6cd71 100644 --- a/cli/pathmatch.cpp +++ b/cli/pathmatch.cpp @@ -25,6 +25,9 @@ PathMatch::PathMatch(const std::vector &masks) bool PathMatch::Match(const std::string &path) { + if (path.empty()) + return false; + std::vector::const_iterator iterMask; for (iterMask = _masks.begin(); iterMask != _masks.end(); ++iterMask) { From 1a83e3ef8124cffaa43d900dc4c71b79f7772def Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Tue, 1 Feb 2011 23:02:07 +0200 Subject: [PATCH 12/40] Use different way to remove items from vector. The way I was using caused a debug error in Visual Studio 2008. Probably because the iterator got invalidated. So access items as array instead. --- cli/cppcheckexecutor.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index de1756d3f..94deeccfe 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -93,15 +93,12 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c if (!filenames.empty()) { PathMatch matcher(parser.GetIgnoredPaths()); - // Ignore files - std::vector::iterator iter = filenames.end(); - do + std::vector::iterator iterBegin = filenames.begin(); + for (int i = (int)filenames.size() - 1; i >= 0; i--) { - --iter; - if (matcher.Match(*iter)) - filenames.erase(iter); + if (matcher.Match(filenames[i])) + filenames.erase(iterBegin + i); } - while (iter != filenames.begin()); } else { From 9a383388beeefaf66d9b809eb7a1b7df421cc3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 2 Feb 2011 18:46:07 +0100 Subject: [PATCH 13/40] xml2: added element --- cli/cppcheckexecutor.cpp | 4 ++-- lib/errorlogger.cpp | 7 ++++--- lib/errorlogger.h | 2 +- test/testerrorlogger.cpp | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index fdb886471..1f008f890 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -55,7 +55,7 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c errorlist = true; std::cout << ErrorLogger::ErrorMessage::getXMLHeader(_settings._xml_version); cppcheck->getErrorMessages(); - std::cout << ErrorLogger::ErrorMessage::getXMLFooter() << std::endl; + std::cout << ErrorLogger::ErrorMessage::getXMLFooter(_settings._xml_version) << std::endl; } if (parser.ExitAfterPrinting()) @@ -141,7 +141,7 @@ int CppCheckExecutor::check(int argc, const char* const argv[]) if (_settings._xml) { - reportErr(ErrorLogger::ErrorMessage::getXMLFooter()); + reportErr(ErrorLogger::ErrorMessage::getXMLFooter(_settings._xml_version)); } if (returnValue) diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp index 6f4baa90f..0bb9cbc98 100644 --- a/lib/errorlogger.cpp +++ b/lib/errorlogger.cpp @@ -162,15 +162,16 @@ std::string ErrorLogger::ErrorMessage::getXMLHeader(int xml_version) else { ostr << "\n"; - ostr << " "; + ostr << " \n"; + ostr << " "; } return ostr.str(); } -std::string ErrorLogger::ErrorMessage::getXMLFooter() +std::string ErrorLogger::ErrorMessage::getXMLFooter(int xml_version) { - return ""; + return (xml_version<=1) ? "" : " \n"; } static std::string stringToXml(std::string s) diff --git a/lib/errorlogger.h b/lib/errorlogger.h index da68ba499..da5b7835f 100644 --- a/lib/errorlogger.h +++ b/lib/errorlogger.h @@ -137,7 +137,7 @@ public: std::string toXML(bool verbose, int ver) const; static std::string getXMLHeader(int xml_version); - static std::string getXMLFooter(); + static std::string getXMLFooter(int xml_version); /** * Format the error message into a string. diff --git a/test/testerrorlogger.cpp b/test/testerrorlogger.cpp index e1064464b..fd10cba36 100644 --- a/test/testerrorlogger.cpp +++ b/test/testerrorlogger.cpp @@ -124,7 +124,7 @@ private: locs.push_back(loc); ErrorMessage msg(locs, Severity::error, "Programming error.\nVerbose error", "errorId"); ASSERT_EQUALS("\n", ErrorLogger::ErrorMessage::getXMLHeader(1)); - ASSERT_EQUALS("", ErrorLogger::ErrorMessage::getXMLFooter()); + ASSERT_EQUALS("", ErrorLogger::ErrorMessage::getXMLFooter(1)); ASSERT_EQUALS("", msg.toXML(false,1)); } @@ -137,7 +137,7 @@ private: locs.push_back(loc); ErrorMessage msg(locs, Severity::error, "Programming error.\nVerbose error", "errorId"); ASSERT_EQUALS("\n", ErrorLogger::ErrorMessage::getXMLHeader(1)); - ASSERT_EQUALS("", ErrorLogger::ErrorMessage::getXMLFooter()); + ASSERT_EQUALS("", ErrorLogger::ErrorMessage::getXMLFooter(1)); ASSERT_EQUALS("", msg.toXML(true,1)); } }; From d592250284cdf3f1ded17814c29ea4bae06b3126 Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 10:56:02 -0600 Subject: [PATCH 14/40] Fix sizeof sizeof check to handle sizeof(sizeof type) --- lib/checkother.cpp | 5 ++++- test/testother.cpp | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 87574a6df..5313dd611 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -2834,8 +2834,11 @@ void CheckOther::sizeofsizeof() return; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { - if (Token::simpleMatch(tok, "sizeof sizeof")) + if (Token::Match(tok, "sizeof (| sizeof")) + { sizeofsizeofError(tok); + tok = tok->next(); + } } } diff --git a/test/testother.cpp b/test/testother.cpp index af08d80c4..dced35a69 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -961,6 +961,18 @@ private: " int i = sizeof sizeof char;\n" "}\n"); ASSERT_EQUALS("[test.cpp:3]: (warning) Calling sizeof for 'sizeof'.\n", errout.str()); + + check("void foo()\n" + "{\n" + " int i = sizeof (sizeof long);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3]: (warning) Calling sizeof for 'sizeof'.\n", errout.str()); + + check("void foo(long *p)\n" + "{\n" + " int i = sizeof (sizeof (p));\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3]: (warning) Calling sizeof for 'sizeof'.\n", errout.str()); } void sizeofCalculation() From 9075ca59ca5a3c21c6f9cc18f2e411b3ce6bbd93 Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 09:16:27 -0600 Subject: [PATCH 15/40] Introduce some rules for checking cppcheck's use of Token::*Match --- rules/token-matching.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 rules/token-matching.xml diff --git a/rules/token-matching.xml b/rules/token-matching.xml new file mode 100644 index 000000000..6abcc7cde --- /dev/null +++ b/rules/token-matching.xml @@ -0,0 +1,18 @@ + + + Token :: (?:findm|(?:simple|)M)atch \([^,]+,\s+"\s+ + + TokenMatchSpacing + style + Useless extra spacing for Token::*Match. + + + + Token :: Match \([^,]+,\s+"[^%|!\[\]]+" + + UseTokensimpleMatch + error + Token::simpleMatch should be used to match tokens +without special pattern requirements. + + From 61435684b2f50a7a5c213ab743bdd13015f506ec Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 09:35:15 -0600 Subject: [PATCH 16/40] Support multiple rules in a single XML file --- cli/cmdlineparser.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 98bcee069..10482e6fc 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -513,18 +513,17 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) TiXmlDocument doc; if (doc.LoadFile(12+argv[i])) { - TiXmlElement *root = doc.FirstChildElement(); - if (root && root->ValueStr() == "rule") - { + TiXmlElement *node = doc.FirstChildElement(); + for (; node && node->ValueStr() == "rule"; node = node->NextSiblingElement()) { Settings::Rule rule; - TiXmlElement *pattern = root->FirstChildElement("pattern"); + TiXmlElement *pattern = node->FirstChildElement("pattern"); if (pattern) { rule.pattern = pattern->GetText(); } - TiXmlElement *message = root->FirstChildElement("message"); + TiXmlElement *message = node->FirstChildElement("message"); if (message) { TiXmlElement *severity = message->FirstChildElement("severity"); From a9681ad4d144a500bb10d8c5e238a297c11b5a7e Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 09:41:08 -0600 Subject: [PATCH 17/40] Also detect useless spacing at the end of *Match calls --- rules/token-matching.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/token-matching.xml b/rules/token-matching.xml index 6abcc7cde..a935bd93d 100644 --- a/rules/token-matching.xml +++ b/rules/token-matching.xml @@ -1,6 +1,6 @@ - Token :: (?:findm|(?:simple|)M)atch \([^,]+,\s+"\s+ + Token :: (?:findm|(?:simple|)M)atch \([^,]+,\s+"(?:\s+|[^"]+?\s+") TokenMatchSpacing style From cf2b6f7bc1f7f00a3797699ad3cfe7e37e81546b Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 09:41:43 -0600 Subject: [PATCH 18/40] Remove useless spacing at the end of *Match strings --- lib/checkbufferoverrun.cpp | 2 +- lib/checkclass.cpp | 2 +- lib/checkother.cpp | 2 +- lib/checkstl.cpp | 2 +- lib/symboldatabase.cpp | 2 +- lib/tokenize.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 5f7e42619..b2affa275 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -302,7 +302,7 @@ static bool for_condition(const Token * const tok2, unsigned int varid, std::str maxMinFlipped = false; max_value = tok2->strAt(2); } - else if (Token::Match(tok2, " %num% < %varid% ;", varid) || + else if (Token::Match(tok2, "%num% < %varid% ;", varid) || Token::Match(tok2, "%num% != %varid% ; ++ %varid%", varid) || Token::Match(tok2, "%num% != %varid% ; %varid% ++", varid)) { diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 0991e795f..2067142f9 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -310,7 +310,7 @@ void CheckClass::initializeVarList(const Function &func, std::list ftok = ftok->next(); // Using the operator= function to initialize all variables.. - if (Token::simpleMatch(ftok->next(), "* this = ")) + if (Token::simpleMatch(ftok->next(), "* this =")) { assignAllVar(usage); break; diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 5313dd611..1b41bb1cd 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -137,7 +137,7 @@ void CheckOther::checkSizeofForArrayParameter() { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { - if (Token::Match(tok, "sizeof ( %var% )") || Token::Match(tok, "sizeof %var% ")) + if (Token::Match(tok, "sizeof ( %var% )") || Token::Match(tok, "sizeof %var%")) { int tokIdx = 1; if (tok->tokAt(tokIdx)->str() == "(") diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index fc90339bb..87044e4d2 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -445,7 +445,7 @@ void CheckStl::erase() break; } - if (Token::Match(tok2, "%var% = %var% . begin ( ) ; %var% != %var% . end ( ) ") && + if (Token::Match(tok2, "%var% = %var% . begin ( ) ; %var% != %var% . end ( )") && tok2->str() == tok2->tokAt(8)->str() && tok2->tokAt(2)->str() == tok2->tokAt(10)->str()) { diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 51032d44d..cf69b6196 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1213,7 +1213,7 @@ const Token* skipScopeIdentifiers(const Token* tok) { ret = ret->next(); } - while (Token::Match(ret, "%type% :: ")) + while (Token::Match(ret, "%type% ::")) { ret = ret->tokAt(2); } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 8cc0b6945..aa3707c8e 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -7702,7 +7702,7 @@ void Tokenizer::simplifyEnum() lastEnumValueStart = 0; lastEnumValueEnd = 0; } - else if (Token::Match(tok1->previous(), ",|{ %type% = ")) + else if (Token::Match(tok1->previous(), ",|{ %type% =")) { // value is specified expression enumName = tok1; From 8d5863133c0cc4ad1bdf7981caf43cd803743e14 Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 09:48:00 -0600 Subject: [PATCH 19/40] Use Token::simpleMatch where no patterns are used --- lib/checkautovariables.cpp | 2 +- lib/checkbufferoverrun.cpp | 2 +- lib/checkclass.cpp | 2 +- lib/checkmemoryleak.cpp | 2 +- lib/checknullpointer.cpp | 2 +- lib/checkother.cpp | 2 +- lib/checkstl.cpp | 2 +- lib/executionpath.cpp | 2 +- lib/preprocessor.cpp | 2 +- lib/tokenize.cpp | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 414ae527e..f33a9a8ae 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -448,7 +448,7 @@ void CheckAutoVariables::returncstr() } // have we reached a function that returns a reference? - if (Token::Match(tok, "const char *")) + if (Token::simpleMatch(tok, "const char *")) { // go to the '(' const Token *tok2 = tok->tokAt(3); diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index b2affa275..d4340048c 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -766,7 +766,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector(varname.empty() ? 0U : (varname.size() - 1) * 2U)); - if (Token::Match(tok, "return")) + if (Token::simpleMatch(tok, "return")) { tok = tok->next(); if (!tok) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 2067142f9..8f71226ad 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -931,7 +931,7 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co // check of *this is returned else if (!(Token::Match(tok->tokAt(1), "(| * this ;|=") || Token::Match(tok->tokAt(1), "(| * this +=") || - Token::Match(tok->tokAt(1), "operator= ("))) + Token::simpleMatch(tok->tokAt(1), "operator= ("))) operatorEqRetRefThisError(func->token); } } diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 0ffab12c7..f539e431c 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -223,7 +223,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok return gMalloc; if (Token::Match(tok, "fclose ( %varid% )", varid) || - Token::Match(tok, "fcloseall ( )")) + Token::simpleMatch(tok, "fcloseall ( )")) return File; if (Token::Match(tok, "close ( %varid% )", varid)) diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index bd36a4e37..df8c49495 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -544,7 +544,7 @@ void CheckNullPointer::nullPointerByCheckAndDeRef() if (Token::Match(tok, "* %var% [;,)=]")) pointerVariables.insert(tok->next()->varId()); - else if (Token::Match(tok, "if (")) + else if (Token::simpleMatch(tok, "if (")) { // TODO: investigate false negatives: // - handle "while"? diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 1b41bb1cd..bf96eedf7 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1491,7 +1491,7 @@ void CheckOther::functionVariableUsage() variables.read(nametok->tokAt(2)->varId()); // look at initializers - if (Token::Match(nametok->tokAt(4), "= {")) + if (Token::simpleMatch(nametok->tokAt(4), "= {")) { tok = nametok->tokAt(6); while (tok->str() != "}") diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 87044e4d2..6ae97742b 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -572,7 +572,7 @@ void CheckStl::pushback() } // Using push_back or push_front inside a loop.. - if (Token::Match(tok2, "for (")) + if (Token::simpleMatch(tok2, "for (")) { tok2 = tok2->tokAt(2); } diff --git a/lib/executionpath.cpp b/lib/executionpath.cpp index fad18cc58..7e8b6c4c7 100644 --- a/lib/executionpath.cpp +++ b/lib/executionpath.cpp @@ -348,7 +348,7 @@ void ExecutionPath::checkScope(const Token *tok, std::list &che } } - if (Token::Match(tok, "= {")) + if (Token::simpleMatch(tok, "= {")) { // GCC struct initialization.. bail out if (Token::Match(tok->tokAt(2), ". %var% =")) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 4cdd5f729..5aa45a0ee 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -2142,7 +2142,7 @@ public: if (Token::Match(tok, "%var% %var%") || Token::Match(tok, "%var% %num%") || Token::Match(tok, "%num% %var%") || - Token::Match(tok, "> >")) + Token::simpleMatch(tok, "> >")) macrocode += " "; } } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index aa3707c8e..210fe3702 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -552,7 +552,7 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name) if (end) { - if (Token::Match(end, ") {")) // function parameter ? + if (Token::simpleMatch(end, ") {")) // function parameter ? { // look backwards if (Token::Match(tok->previous(), "%type%") && From 15dceed6cd81d1c1b6dec7f20ee360fabf917bc7 Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 09:54:04 -0600 Subject: [PATCH 20/40] Remove uneeded indentation --- lib/cppcheck.cpp | 70 ++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index db0a15105..951ca3470 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -335,48 +335,48 @@ void CppCheck::checkFile(const std::string &code, const char FileName[]) reportErr(errmsg); } - if (re) + if (!re) + continue; + + int pos = 0; + int ovector[30]; + if (0 <= pcre_exec(re, NULL, str.c_str(), (int)str.size(), pos, 0, ovector, 30)) { - int pos = 0; - int ovector[30]; - if (0 <= pcre_exec(re, NULL, str.c_str(), (int)str.size(), pos, 0, ovector, 30)) + unsigned int pos1 = (unsigned int)ovector[0]; + unsigned int pos2 = (unsigned int)ovector[1]; + + // determine location.. + ErrorLogger::ErrorMessage::FileLocation loc; + loc.setfile(_tokenizer.getFiles()->front()); + loc.line = 0; + + unsigned int len = 0; + for (const Token *tok = _tokenizer.tokens(); tok; tok = tok->next()) { - unsigned int pos1 = (unsigned int)ovector[0]; - unsigned int pos2 = (unsigned int)ovector[1]; - - // determine location.. - ErrorLogger::ErrorMessage::FileLocation loc; - loc.setfile(_tokenizer.getFiles()->front()); - loc.line = 0; - - unsigned int len = 0; - for (const Token *tok = _tokenizer.tokens(); tok; tok = tok->next()) + len = len + 1 + tok->str().size(); + if (len > pos1) { - len = len + 1 + tok->str().size(); - if (len > pos1) - { - loc.setfile(_tokenizer.getFiles()->at(tok->fileIndex())); - loc.line = tok->linenr(); - break; - } + loc.setfile(_tokenizer.getFiles()->at(tok->fileIndex())); + loc.line = tok->linenr(); + break; } - - const std::list callStack(1, loc); - - // Create error message - std::string summary; - if (rule.summary.empty()) - summary = "found '" + str.substr(pos1, pos2 - pos1) + "'"; - else - summary = rule.summary; - ErrorLogger::ErrorMessage errmsg(callStack, Severity::fromString(rule.severity), summary, rule.id); - - // Report error - reportErr(errmsg); } - pcre_free(re); + const std::list callStack(1, loc); + + // Create error message + std::string summary; + if (rule.summary.empty()) + summary = "found '" + str.substr(pos1, pos2 - pos1) + "'"; + else + summary = rule.summary; + ErrorLogger::ErrorMessage errmsg(callStack, Severity::fromString(rule.severity), summary, rule.id); + + // Report error + reportErr(errmsg); } + + pcre_free(re); } } #endif From 45e5dc20a2aa83932fb1cd29e7dd30f8d9ddfb4f Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 10:01:09 -0600 Subject: [PATCH 21/40] Try to match custom rules as many times as possible, not just once --- lib/cppcheck.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 951ca3470..8364e379e 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -340,11 +340,14 @@ void CppCheck::checkFile(const std::string &code, const char FileName[]) int pos = 0; int ovector[30]; - if (0 <= pcre_exec(re, NULL, str.c_str(), (int)str.size(), pos, 0, ovector, 30)) + while (0 <= pcre_exec(re, NULL, str.c_str(), (int)str.size(), pos, 0, ovector, 30)) { unsigned int pos1 = (unsigned int)ovector[0]; unsigned int pos2 = (unsigned int)ovector[1]; + // jump to the end of the match for the next pcre_exec + pos = pos2; + // determine location.. ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile(_tokenizer.getFiles()->front()); From f8e2d50e6fbb8b27ac215348962d866bba34b1c5 Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 10:12:46 -0600 Subject: [PATCH 22/40] Use Token::simpleMatch where no special patterns are needed --- lib/checkbufferoverrun.cpp | 2 +- lib/checkclass.cpp | 6 +++--- lib/checkmemoryleak.cpp | 6 +++--- lib/checknullpointer.cpp | 2 +- lib/checkother.cpp | 2 +- lib/checkstl.cpp | 2 +- lib/symboldatabase.cpp | 2 +- lib/tokenize.cpp | 34 +++++++++++++++++----------------- 8 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index d4340048c..c0afdce94 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -828,7 +828,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vectorstrAt(3)); if (index < 0 || index >= size) { - if (index > size || !Token::Match(tok->previous(), "& (")) + if (index > size || !Token::simpleMatch(tok->previous(), "& (")) { arrayIndexOutOfBounds(tok->next(), size, index); } diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 8f71226ad..53dd353a2 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -799,7 +799,7 @@ void CheckClass::noMemset() if (Token::Match(tstruct->next(), "std :: %type% %var% ;")) memsetStructError(tok, tok->str(), tstruct->strAt(3)); - else if (Token::Match(tstruct->next(), "std :: %type% < ")) + else if (Token::Match(tstruct->next(), "std :: %type% <")) { // backup the type const std::string typestr(tstruct->strAt(3)); @@ -1132,7 +1132,7 @@ bool CheckClass::hasAssignSelf(const Token *first, const Token *last, const Toke { for (const Token *tok = first; tok && tok != last; tok = tok->next()) { - if (Token::Match(tok, "if (")) + if (Token::simpleMatch(tok, "if (")) { const Token *tok1 = tok->tokAt(2); const Token *tok2 = tok->tokAt(1)->link(); @@ -1412,7 +1412,7 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) while (tok->previous() && !Token::Match(tok->previous(), "}|{|;|public:|protected:|private:|return|:|?")) { - if (Token::Match(tok->previous(), "* this")) + if (Token::simpleMatch(tok->previous(), "* this")) return true; tok = tok->previous(); diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index f539e431c..97a8ea249 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -1445,7 +1445,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::liststr(";"); Token::eraseTokens(tok2, tok2->tokAt(4)); @@ -1820,7 +1820,7 @@ void CheckMemoryLeakInFunction::simplifycode(Token *tok) } // Reduce "if continue ; if continue ;" => "if continue ;" - else if (Token::Match(tok2->next(), "if continue ; if continue ;")) + else if (Token::simpleMatch(tok2->next(), "if continue ; if continue ;")) { Token::eraseTokens(tok2, tok2->tokAt(4)); done = false; diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index df8c49495..ff951f5ba 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -617,7 +617,7 @@ void CheckNullPointer::nullPointerByCheckAndDeRef() if (null && indentlevel == 0) { // skip all "else" blocks because they are not executed in this execution path - while (Token::Match(tok2, "} else {")) + while (Token::simpleMatch(tok2, "} else {")) tok2 = tok2->tokAt(2)->link(); null = false; } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index bf96eedf7..4e5ff04cd 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -2705,7 +2705,7 @@ void CheckOther::checkMisusedScopedObject() } if (Token::Match(tok, "[;{}] %var% (") - && Token::Match(tok->tokAt(2)->link(), ") ;") + && Token::simpleMatch(tok->tokAt(2)->link(), ") ;") && symbolDatabase->isClassOrStruct(tok->next()->str()) ) { diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 6ae97742b..a2c871db3 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -1038,7 +1038,7 @@ void CheckStl::string_c_str() string_c_strError(tok); } else if (Token::Match(tok, "[;{}] %var% = %var% (") && - Token::Match(tok->tokAt(4)->link(), ") . c_str ( ) ;") && + Token::simpleMatch(tok->tokAt(4)->link(), ") . c_str ( ) ;") && tok->next()->varId() > 0 && pointers.find(tok->next()->varId()) != pointers.end() && Token::findmatch(_tokenizer->tokens(), ("std :: string " + tok->strAt(3) + " (").c_str())) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index cf69b6196..b7e9f8ea3 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1238,7 +1238,7 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const const Token* localTypeTok = skipScopeIdentifiers(tok); const Token* localVarTok = NULL; - if (Token::Match(localTypeTok, "%type% < ")) + if (Token::Match(localTypeTok, "%type% <")) { const Token* closeTok = NULL; bool found = findClosingBracket(localTypeTok->next(), closeTok); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 210fe3702..f747e4a06 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -588,7 +588,7 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name) (tok->previous()->str() == "*" && tok->next()->str() != "(") || (Token::Match(tok->previous(), "%type%") && (!Token::Match(tok->previous(), "return|new|const|friend|public|private|protected|throw|extern") && - !Token::Match(tok->tokAt(-2), "friend class")))) + !Token::simpleMatch(tok->tokAt(-2), "friend class")))) { // scan backwards for the end of the previous statement int level = (tok->previous()->str() == "}") ? 1 : 0; @@ -926,7 +926,7 @@ void Tokenizer::simplifyTypedef() Token *namespaceStart = 0; Token *namespaceEnd = 0; - if (Token::Match(tok->next(), "::") || + if (Token::simpleMatch(tok->next(), "::") || Token::Match(tok->next(), "%type%")) { typeStart = tok->next(); @@ -940,13 +940,13 @@ void Tokenizer::simplifyTypedef() bool atEnd = false; while (!atEnd) { - if (Token::Match(tok->tokAt(offset), "::")) + if (Token::simpleMatch(tok->tokAt(offset), "::")) typeEnd = tok->tokAt(offset++); if (Token::Match(tok->tokAt(offset), "%type%") && tok->tokAt(offset + 1) && !Token::Match(tok->tokAt(offset + 1), "[|;|,|(")) typeEnd = tok->tokAt(offset++); - else if (Token::Match(tok->tokAt(offset), "const (")) + else if (Token::simpleMatch(tok->tokAt(offset), "const (")) { typeEnd = tok->tokAt(offset++); atEnd = true; @@ -1040,7 +1040,7 @@ void Tokenizer::simplifyTypedef() tok = tok->tokAt(offset); // or a function typedef - else if (Token::Match(tok->tokAt(offset), "(")) + else if (Token::simpleMatch(tok->tokAt(offset), "(")) { // unhandled typedef, skip it and continue if (typeName->str() == "void") @@ -1143,7 +1143,7 @@ void Tokenizer::simplifyTypedef() // function returning pointer to function else if (Token::Match(tok->tokAt(offset), "( * %type% (") && - Token::Match(tok->tokAt(offset + 3)->link(), ") ) (")) + Token::simpleMatch(tok->tokAt(offset + 3)->link(), ") ) (")) { functionRetFuncPtr = true; @@ -1397,8 +1397,8 @@ void Tokenizer::simplifyTypedef() inTemplate = true; // check for operator - if (Token::Match(tok2->previous(), "operator") || - Token::Match(tok2->tokAt(-2), "operator const")) + if (Token::simpleMatch(tok2->previous(), "operator") || + Token::simpleMatch(tok2->tokAt(-2), "operator const")) inOperator = true; // skip over class or struct in derived class declaration @@ -2717,7 +2717,7 @@ void Tokenizer::simplifyTemplates() ostr << " "; ostr << tok3->str(); } - if (!Token::Match(tok3, "> (")) + if (!Token::simpleMatch(tok3, "> (")) continue; s = ostr.str(); } @@ -3999,7 +3999,7 @@ void Tokenizer::simplifySizeof() tok->next()->deleteNext(); } - if (Token::Match(tok->next(), "( * )")) + if (Token::simpleMatch(tok->next(), "( * )")) { tok->str(MathLib::toString(sizeOfType(tok->tokAt(2)))); Token::eraseTokens(tok, tok->tokAt(4)); @@ -4711,7 +4711,7 @@ void Tokenizer::simplifyIfAddBraces() if (!innerIf) break; - if (Token::Match(tempToken, "; else if")) + if (Token::simpleMatch(tempToken, "; else if")) ; else if (Token::Match(tempToken, "; else")) innerIf = false; @@ -4754,7 +4754,7 @@ bool Tokenizer::simplifyDoWhileAddBracesHelper(Token *tok) tok2 = tok3; break; } - else if (Token::Match(tok3, "do {")) + else if (Token::simpleMatch(tok3, "do {")) { // Skip do{}while inside the current "do" tok3 = tok3->next()->link(); @@ -5758,7 +5758,7 @@ void Tokenizer::simplifyStdType() tok->isSigned(!isUnsigned); } - if (Token::Match(tok, "__int8")) + if (Token::simpleMatch(tok, "__int8")) tok->str("char"); else if (Token::Match(tok, "__int16")) tok->str("short"); @@ -7492,7 +7492,7 @@ bool Tokenizer::duplicateDefinition(Token ** tokPtr, const Token * name) if (end) { - if (Token::Match(end, ") {")) // function parameter ? + if (Token::simpleMatch(end, ") {")) // function parameter ? { // look backwards if (tok->previous()->str() == "enum" || @@ -7908,7 +7908,7 @@ void Tokenizer::simplifyEnum() } else if (tok2->str() == "{") ++level; - else if (!pattern.empty() && ((Token::Match(tok2, "enum") && Token::Match(tok2->next(), pattern.c_str())) || Token::Match(tok2, pattern.c_str()))) + else if (!pattern.empty() && ((Token::simpleMatch(tok2, "enum") && Token::Match(tok2->next(), pattern.c_str())) || Token::Match(tok2, pattern.c_str()))) { simplify = true; hasClass = true; @@ -8243,7 +8243,7 @@ void Tokenizer::simplifyComma() // We must not accept just any keyword, e.g. accepting int // would cause function parameters to corrupt. - if (Token::Match(tok->next(), "delete")) + if (Token::simpleMatch(tok->next(), "delete")) { // Handle "delete a, delete b;" tok->str(";"); @@ -8566,7 +8566,7 @@ void Tokenizer::simplifyStructInit() if (Token::simpleMatch(tok2, ", .")) tok2 = tok2->next(); } - if (!Token::Match(tok2, "} ;")) + if (!Token::simpleMatch(tok2, "} ;")) continue; // Known expression format => Perform simplification From 3c76dd2e3f0ce4cdfef5356fb2b78af821750326 Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 10:21:36 -0600 Subject: [PATCH 23/40] Yet another tweak to the regex, use ungreedy mode --- rules/token-matching.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/token-matching.xml b/rules/token-matching.xml index a935bd93d..47110c4b5 100644 --- a/rules/token-matching.xml +++ b/rules/token-matching.xml @@ -8,7 +8,7 @@ - Token :: Match \([^,]+,\s+"[^%|!\[\]]+" + (?U)Token :: Match \([^,]+,\s+"[^%|!\[\]]+" UseTokensimpleMatch error From c9a0d95e89366ea615f5049e6c8bff086917998a Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 10:25:13 -0600 Subject: [PATCH 24/40] A few more Token::Match -> ::simpleMatch replacements --- lib/tokenize.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index f747e4a06..49d752020 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -4713,7 +4713,7 @@ void Tokenizer::simplifyIfAddBraces() if (Token::simpleMatch(tempToken, "; else if")) ; - else if (Token::Match(tempToken, "; else")) + else if (Token::simpleMatch(tempToken, "; else")) innerIf = false; else break; @@ -5760,35 +5760,35 @@ void Tokenizer::simplifyStdType() if (Token::simpleMatch(tok, "__int8")) tok->str("char"); - else if (Token::Match(tok, "__int16")) + else if (Token::simpleMatch(tok, "__int16")) tok->str("short"); - else if (Token::Match(tok, "__int32")) + else if (Token::simpleMatch(tok, "__int32")) tok->str("int"); - else if (Token::Match(tok, "__int64")) + else if (Token::simpleMatch(tok, "__int64")) { tok->str("long"); tok->isLong(true); } - else if (Token::Match(tok, "long")) + else if (Token::simpleMatch(tok, "long")) { - if (Token::Match(tok->next(), "long")) + if (Token::simpleMatch(tok->next(), "long")) { tok->isLong(true); tok->deleteNext(); } - if (Token::Match(tok->next(), "int")) + if (Token::simpleMatch(tok->next(), "int")) tok->deleteNext(); - else if (Token::Match(tok->next(), "double")) + else if (Token::simpleMatch(tok->next(), "double")) { tok->str("double"); tok->isLong(true); tok->deleteNext(); } } - else if (Token::Match(tok, "short")) + else if (Token::simpleMatch(tok, "short")) { - if (Token::Match(tok->next(), "int")) + if (Token::simpleMatch(tok->next(), "int")) tok->deleteNext(); } } @@ -8251,7 +8251,7 @@ void Tokenizer::simplifyComma() if (tok->previous() && tok->previous()->previous()) { - if (Token::Match(tok->previous()->previous(), "delete") && + if (Token::simpleMatch(tok->previous()->previous(), "delete") && tok->next()->varId() != 0) { // Handle "delete a, b;" From bacb234534ff818699391aa0dcdbd75bac606703 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Wed, 2 Feb 2011 22:51:05 +0200 Subject: [PATCH 25/40] Add testsymboldatabase.cpp to test.pro. Also add comment explaining omitting testfilelister_unix.cpp. --- test/test.pro | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test.pro b/test/test.pro index b786428cf..f7237777c 100644 --- a/test/test.pro +++ b/test/test.pro @@ -33,6 +33,13 @@ HEADERS += ../cli/cmdlineparser.h \ ../cli/threadexecutor.h # test/* + +# Note: +# testfilelister_unix.cpp omitted since there is test fail when run in QtCreator +# Test assumes the test (executable) is built from the test directory (or +# directory containing source files). But QtCreator builds to separate build +# directory. Hence the test does not find the source files. + HEADERS += options.h redirect.h testsuite.h SOURCES += options.cpp \ testautovariables.cpp \ @@ -61,6 +68,7 @@ SOURCES += options.cpp \ testsimplifytokens.cpp \ teststl.cpp \ testsuite.cpp \ + testsymboldatabase.cpp \ testthreadexecutor.cpp \ testtoken.cpp \ testtokenize.cpp \ From 2b77e3591ed5d61eac61fc17ae52b7f5a2c8fbe3 Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 18:57:45 -0600 Subject: [PATCH 26/40] Add rules for tokAt(0) and strAt(0), suggested by reif --- rules/token-matching.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rules/token-matching.xml b/rules/token-matching.xml index 47110c4b5..3371f3496 100644 --- a/rules/token-matching.xml +++ b/rules/token-matching.xml @@ -16,3 +16,19 @@ without special pattern requirements. + + \b[\w_]+ \. tokAt \( 0 \) + + TokentokAt0 + error + tok->tokAt(0) is a slow way to say tok. + + + + \b[\w_]+ \. strAt \( 0 \) + + TokenstrAt0 + error + tok->strAt(0) is a slow way to say tok->str() + + From 43b0e655bbdc87f57f08d4228e44771d8340abef Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Wed, 2 Feb 2011 20:08:03 -0600 Subject: [PATCH 27/40] Add a few more rules --- rules/error-reporting.xml | 10 ++++++++++ rules/stl.xml | 11 +++++++++++ 2 files changed, 21 insertions(+) create mode 100644 rules/error-reporting.xml create mode 100644 rules/stl.xml diff --git a/rules/error-reporting.xml b/rules/error-reporting.xml new file mode 100644 index 000000000..2813c9bba --- /dev/null +++ b/rules/error-reporting.xml @@ -0,0 +1,10 @@ + + + Severity :: fromString \( "\w+" \) + + ConstantSeverityFromString + style + Constant severity lookups should be done via +Severity::constant. + + diff --git a/rules/stl.xml b/rules/stl.xml new file mode 100644 index 000000000..e98d55831 --- /dev/null +++ b/rules/stl.xml @@ -0,0 +1,11 @@ + + + + \. find \( "[^"]+?" \) == \d+ + + UselessSTDStringFind + performance + When looking for a string at a fixed position compare +is faster. + + From 8288c28b3fd2536838fee8f565cea39dd03faa2c Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Thu, 3 Feb 2011 07:57:10 +0100 Subject: [PATCH 28/40] Fixed #2537 (segmentation fault of cppcheck) --- lib/symboldatabase.cpp | 34 ++++++++++++++++++++++++++++++++-- lib/symboldatabase.h | 6 ++++++ test/testclass.cpp | 15 +++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index b7e9f8ea3..a9634b2d1 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -254,9 +254,19 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti } } - // nested class function? + // nested class or friend function? else if (tok->previous()->str() == "::" && isFunction(tok, &funcStart, &argStart)) - addFunction(&scope, &tok, argStart); + { + /** @todo check entire qualification for match */ + Scope * nested = scope->findInNestedListRecursive(tok->strAt(-2)); + + if (nested) + addFunction(&scope, &tok, argStart); + else + { + /** @todo handle friend functions */ + } + } // friend class declaration? else if (Token::Match(tok, "friend class| %any% ;")) @@ -1398,6 +1408,26 @@ Scope * Scope::findInNestedList(const std::string & name) //--------------------------------------------------------------------------- +Scope * Scope::findInNestedListRecursive(const std::string & name) +{ + std::list::iterator it; + + for (it = nestedList.begin(); it != nestedList.end(); ++it) + { + if ((*it)->className == name) + return (*it); + } + + for (it = nestedList.begin(); it != nestedList.end(); ++it) + { + Scope *child = (*it)->findInNestedListRecursive(name); + return child; + } + return 0; +} + +//--------------------------------------------------------------------------- + const Function *Scope::getDestructor() const { std::list::const_iterator it; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index e8c858c3d..4e04f4d5a 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -311,6 +311,12 @@ public: */ Scope * findInNestedList(const std::string & name); + /** + * @brief find if name is in nested list + * @param name name of nested scope + */ + Scope * findInNestedListRecursive(const std::string & name); + void addVariable(const Token *token_, AccessControl access_, bool mutable_, bool static_, bool const_, bool class_, const Scope *type_) { varlist.push_back(Variable(token_, varlist.size(), access_, mutable_, static_, const_, class_, type_)); diff --git a/test/testclass.cpp b/test/testclass.cpp index 03080cfb8..ffeac3df6 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -188,6 +188,7 @@ private: TEST_CASE(symboldatabase7); // ticket #2230 TEST_CASE(symboldatabase8); // ticket #2252 TEST_CASE(symboldatabase9); // ticket #2525 + TEST_CASE(symboldatabase10); // ticket #2537 } // Check the operator Equal @@ -5490,6 +5491,20 @@ private: ASSERT_EQUALS("", errout.str()); } + void symboldatabase10() + { + // ticket #2537 - segmentation fault + checkConst("class A {\n" + "private:\n" + " void f();\n" + "};\n" + "class B {\n" + " friend void A::f();\n" + "};\n"); + + ASSERT_EQUALS("", errout.str()); + } + }; REGISTER_TEST(TestClass) From e9ec4bc3e41cd13307c9e9c75ea49d65a4dd558d Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Thu, 3 Feb 2011 07:58:49 +0100 Subject: [PATCH 29/40] Fixed #2536 (cppcheck hangs with 100% cpu load) --- lib/tokenize.cpp | 36 +++++++++++++++++++++++++++++++----- test/testsimplifytokens.cpp | 8 ++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 49d752020..5c7cfaf2d 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -824,7 +824,8 @@ void Tokenizer::simplifyTypedef() if (_errorLogger && !_files.empty()) _errorLogger->reportProgress(_files[0], "Tokenize (typedef)", tok->progressValue()); - if (Token::Match(tok, "class|struct|namespace %any%")) + if (Token::Match(tok, "class|struct|namespace %any%") && + (!tok->previous() || (tok->previous() && tok->previous()->str() != "enum"))) { isNamespace = (tok->str() == "namespace"); hasClass = true; @@ -7549,7 +7550,8 @@ void Tokenizer::simplifyEnum() int classLevel = 0; for (Token *tok = _tokens; tok; tok = tok->next()) { - if (Token::Match(tok, "class|struct|namespace %any%")) + if (Token::Match(tok, "class|struct|namespace %any%") && + (!tok->previous() || (tok->previous() && tok->previous()->str() != "enum"))) { className = tok->next()->str(); classLevel = 0; @@ -7569,7 +7571,7 @@ void Tokenizer::simplifyEnum() continue; } else if (Token::Match(tok, "enum class|struct| {|:") || - Token::Match(tok, "enum class|struct| %type% {|:")) + Token::Match(tok, "enum class|struct| %type% {|:|;")) { Token *tok1; Token *start = tok; @@ -7590,12 +7592,19 @@ void Tokenizer::simplifyEnum() offset = 3; // check for forward declaration - /** @todo start substitution check at forward declaration */ const Token *temp = tok->tokAt(offset); while (!Token::Match(temp, "{|;")) temp = temp->next(); if (temp->str() == ";") + { + /** @todo start substitution check at forward declaration */ + // delete forward declaration + tok->deleteThis(); + tok->deleteThis(); + tok->deleteThis(); + tok->deleteThis(); continue; + } typeTokenStart = tok->tokAt(offset); typeTokenEnd = typeTokenStart; @@ -7609,6 +7618,16 @@ void Tokenizer::simplifyEnum() } } + // check for forward declaration + else if (Token::Match(tok->next(), "%type% ;")) + { + /** @todo start substitution check at forward declaration */ + // delete forward declaration + tok->deleteThis(); + tok->deleteThis(); + continue; + } + if (tok->tokAt(1)->str() == "{") tok1 = tok->tokAt(2); else if (tok->tokAt(1)->str() == ":") @@ -9254,6 +9273,12 @@ void Tokenizer::simplifyQtSignalsSlots() Token *tok = _tokens; while ((tok = const_cast(Token::findmatch(tok, "class %var% :")))) { + if (tok->previous() && tok->previous()->str() == "enum") + { + tok = tok->tokAt(2); + continue; + } + // count { and } for tok2 unsigned int indentlevel = 0; for (Token *tok2 = tok; tok2; tok2 = tok2->next()) @@ -9341,7 +9366,8 @@ void Tokenizer::removeUnnecessaryQualification() std::stack classInfo; for (Token *tok = _tokens; tok; tok = tok->next()) { - if (Token::Match(tok, "class|struct %type% :|{")) + if (Token::Match(tok, "class|struct %type% :|{") && + (!tok->previous() || (tok->previous() && tok->previous()->str() != "enum"))) { tok = tok->next(); ClassInfo info; diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 9ba7bc197..0de4ff250 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -278,6 +278,7 @@ private: TEST_CASE(enum16); // ticket #1988 TEST_CASE(enum17); // ticket #2381 (duplicate enums) TEST_CASE(enum18); // #2466 (array with same name as enum constant) + TEST_CASE(enum19); // ticket #2536 // remove "std::" on some standard functions TEST_CASE(removestd); @@ -6099,6 +6100,13 @@ private: ASSERT_EQUALS("; void f ( ) { a [ 0 ] ; }", tok(code, false)); } + void enum19() // ticket #2536 + { + const char code[] = "enum class E1;\n" + "enum class E2 : int;\n"; + ASSERT_EQUALS(";", tok(code, false)); + } + void removestd() { ASSERT_EQUALS("; strcpy ( a , b ) ;", tok("; std::strcpy(a,b);")); From f65fa338a50fbb0f8d6a6b2555499f5981869c2f Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Thu, 3 Feb 2011 08:56:28 +0200 Subject: [PATCH 30/40] Tighten the directory name mathing with -i. Only match full directory names as parts of whole paths. So -isrc matches src/file.cpp and proj/src/file.cpp. But does not match mysrc/file.cpp or proj/srcfiles/file.cpp. --- cli/pathmatch.cpp | 9 ++++++++- test/testpathmatch.cpp | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/cli/pathmatch.cpp b/cli/pathmatch.cpp index 25ed6cd71..270f5c1da 100644 --- a/cli/pathmatch.cpp +++ b/cli/pathmatch.cpp @@ -35,7 +35,14 @@ bool PathMatch::Match(const std::string &path) if (findpath[findpath.length() - 1] != '/') findpath = RemoveFilename(findpath); - if (findpath.find(*iterMask) != std::string::npos) + // Match relative paths starting with mask + // -isrc matches src/foo.cpp + if (findpath.compare(0, (*iterMask).size(), *iterMask) == 0) + return true; + // Match only full directory name in middle or end of the path + // -isrc matches myproject/src/ but does not match + // myproject/srcfiles/ or myproject/mysrc/ + if (findpath.find("/" + *iterMask) != std::string::npos) return true; } return false; diff --git a/test/testpathmatch.cpp b/test/testpathmatch.cpp index dadeef311..f929308e7 100644 --- a/test/testpathmatch.cpp +++ b/test/testpathmatch.cpp @@ -38,6 +38,10 @@ private: TEST_CASE(onemaskemptypath); TEST_CASE(onemasksamepath); TEST_CASE(onemasksamepathwithfile); + TEST_CASE(onemaskdifferentdir1); + TEST_CASE(onemaskdifferentdir2); + TEST_CASE(onemaskdifferentdir3); + TEST_CASE(onemaskdifferentdir4); TEST_CASE(onemasklongerpath1); TEST_CASE(onemasklongerpath2); TEST_CASE(onemasklongerpath3); @@ -95,6 +99,38 @@ private: ASSERT(match.Match("src/file.txt")); } + void onemaskdifferentdir1() + { + std::vector masks; + masks.push_back("src/"); + PathMatch match(masks); + ASSERT(!match.Match("srcfiles/file.txt")); + } + + void onemaskdifferentdir2() + { + std::vector masks; + masks.push_back("src/"); + PathMatch match(masks); + ASSERT(!match.Match("proj/srcfiles/file.txt")); + } + + void onemaskdifferentdir3() + { + std::vector masks; + masks.push_back("src/"); + PathMatch match(masks); + ASSERT(!match.Match("proj/mysrc/file.txt")); + } + + void onemaskdifferentdir4() + { + std::vector masks; + masks.push_back("src/"); + PathMatch match(masks); + ASSERT(!match.Match("proj/mysrcfiles/file.txt")); + } + void onemasklongerpath1() { std::vector masks; From 9b9b9c99f53ccb84a3f489be6b6ff4d86013c8dd Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Thu, 3 Feb 2011 09:44:23 +0200 Subject: [PATCH 31/40] Add test for XML format version 2. --- test/testerrorlogger.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/testerrorlogger.cpp b/test/testerrorlogger.cpp index fd10cba36..e716602a5 100644 --- a/test/testerrorlogger.cpp +++ b/test/testerrorlogger.cpp @@ -17,6 +17,7 @@ */ #include +#include "cppcheck.h" #include "testsuite.h" #include "errorlogger.h" @@ -38,6 +39,7 @@ private: TEST_CASE(CustomFormat2); TEST_CASE(ToXml); TEST_CASE(ToVerboseXml); + TEST_CASE(ToXmlV2); } void FileLocationDefaults() @@ -140,5 +142,25 @@ private: ASSERT_EQUALS("", ErrorLogger::ErrorMessage::getXMLFooter(1)); ASSERT_EQUALS("", msg.toXML(true,1)); } + + void ToXmlV2() + { + ErrorLogger::ErrorMessage::FileLocation loc; + loc.setfile("foo.cpp"); + loc.line = 5; + std::list locs; + locs.push_back(loc); + ErrorMessage msg(locs, Severity::error, "Programming error.\nVerbose error", "errorId"); + std::string header("\n\n"); + header += " \n "; + ASSERT_EQUALS(header, ErrorLogger::ErrorMessage::getXMLHeader(2)); + ASSERT_EQUALS(" \n", ErrorLogger::ErrorMessage::getXMLFooter(2)); + std::string message(" \n"; + message += " \n "; + ASSERT_EQUALS(message, msg.toXML(false,2)); + } }; REGISTER_TEST(TestErrorLogger) From 96d62553bc266145158ccadc2e1b21014a809322 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Thu, 3 Feb 2011 11:48:16 +0200 Subject: [PATCH 32/40] Make FileLister::acceptFile() a static method. We don't need different acceptFile() implementations per platform so it is better to have one static method. --- cli/filelister.h | 2 +- cli/filelister_unix.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/filelister.h b/cli/filelister.h index aa292b701..4c6cd7d03 100644 --- a/cli/filelister.h +++ b/cli/filelister.h @@ -55,7 +55,7 @@ public: * @param filename filename to check * @return returns true if the file extension indicates it should be checked */ - virtual bool acceptFile(const std::string &filename); + static bool acceptFile(const std::string &filename); /** * @brief Is given path a directory? diff --git a/cli/filelister_unix.cpp b/cli/filelister_unix.cpp index ed6d12f4b..f9263eb78 100644 --- a/cli/filelister_unix.cpp +++ b/cli/filelister_unix.cpp @@ -72,7 +72,7 @@ void FileListerUnix::recursiveAddFiles2(std::vector &relative, continue; } - if (Path::sameFileName(path,filename) || FileListerUnix::acceptFile(filename)) + if (Path::sameFileName(path,filename) || FileLister::acceptFile(filename)) { relative.push_back(filename); absolute.push_back(fname); From 2d6d8580d73cbd86f95b21f6a8776e646f8087e5 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Thu, 3 Feb 2011 14:43:42 +0200 Subject: [PATCH 33/40] Allow to exclude filenames (with paths). This expands the CLI exclude feature to also allow excluding filenames (with paths). When filename with recognized extension is given to -i option then matching filenames (with paths) are ignored when checking. Ticket #2538 (Allow excluding files from the checking) --- cli/cmdlineparser.cpp | 22 +++++++++----- cli/pathmatch.cpp | 42 ++++++++++++++++++-------- test/testcmdlineparser.cpp | 24 +++++++++++++++ test/testpathmatch.cpp | 62 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 20 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 10482e6fc..b64229edf 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -26,6 +26,7 @@ #include "settings.h" #include "cmdlineparser.h" #include "path.h" +#include "filelister.h" // xml is used in rules #include "tinyxml/tinyxml.h" @@ -361,7 +362,7 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) path = argv[i]; } - // "-Ipath/" + // "-ipath/" else { path = 2 + argv[i]; @@ -371,10 +372,13 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) { path = Path::fromNativeSeparators(path); - // If path doesn't end with / or \, add it - if (path[path.length()-1] != '/') - path += '/'; - + // If not "known" filename extension then assume it is path + if (!FileLister::acceptFile(path)) + { + // If path doesn't end with / or \, add it + if (path[path.length()-1] != '/') + path += '/'; + } _ignoredPaths.push_back(path); } } @@ -514,7 +518,8 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) if (doc.LoadFile(12+argv[i])) { TiXmlElement *node = doc.FirstChildElement(); - for (; node && node->ValueStr() == "rule"; node = node->NextSiblingElement()) { + for (; node && node->ValueStr() == "rule"; node = node->NextSiblingElement()) + { Settings::Rule rule; TiXmlElement *pattern = node->FirstChildElement("pattern"); @@ -641,8 +646,9 @@ void CmdLineParser::PrintHelp() " several paths. First given path is checked first. If\n" " paths are relative to source files, this is not needed\n" " -i [dir] Give path to ignore. Give several -i parameters to ignore\n" - " several paths. If any part of the checked path matches the\n" - " given dir the path is ignored and not checked.\n" + " several paths. Give directory name or filename with path\n" + " as parameter. Directory name is matched to all parts of the\n" + " path." " --inline-suppr Enable inline suppressions. Use them by placing one or\n" " more comments, like: // cppcheck-suppress warningId\n" " on the lines before the warning to suppress.\n" diff --git a/cli/pathmatch.cpp b/cli/pathmatch.cpp index 270f5c1da..db36d99c9 100644 --- a/cli/pathmatch.cpp +++ b/cli/pathmatch.cpp @@ -31,19 +31,37 @@ bool PathMatch::Match(const std::string &path) std::vector::const_iterator iterMask; for (iterMask = _masks.begin(); iterMask != _masks.end(); ++iterMask) { - std::string findpath(path); - if (findpath[findpath.length() - 1] != '/') - findpath = RemoveFilename(findpath); + // Filtering directory name + if ((*iterMask)[(*iterMask).length() - 1] == '/') + { + std::string findpath(path); + if (findpath[findpath.length() - 1] != '/') + findpath = RemoveFilename(findpath); - // Match relative paths starting with mask - // -isrc matches src/foo.cpp - if (findpath.compare(0, (*iterMask).size(), *iterMask) == 0) - return true; - // Match only full directory name in middle or end of the path - // -isrc matches myproject/src/ but does not match - // myproject/srcfiles/ or myproject/mysrc/ - if (findpath.find("/" + *iterMask) != std::string::npos) - return true; + if ((*iterMask).length() > findpath.length()) + continue; + // Match relative paths starting with mask + // -isrc matches src/foo.cpp + if (findpath.compare(0, (*iterMask).size(), *iterMask) == 0) + return true; + // Match only full directory name in middle or end of the path + // -isrc matches myproject/src/ but does not match + // myproject/srcfiles/ or myproject/mysrc/ + if (findpath.find("/" + *iterMask) != std::string::npos) + return true; + } + // Filtering filename + else + { + if ((*iterMask).length() > path.length()) + continue; + // Check if path ends with mask + // -ifoo.cpp matches (./)foo.c, src/foo.cpp and proj/src/foo.cpp + // -isrc/file.cpp matches src/foo.cpp and proj/src/foo.cpp + if (path.compare(path.size() - (*iterMask).size(), path.size(), *iterMask) == 0) + return true; + + } } return false; } diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 91cd92e01..bdbd1e4d7 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -95,6 +95,8 @@ private: TEST_CASE(ignorepaths2) TEST_CASE(ignorepaths3) TEST_CASE(ignorepaths4) + TEST_CASE(ignorefilepaths1) + TEST_CASE(ignorefilepaths2) TEST_CASE(unknownParam); } @@ -740,6 +742,28 @@ private: ASSERT_EQUALS("module/", parser.GetIgnoredPaths()[1]); } + void ignorefilepaths1() + { + REDIRECT; + const char *argv[] = {"cppcheck", "-ifoo.cpp", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(parser.ParseFromArgs(3, argv)); + ASSERT_EQUALS(1, parser.GetIgnoredPaths().size()); + ASSERT_EQUALS("foo.cpp", parser.GetIgnoredPaths()[0]); + } + + void ignorefilepaths2() + { + REDIRECT; + const char *argv[] = {"cppcheck", "-isrc/foo.cpp", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(parser.ParseFromArgs(3, argv)); + ASSERT_EQUALS(1, parser.GetIgnoredPaths().size()); + ASSERT_EQUALS("src/foo.cpp", parser.GetIgnoredPaths()[0]); + } + void unknownParam() { REDIRECT; diff --git a/test/testpathmatch.cpp b/test/testpathmatch.cpp index f929308e7..1f552e0f8 100644 --- a/test/testpathmatch.cpp +++ b/test/testpathmatch.cpp @@ -45,6 +45,13 @@ private: TEST_CASE(onemasklongerpath1); TEST_CASE(onemasklongerpath2); TEST_CASE(onemasklongerpath3); + TEST_CASE(filemask1); + TEST_CASE(filemask2); + TEST_CASE(filemask3); + TEST_CASE(filemaskpath1); + TEST_CASE(filemaskpath2); + TEST_CASE(filemaskpath3); + TEST_CASE(filemaskpath4); } void emptymaskemptyfile() @@ -191,6 +198,61 @@ private: ASSERT(match.Match("project/src/module/")); } + void filemask1() + { + std::vector masks; + masks.push_back("foo.cpp"); + PathMatch match(masks); + ASSERT(match.Match("foo.cpp")); + } + + void filemask2() + { + std::vector masks; + masks.push_back("foo.cpp"); + PathMatch match(masks); + ASSERT(match.Match("../foo.cpp")); + } + + void filemask3() + { + std::vector masks; + masks.push_back("foo.cpp"); + PathMatch match(masks); + ASSERT(match.Match("src/foo.cpp")); + } + + void filemaskpath1() + { + std::vector masks; + masks.push_back("src/foo.cpp"); + PathMatch match(masks); + ASSERT(match.Match("src/foo.cpp")); + } + + void filemaskpath2() + { + std::vector masks; + masks.push_back("src/foo.cpp"); + PathMatch match(masks); + ASSERT(match.Match("proj/src/foo.cpp")); + } + + void filemaskpath3() + { + std::vector masks; + masks.push_back("src/foo.cpp"); + PathMatch match(masks); + ASSERT(!match.Match("foo.cpp")); + } + + void filemaskpath4() + { + std::vector masks; + masks.push_back("src/foo.cpp"); + PathMatch match(masks); + ASSERT(!match.Match("bar/foo.cpp")); + } }; REGISTER_TEST(TestPathMatch) From 85187dca07fc9546be1837c2f4533026ac82f136 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Thu, 3 Feb 2011 17:53:50 +0200 Subject: [PATCH 34/40] Update VS 2008/2010 project files for tests. --- test/test.vcproj | 2 ++ test/test.vcxproj | 1 + test/test.vcxproj.filters | 3 +++ 3 files changed, 6 insertions(+) diff --git a/test/test.vcproj b/test/test.vcproj index e4b4589c6..bc314d136 100755 --- a/test/test.vcproj +++ b/test/test.vcproj @@ -229,6 +229,8 @@ RelativePath="teststl.cpp" /> + + diff --git a/test/test.vcxproj.filters b/test/test.vcxproj.filters index 027fb94a8..deb632b52 100644 --- a/test/test.vcxproj.filters +++ b/test/test.vcxproj.filters @@ -170,6 +170,9 @@ Source Files + + Source Files + Source Files From 21d6c26e3009a158597d462cf8006b5969842b2c Mon Sep 17 00:00:00 2001 From: Tim Gerundt Date: Thu, 3 Feb 2011 20:25:55 +0100 Subject: [PATCH 35/40] Web: Add RSS link to Trac Timeline --- htdocs/devinfo/index.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/devinfo/index.php b/htdocs/devinfo/index.php index cb40209f9..dbfeeab23 100644 --- a/htdocs/devinfo/index.php +++ b/htdocs/devinfo/index.php @@ -7,6 +7,8 @@ +