preprocessor: Use the new preprocessor in cppcheck

This commit is contained in:
Daniel Marjamäki 2008-10-30 19:42:34 +00:00
parent 3bf539939f
commit a3a4d72082
5 changed files with 106 additions and 30 deletions

View File

@ -17,6 +17,7 @@
*/ */
#include "preprocessor.h" // preprocessor.
#include "tokenize.h" // <- Tokenizer #include "tokenize.h" // <- Tokenizer
#include "CommonCheck.h" #include "CommonCheck.h"
@ -30,6 +31,8 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <cstring> #include <cstring>
#include <fstream>
#include <map>
// Check that the compiler are supported // Check that the compiler are supported
@ -62,7 +65,7 @@ bool ShowAll = false;
bool CheckCodingStyle = 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<std::string> &filenames, const char path[], const char pattern[] ) static void AddFiles( std::vector<std::string> &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++) for (unsigned int c = 0; c < filenames.size(); c++)
{ {
errout.str(""); errout.str("");
CppCheck(filenames[c].c_str(), c); std::string fname = filenames[c];
std::cerr << errout.str();
std::cout << "Checking " << fname << "...\n";
std::ifstream fin( fname.c_str() );
std::map<std::string, std::string> code;
preprocess(fin, code);
for ( std::map<std::string,std::string>::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 // 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 // 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; OnlyReportUniqueErrors = true;
std::cout << "Checking " << FileName << "...\n";
// Tokenize the file // Tokenize the file
tokens = tokens_back = NULL; tokens = tokens_back = NULL;
Files.clear(); Files.clear();
Tokenize(FileName); {
std::istringstream istr(code);
Tokenize(istr, FileName);
}
FillFunctionList(FileId); FillFunctionList(FileId);
@ -362,8 +378,6 @@ static void CppCheck(const char FileName[], unsigned int FileId)
// Clean up tokens.. // Clean up tokens..
DeallocateTokens(); DeallocateTokens();
if ( errout.str().empty() )
std::cout << "No errors found\n";
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -50,7 +50,7 @@ void preprocess(std::istream &istr, std::map<std::string, std::string> &result)
bool ignoreSpace = true; bool ignoreSpace = true;
std::ostringstream code; 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.. // Replace assorted special chars with spaces..
if ( ch < 0 ) if ( ch < 0 )
@ -70,7 +70,7 @@ void preprocess(std::istream &istr, std::map<std::string, std::string> &result)
if ( chNext == '/' ) if ( chNext == '/' )
{ {
while (!istr.eof() && ch!='\n') while (istr.good() && ch!='\n')
ch = (char)istr.get(); ch = (char)istr.get();
code << "\n"; code << "\n";
} }
@ -78,7 +78,7 @@ void preprocess(std::istream &istr, std::map<std::string, std::string> &result)
else if ( chNext == '*' ) else if ( chNext == '*' )
{ {
char chPrev = 0; char chPrev = 0;
while (!istr.eof() && (chPrev!='*' || ch!='/')) while (istr.good() && (chPrev!='*' || ch!='/'))
{ {
chPrev = ch; chPrev = ch;
ch = (char)istr.get(); ch = (char)istr.get();
@ -106,7 +106,7 @@ void preprocess(std::istream &istr, std::map<std::string, std::string> &result)
ch = (char)istr.get(); ch = (char)istr.get();
code << std::string(1,ch); code << std::string(1,ch);
} }
} while ( !istr.eof() && ch != '\"' ); } while ( istr.good() && ch != '\"' );
} }
// char constants.. // char constants..
@ -222,7 +222,7 @@ static std::list<std::string> getcfgs( const std::string &filedata )
deflist.push_back( def ); deflist.push_back( def );
} }
if ( line.find("#endif") == 0 ) if ( line.find("#endif") == 0 && ! deflist.empty() )
deflist.pop_back(); deflist.pop_back();
} }
@ -275,13 +275,16 @@ static std::string getcode(const std::string &filedata, std::string cfg)
else if ( ! ndef.empty() ) else if ( ! ndef.empty() )
matching_ifdef.push_back( ! match_cfg_def(cfg, ndef) ); 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(); matching_ifdef.back() = ! matching_ifdef.back();
else if ( line == "#endif" ) else if ( line == "#endif" && !matching_ifdef.empty() )
matching_ifdef.pop_back(); matching_ifdef.pop_back();
if ( !matching_ifdef.empty() && !matching_ifdef.back() ) bool match = true;
for ( std::list<bool>::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it )
match &= *it;
if ( ! match )
line = ""; line = "";
if ( line.find("#if") == 0 || if ( line.find("#if") == 0 ||

View File

@ -37,6 +37,10 @@ private:
void run() void run()
{ {
// The bug that started the whole work with the new preprocessor
TEST_CASE( Bug2190219 );
TEST_CASE( test1 ); TEST_CASE( test1 );
TEST_CASE( test2 ); TEST_CASE( test2 );
TEST_CASE( test3 ); 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<std::string, std::string> 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<std::string, std::string> actual;
preprocess( istr, actual );
// Compare results..
ASSERT_EQUALS( true, cmpmaps(actual, expected));
}
void test1() void test1()
{ {
const char filedata[] = "#ifdef WIN32 \n" const char filedata[] = "#ifdef WIN32 \n"

View File

@ -286,7 +286,7 @@ static void InsertTokens(TOKEN *dest, TOKEN *src, unsigned int n)
// Tokenize - tokenizes a given file. // Tokenize - tokenizes a given file.
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void Tokenize(const char FileName[]) void Tokenize(std::istream &code, const char FileName[])
{ {
// Has this file been tokenized already? // Has this file been tokenized already?
for (unsigned int i = 0; i < Files.size(); i++) for (unsigned int i = 0; i < Files.size(); i++)
@ -295,16 +295,11 @@ void Tokenize(const char FileName[])
return; return;
} }
// Open file..
std::ifstream fin(FileName);
if (!fin.is_open())
return;
// The "Files" vector remembers what files have been tokenized.. // The "Files" vector remembers what files have been tokenized..
Files.push_back(FileName); Files.push_back(FileName);
// Tokenize the file.. // 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; unsigned int lineno = 1;
char CurrentToken[1000] = {0}; char CurrentToken[1000] = {0};
char *pToken = CurrentToken; 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 // Todo
if ( ch < 0 ) if ( ch < 0 )
@ -352,7 +347,8 @@ void TokenizeCode(std::istream &code, const unsigned int FileIndex)
addtoken("#include", lineno, FileIndex); addtoken("#include", lineno, FileIndex);
addtoken(line.c_str(), 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) else if (strncmp(line.c_str(), "#define", 7) == 0)
@ -422,7 +418,7 @@ void TokenizeCode(std::istream &code, const unsigned int FileIndex)
} }
// Comments.. // Comments..
if (ch == '/' && !code.eof()) if (ch == '/' && code.good())
{ {
bool newstatement = bool( strchr(";{}", CurrentToken[0]) != NULL ); bool newstatement = bool( strchr(";{}", CurrentToken[0]) != NULL );
@ -466,7 +462,7 @@ void TokenizeCode(std::istream &code, const unsigned int FileIndex)
{ {
char chPrev; char chPrev;
ch = chPrev = 'A'; ch = chPrev = 'A';
while (!code.eof() && (chPrev!='*' || ch!='/')) while (code.good() && (chPrev!='*' || ch!='/'))
{ {
chPrev = ch; chPrev = ch;
ch = (char)code.get(); ch = (char)code.get();
@ -528,7 +524,7 @@ void TokenizeCode(std::istream &code, const unsigned int FileIndex)
// Get next character // Get next character
c = (char)code.get(); c = (char)code.get();
} }
while (!code.eof() && (special || c != '\"')); while (code.good() && (special || c != '\"'));
*pToken = '\"'; *pToken = '\"';
addtoken(CurrentToken, lineno, FileIndex); addtoken(CurrentToken, lineno, FileIndex);
memset(CurrentToken, 0, sizeof(CurrentToken)); memset(CurrentToken, 0, sizeof(CurrentToken));

View File

@ -37,7 +37,7 @@ struct TOKEN
extern struct TOKEN *tokens, *tokens_back; 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); void TokenizeCode(std::istream &code, const unsigned int FileIndex=0);