Fix ticket #242 (Preprocessor: Bail out on failure instead of terminating the program)

http://apps.sourceforge.net/trac/cppcheck/ticket/242
This commit is contained in:
Reijo Tomperi 2009-04-03 22:09:12 +03:00
parent 3b0643a000
commit 7a11f0e61f
4 changed files with 45 additions and 14 deletions

View File

@ -327,7 +327,7 @@ unsigned int CppCheck::check()
} }
cfg = *it; cfg = *it;
std::string codeWithoutCfg = Preprocessor::getcode(filedata, *it); std::string codeWithoutCfg = Preprocessor::getcode(filedata, *it, fname, _errorLogger);
// If only errors are printed, print filename after the check // If only errors are printed, print filename after the check
if (_settings._errorsOnly == false && it != configurations.begin()) if (_settings._errorsOnly == false && it != configurations.begin())

View File

@ -184,13 +184,13 @@ std::string Preprocessor::read(std::istream &istr)
return code.str(); return code.str();
} }
void Preprocessor::preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string &filename, const std::list<std::string> &includePaths) void Preprocessor::preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string &filename, const std::list<std::string> &includePaths, ErrorLogger *errorLogger)
{ {
std::list<std::string> configs; std::list<std::string> configs;
std::string data; std::string data;
preprocess(istr, data, configs, filename, includePaths); preprocess(istr, data, configs, filename, includePaths);
for (std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it) for (std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it)
result[ *it ] = Preprocessor::getcode(data, *it); result[ *it ] = Preprocessor::getcode(data, *it, filename, errorLogger);
} }
std::string Preprocessor::removeSpaceNearNL(const std::string &str) std::string Preprocessor::removeSpaceNearNL(const std::string &str)
@ -384,7 +384,7 @@ bool Preprocessor::match_cfg_def(std::string cfg, const std::string &def)
} }
std::string Preprocessor::getcode(const std::string &filedata, std::string cfg) std::string Preprocessor::getcode(const std::string &filedata, std::string cfg, const std::string &filename, ErrorLogger *errorLogger)
{ {
std::ostringstream ret; std::ostringstream ret;
@ -467,7 +467,7 @@ std::string Preprocessor::getcode(const std::string &filedata, std::string cfg)
ret << line << "\n"; ret << line << "\n";
} }
return expandMacros(ret.str()); return expandMacros(ret.str(), filename, errorLogger);
} }
std::string Preprocessor::getHeaderFileName(const std::string &str) std::string Preprocessor::getHeaderFileName(const std::string &str)
@ -708,7 +708,7 @@ public:
} }
}; };
std::string Preprocessor::expandMacros(std::string code) std::string Preprocessor::expandMacros(std::string code, const std::string &filename, ErrorLogger *errorLogger)
{ {
// Search for macros and expand them.. // Search for macros and expand them..
std::string::size_type defpos = 0; std::string::size_type defpos = 0;
@ -780,9 +780,21 @@ std::string Preprocessor::expandMacros(std::string code)
if (!code[pos1]) if (!code[pos1])
{ {
// This should not happen, if it does, there is a bug in cppcheck. // End of file was reached without finding pair
std::cout << "\n\n####### There is a bug in preprocessor.cpp that can cause crash, shutting down.\n\n" << std::endl; if (errorLogger)
std::exit(0); {
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
ErrorLogger::ErrorMessage::FileLocation loc;
loc.line = 0;
loc.file = filename;
locationList.push_back(loc);
errorLogger->reportErr(
ErrorLogger::ErrorMessage(locationList,
"error",
std::string("No pair for character (") + ch + "). Can't process file. File is either invalid or unicode, which is currently not supported.",
"noQuoteCharPair"));
}
return "";
} }
} }
continue; continue;

View File

@ -26,6 +26,7 @@
#include <istream> #include <istream>
#include <string> #include <string>
#include <list> #include <list>
#include "errorlogger.h"
class Preprocessor class Preprocessor
@ -44,7 +45,7 @@ public:
* Note that if path from given filename is also extracted and that is used as * Note that if path from given filename is also extracted and that is used as
* a last include path if include file was not found from earlier paths. * a last include path if include file was not found from earlier paths.
*/ */
void preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string &filename, const std::list<std::string> &includePaths = std::list<std::string>()); void preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string &filename, const std::list<std::string> &includePaths = std::list<std::string>(), ErrorLogger *errorLogger = 0);
/** /**
* Extract the code for each configuration. Use this with getcode() to get the * Extract the code for each configuration. Use this with getcode() to get the
@ -71,7 +72,7 @@ public:
/** /**
* Get preprocessed code for a given configuration * Get preprocessed code for a given configuration
*/ */
static std::string getcode(const std::string &filedata, std::string cfg); static std::string getcode(const std::string &filedata, std::string cfg, const std::string &filename, ErrorLogger *errorLogger);
protected: protected:
@ -83,7 +84,7 @@ protected:
*/ */
static std::string replaceIfDefined(const std::string &str); static std::string replaceIfDefined(const std::string &str);
static std::string expandMacros(std::string code); static std::string expandMacros(std::string code, const std::string &filename, ErrorLogger *errorLogger);
private: private:

View File

@ -28,6 +28,8 @@
#include <map> #include <map>
#include <string> #include <string>
extern std::ostringstream errout;
class TestPreprocessor : public TestFixture class TestPreprocessor : public TestFixture
{ {
public: public:
@ -42,9 +44,9 @@ public:
return Preprocessor::replaceIfDefined(str); return Preprocessor::replaceIfDefined(str);
} }
static std::string expandMacros(std::string code) static std::string expandMacros(std::string code, ErrorLogger *errorLogger = 0)
{ {
return Preprocessor::expandMacros(code); return Preprocessor::expandMacros(code, "file.cpp", errorLogger);
} }
}; };
@ -112,6 +114,7 @@ private:
TEST_CASE(ifdefwithfile); TEST_CASE(ifdefwithfile);
TEST_CASE(pragma); TEST_CASE(pragma);
TEST_CASE(endifsemicolon); TEST_CASE(endifsemicolon);
TEST_CASE(missing_doublequote);
} }
@ -816,6 +819,21 @@ private:
"\n" "\n"
"}\n", actual[""]); "}\n", actual[""]);
} }
void missing_doublequote()
{
const char filedata[] = "#define a\n"
"#ifdef 1\n"
"\"\n"
"#endif\n";
// expand macros..
errout.str("");
std::string actual = OurPreprocessor::expandMacros(filedata, this);
ASSERT_EQUALS("", actual);
ASSERT_EQUALS("[file.cpp:0]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported.\n", errout.str());
}
}; };
REGISTER_TEST(TestPreprocessor) REGISTER_TEST(TestPreprocessor)