diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 45bfca1a4..55130f806 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -304,6 +304,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string std::set checksums; unsigned int checkCount = 0; bool hasValidConfig = false; + std::list configurationError; for (std::set::const_iterator it = configurations.begin(); it != configurations.end(); ++it) { // bail out if terminated if (_settings.terminated()) @@ -361,9 +362,9 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string const simplecpp::TokenList &tokensP = preprocessor.preprocess(tokens1, cfg, files); _tokenizer.createTokens(&tokensP); timer.Stop(); + hasValidConfig = true; if (tokensP.empty()) continue; - hasValidConfig = true; // skip rest of iteration if just checking configuration if (_settings.checkConfiguration) @@ -418,6 +419,12 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string checkSimplifiedTokens(_tokenizer); } + } catch (const simplecpp::Output &o) { + // #error etc during preprocessing + configurationError.push_back(std::string(o.location.file() + ':' + MathLib::toString(o.location.line) + ": " + o.msg)); + --checkCount; // don't count invalid configurations + continue; + } catch (const InternalError &e) { internalErrorFound=true; std::list locationList; @@ -445,6 +452,12 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string } if (!hasValidConfig && configurations.size() > 1 && _settings.isEnabled(Settings::INFORMATION)) { + std::string msg; + msg = "This file is not analyzed. Every tested configuration results in preprocessor errors. It seems that Cppcheck failed to extract a valid configuration. Use -v for more details."; + msg += "\nThis file is not analyzed. Every tested configuration results in preprocessor errors. It seems that Cppcheck failed to extract a valid configuration. The preprocessor errors:"; + for (const std::string &s : configurationError) + msg += "\n " + s; + std::list locationList; ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile(Path::toNativeSeparators(filename)); @@ -452,7 +465,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string ErrorLogger::ErrorMessage errmsg(locationList, loc.getfile(), Severity::information, - "No tested configuration is valid, this file is not analyzed.", + msg, "noValidConfiguration", false); reportErr(errmsg); diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 49b1ae761..73106618c 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -619,8 +619,21 @@ simplecpp::TokenList Preprocessor::preprocess(const simplecpp::TokenList &tokens const bool showerror = (!_settings.userDefines.empty() && !_settings.force); reportOutput(outputList, showerror); - if (hasErrors(outputList)) - return simplecpp::TokenList(files); + if (hasErrors(outputList)) { + for (const simplecpp::Output &output : outputList) { + switch (output.type) { + case simplecpp::Output::ERROR: + case simplecpp::Output::INCLUDE_NESTED_TOO_DEEPLY: + case simplecpp::Output::SYNTAX_ERROR: + case simplecpp::Output::UNHANDLED_CHAR_ERROR: + throw output; + case simplecpp::Output::WARNING: + case simplecpp::Output::MISSING_HEADER: + case simplecpp::Output::PORTABILITY_BACKSLASH: + break; + }; + } + } tokens2.removeComments(); @@ -675,7 +688,13 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string if (hasErrors(outputList)) return ""; - return getcode(tokens1, cfg, files, filedata.find("#file") != std::string::npos); + std::string ret; + try { + ret = getcode(tokens1, cfg, files, filedata.find("#file") != std::string::npos); + } catch (const simplecpp::Output &o) { + ret.clear(); + } + return ret; } void Preprocessor::reportOutput(const simplecpp::OutputList &outputList, bool showerror) diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index c3020fb05..4abb0f8dc 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -262,6 +262,8 @@ private: try { const std::string &cfgcode = preprocessor0.getcode(tokens, *it, files, std::string(code).find("#file") != std::string::npos); actual[*it] = cfgcode; + } catch (const simplecpp::Output &o) { + actual[*it] = ""; } catch (...) { } }