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 "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";
|
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -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 ||
|
||||||
|
|
|
@ -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"
|
||||||
|
|
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.
|
// 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));
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue