From a3a4d72082cda410e46e64b0e871d64abcc4b996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 30 Oct 2008 19:42:34 +0000 Subject: [PATCH] preprocessor: Use the new preprocessor in cppcheck --- main.cpp | 32 +++++++++++++++------- preprocessor.cpp | 19 +++++++------ testpreprocessor.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++ tokenize.cpp | 20 ++++++-------- tokenize.h | 2 +- 5 files changed, 106 insertions(+), 30 deletions(-) diff --git a/main.cpp b/main.cpp index b4c39248d..3c3dceb42 100644 --- a/main.cpp +++ b/main.cpp @@ -17,6 +17,7 @@ */ +#include "preprocessor.h" // preprocessor. #include "tokenize.h" // <- Tokenizer #include "CommonCheck.h" @@ -30,6 +31,8 @@ #include #include #include +#include +#include // Check that the compiler are supported @@ -62,7 +65,7 @@ bool ShowAll = false; bool CheckCodingStyle = false; //--------------------------------------------------------------------------- -static void CppCheck(const char FileName[], unsigned int FileId); +static void CppCheck(const std::string &code, const char FileName[], unsigned int FileId); static void AddFiles( std::vector &filenames, const char path[], const char pattern[] ) @@ -230,8 +233,20 @@ int main(int argc, char* argv[]) for (unsigned int c = 0; c < filenames.size(); c++) { errout.str(""); - CppCheck(filenames[c].c_str(), c); - std::cerr << errout.str(); + std::string fname = filenames[c]; + + std::cout << "Checking " << fname << "...\n"; + + std::ifstream fin( fname.c_str() ); + std::map code; + preprocess(fin, code); + for ( std::map::const_iterator it = code.begin(); it != code.end(); ++it ) + CppCheck(it->second, filenames[c].c_str(), c); + + if ( errout.str().empty() ) + std::cout << "No errors found\n"; + else + std::cerr << errout.str(); } // This generates false positives - especially for libraries @@ -254,16 +269,17 @@ int main(int argc, char* argv[]) // CppCheck - A function that checks a specified file //--------------------------------------------------------------------------- -static void CppCheck(const char FileName[], unsigned int FileId) +static void CppCheck(const std::string &code, const char FileName[], unsigned int FileId) { OnlyReportUniqueErrors = true; - std::cout << "Checking " << FileName << "...\n"; - // Tokenize the file tokens = tokens_back = NULL; Files.clear(); - Tokenize(FileName); + { + std::istringstream istr(code); + Tokenize(istr, FileName); + } FillFunctionList(FileId); @@ -362,8 +378,6 @@ static void CppCheck(const char FileName[], unsigned int FileId) // Clean up tokens.. DeallocateTokens(); - if ( errout.str().empty() ) - std::cout << "No errors found\n"; } //--------------------------------------------------------------------------- diff --git a/preprocessor.cpp b/preprocessor.cpp index add5462af..c258a04b6 100644 --- a/preprocessor.cpp +++ b/preprocessor.cpp @@ -50,7 +50,7 @@ void preprocess(std::istream &istr, std::map &result) bool ignoreSpace = true; std::ostringstream code; - for (char ch = (char)istr.get(); !istr.eof(); ch = (char)istr.get()) + for (char ch = (char)istr.get(); istr.good(); ch = (char)istr.get()) { // Replace assorted special chars with spaces.. if ( ch < 0 ) @@ -70,7 +70,7 @@ void preprocess(std::istream &istr, std::map &result) if ( chNext == '/' ) { - while (!istr.eof() && ch!='\n') + while (istr.good() && ch!='\n') ch = (char)istr.get(); code << "\n"; } @@ -78,7 +78,7 @@ void preprocess(std::istream &istr, std::map &result) else if ( chNext == '*' ) { char chPrev = 0; - while (!istr.eof() && (chPrev!='*' || ch!='/')) + while (istr.good() && (chPrev!='*' || ch!='/')) { chPrev = ch; ch = (char)istr.get(); @@ -106,7 +106,7 @@ void preprocess(std::istream &istr, std::map &result) ch = (char)istr.get(); code << std::string(1,ch); } - } while ( !istr.eof() && ch != '\"' ); + } while ( istr.good() && ch != '\"' ); } // char constants.. @@ -222,7 +222,7 @@ static std::list getcfgs( const std::string &filedata ) deflist.push_back( def ); } - if ( line.find("#endif") == 0 ) + if ( line.find("#endif") == 0 && ! deflist.empty() ) deflist.pop_back(); } @@ -275,13 +275,16 @@ static std::string getcode(const std::string &filedata, std::string cfg) else if ( ! ndef.empty() ) matching_ifdef.push_back( ! match_cfg_def(cfg, ndef) ); - else if ( line == "#else" ) + else if ( line == "#else" && !matching_ifdef.empty() ) matching_ifdef.back() = ! matching_ifdef.back(); - else if ( line == "#endif" ) + else if ( line == "#endif" && !matching_ifdef.empty() ) matching_ifdef.pop_back(); - if ( !matching_ifdef.empty() && !matching_ifdef.back() ) + bool match = true; + for ( std::list::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it ) + match &= *it; + if ( ! match ) line = ""; if ( line.find("#if") == 0 || diff --git a/testpreprocessor.cpp b/testpreprocessor.cpp index 2b335543d..0dc288ad7 100644 --- a/testpreprocessor.cpp +++ b/testpreprocessor.cpp @@ -37,6 +37,10 @@ private: void run() { + // The bug that started the whole work with the new preprocessor + TEST_CASE( Bug2190219 ); + + TEST_CASE( test1 ); TEST_CASE( test2 ); TEST_CASE( test3 ); @@ -80,6 +84,65 @@ private: } + void Bug2190219() + { + const char filedata[] = "int main()\n" + "{\n" + "#ifdef __cplusplus\n" + " int* flags = new int[10];\n" + "#else\n" + " int* flags = (int*)malloc((10)*sizeof(int));\n" + "#endif\n" + "\n" + "#ifdef __cplusplus\n" + " delete [] flags;\n" + "#else\n" + " free(flags);\n" + "#endif\n" + "}\n"; + + // Expected result.. + std::map expected; + expected[""] = "int main()\n" + "{\n" + "\n" + "\n" + "\n" + "int* flags = (int*)malloc((10)*sizeof(int));\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "free(flags);\n" + "\n" + "}\n"; + + expected["__cplusplus"] = "int main()\n" + "{\n" + "\n" + "int* flags = new int[10];\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "delete [] flags;\n" + "\n" + "\n" + "\n" + "}\n"; + + // Preprocess => actual result.. + std::istringstream istr(filedata); + std::map actual; + preprocess( istr, actual ); + + // Compare results.. + ASSERT_EQUALS( true, cmpmaps(actual, expected)); + } + + void test1() { const char filedata[] = "#ifdef WIN32 \n" diff --git a/tokenize.cpp b/tokenize.cpp index eb9873e81..ddbd0d0bf 100644 --- a/tokenize.cpp +++ b/tokenize.cpp @@ -286,7 +286,7 @@ static void InsertTokens(TOKEN *dest, TOKEN *src, unsigned int n) // Tokenize - tokenizes a given file. //--------------------------------------------------------------------------- -void Tokenize(const char FileName[]) +void Tokenize(std::istream &code, const char FileName[]) { // Has this file been tokenized already? for (unsigned int i = 0; i < Files.size(); i++) @@ -295,16 +295,11 @@ void Tokenize(const char FileName[]) return; } - // Open file.. - std::ifstream fin(FileName); - if (!fin.is_open()) - return; - // The "Files" vector remembers what files have been tokenized.. Files.push_back(FileName); // Tokenize the file.. - TokenizeCode( fin, Files.size() - 1 ); + TokenizeCode( code, Files.size() - 1 ); } //--------------------------------------------------------------------------- @@ -322,7 +317,7 @@ void TokenizeCode(std::istream &code, const unsigned int FileIndex) unsigned int lineno = 1; char CurrentToken[1000] = {0}; char *pToken = CurrentToken; - for (char ch = (char)code.get(); !code.eof(); ch = (char)code.get()) + for (char ch = (char)code.get(); code.good(); ch = (char)code.get()) { // Todo if ( ch < 0 ) @@ -352,7 +347,8 @@ void TokenizeCode(std::istream &code, const unsigned int FileIndex) addtoken("#include", lineno, FileIndex); addtoken(line.c_str(), lineno, FileIndex); - Tokenize(line.c_str()); + std::ifstream fin( line.c_str() ); + Tokenize(fin, line.c_str()); } else if (strncmp(line.c_str(), "#define", 7) == 0) @@ -422,7 +418,7 @@ void TokenizeCode(std::istream &code, const unsigned int FileIndex) } // Comments.. - if (ch == '/' && !code.eof()) + if (ch == '/' && code.good()) { bool newstatement = bool( strchr(";{}", CurrentToken[0]) != NULL ); @@ -466,7 +462,7 @@ void TokenizeCode(std::istream &code, const unsigned int FileIndex) { char chPrev; ch = chPrev = 'A'; - while (!code.eof() && (chPrev!='*' || ch!='/')) + while (code.good() && (chPrev!='*' || ch!='/')) { chPrev = ch; ch = (char)code.get(); @@ -528,7 +524,7 @@ void TokenizeCode(std::istream &code, const unsigned int FileIndex) // Get next character c = (char)code.get(); } - while (!code.eof() && (special || c != '\"')); + while (code.good() && (special || c != '\"')); *pToken = '\"'; addtoken(CurrentToken, lineno, FileIndex); memset(CurrentToken, 0, sizeof(CurrentToken)); diff --git a/tokenize.h b/tokenize.h index c52040545..aec12b7ab 100644 --- a/tokenize.h +++ b/tokenize.h @@ -37,7 +37,7 @@ struct TOKEN extern struct TOKEN *tokens, *tokens_back; -void Tokenize(const char FileName[]); +void Tokenize(std::istream &code, const char FileName[]); void TokenizeCode(std::istream &code, const unsigned int FileIndex=0);