preprocessor: Use the new preprocessor in cppcheck
This commit is contained in:
parent
3bf539939f
commit
a3a4d72082
32
main.cpp
32
main.cpp
|
@ -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";
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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"
|
||||
|
|
20
tokenize.cpp
20
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));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue