diff --git a/src/cppcheck.cpp b/src/cppcheck.cpp index 13678fbbe..a88d7ba1e 100644 --- a/src/cppcheck.cpp +++ b/src/cppcheck.cpp @@ -327,7 +327,7 @@ unsigned int CppCheck::check() } 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 (_settings._errorsOnly == false && it != configurations.begin()) diff --git a/src/preprocessor.cpp b/src/preprocessor.cpp index d50d76414..99f1c993c 100644 --- a/src/preprocessor.cpp +++ b/src/preprocessor.cpp @@ -184,13 +184,13 @@ std::string Preprocessor::read(std::istream &istr) return code.str(); } -void Preprocessor::preprocess(std::istream &istr, std::map &result, const std::string &filename, const std::list &includePaths) +void Preprocessor::preprocess(std::istream &istr, std::map &result, const std::string &filename, const std::list &includePaths, ErrorLogger *errorLogger) { std::list configs; std::string data; preprocess(istr, data, configs, filename, includePaths); for (std::list::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) @@ -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; @@ -467,7 +467,7 @@ std::string Preprocessor::getcode(const std::string &filedata, std::string cfg) ret << line << "\n"; } - return expandMacros(ret.str()); + return expandMacros(ret.str(), filename, errorLogger); } 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.. std::string::size_type defpos = 0; @@ -780,9 +780,21 @@ std::string Preprocessor::expandMacros(std::string code) if (!code[pos1]) { - // This should not happen, if it does, there is a bug in cppcheck. - std::cout << "\n\n####### There is a bug in preprocessor.cpp that can cause crash, shutting down.\n\n" << std::endl; - std::exit(0); + // End of file was reached without finding pair + if (errorLogger) + { + std::list 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; diff --git a/src/preprocessor.h b/src/preprocessor.h index 7437eea5c..b684041c5 100644 --- a/src/preprocessor.h +++ b/src/preprocessor.h @@ -26,6 +26,7 @@ #include #include #include +#include "errorlogger.h" class Preprocessor @@ -44,7 +45,7 @@ public: * 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. */ - void preprocess(std::istream &istr, std::map &result, const std::string &filename, const std::list &includePaths = std::list()); + void preprocess(std::istream &istr, std::map &result, const std::string &filename, const std::list &includePaths = std::list(), ErrorLogger *errorLogger = 0); /** * 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 */ - 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: @@ -83,7 +84,7 @@ protected: */ 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: diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index ca8656061..196d27435 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -28,6 +28,8 @@ #include #include +extern std::ostringstream errout; + class TestPreprocessor : public TestFixture { public: @@ -42,9 +44,9 @@ public: 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(pragma); TEST_CASE(endifsemicolon); + TEST_CASE(missing_doublequote); } @@ -816,6 +819,21 @@ private: "\n" "}\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)