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 "CommonCheck.h"
@ -30,6 +31,8 @@
#include <iostream>
#include <sstream>
#include <cstring>
#include <fstream>
#include <map>
// 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<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++)
{
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<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
@ -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";
}
//---------------------------------------------------------------------------

View File

@ -50,7 +50,7 @@ void preprocess(std::istream &istr, std::map<std::string, std::string> &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<std::string, std::string> &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<std::string, std::string> &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<std::string, std::string> &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<std::string> 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<bool>::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it )
match &= *it;
if ( ! match )
line = "";
if ( line.find("#if") == 0 ||

View File

@ -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<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()
{
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.
//---------------------------------------------------------------------------
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));

View File

@ -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);