QErrorPathItem::QErrorPathItem(const ErrorLogger::ErrorMessage::FileLocation &loc) : file(QString::fromStdString(loc.getfile(false))) , line(loc.line) , col(loc.col) , info(QString::fromStdString(loc.getinfo())) { }
void FileLocationSetFile() { ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile("foo.cpp"); ASSERT_EQUALS("foo.cpp", loc.getfile()); ASSERT_EQUALS(0, loc.line); }
void ToVerboseXml() { ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile("foo.cpp"); loc.line = 5; std::list<ErrorLogger::ErrorMessage::FileLocation> locs; locs.push_back(loc); ErrorMessage msg(locs, Severity::error, "Programming error.\nVerbose error", "errorId", false); ASSERT_EQUALS("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<results>", ErrorLogger::ErrorMessage::getXMLHeader(1)); ASSERT_EQUALS("</results>", ErrorLogger::ErrorMessage::getXMLFooter(1)); ASSERT_EQUALS("<error file=\"foo.cpp\" line=\"5\" id=\"errorId\" severity=\"error\" msg=\"Verbose error\"/>", msg.toXML(true,1)); }
void ErrorMessageConstruct() { ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile("foo.cpp"); loc.line = 5; std::list<ErrorLogger::ErrorMessage::FileLocation> locs; locs.push_back(loc); ErrorMessage msg(locs, Severity::error, "Programming error.", "errorId", false); ASSERT_EQUALS(1, (int)msg._callStack.size()); ASSERT_EQUALS("Programming error.", msg.shortMessage()); ASSERT_EQUALS("Programming error.", msg.verboseMessage()); ASSERT_EQUALS("[foo.cpp:5]: (error) Programming error.", msg.toString(false)); ASSERT_EQUALS("[foo.cpp:5]: (error) Programming error.", msg.toString(true)); }
void CustomFormat2() { ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile("foo.cpp"); loc.line = 5; std::list<ErrorLogger::ErrorMessage::FileLocation> locs; locs.push_back(loc); ErrorMessage msg(locs, Severity::error, "Programming error.\nVerbose error", "errorId", false); ASSERT_EQUALS(1, (int)msg._callStack.size()); ASSERT_EQUALS("Programming error.", msg.shortMessage()); ASSERT_EQUALS("Verbose error", msg.verboseMessage()); ASSERT_EQUALS("Programming error. - foo.cpp(5):(error,errorId)", msg.toString(false, "{message} - {file}({line}):({severity},{id})")); ASSERT_EQUALS("Verbose error - foo.cpp(5):(error,errorId)", msg.toString(true, "{message} - {file}({line}):({severity},{id})")); }
void CheckUnusedFunctions::unusedFunctionError(ErrorLogger * const errorLogger, const std::string &filename, const std::string &funcname) { std::list<ErrorLogger::ErrorMessage::FileLocation> locationList; if (!filename.empty()) { ErrorLogger::ErrorMessage::FileLocation fileLoc; fileLoc.setfile(filename); fileLoc.line = 1; locationList.push_back(fileLoc); } const ErrorLogger::ErrorMessage errmsg(locationList, Severity::style, "The function '" + funcname + "' is never used", "unusedFunction", false); if (errorLogger) errorLogger->reportErr(errmsg); else reportError(errmsg); }
Token *Token::linkAt(int index) { Token *tok = this->tokAt(index); if (!tok) { std::list<ErrorLogger::ErrorMessage::FileLocation> locationList; ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile(""); loc.line = this->linenr(); locationList.push_back(loc); const ErrorLogger::ErrorMessage errmsg(locationList, Severity::error, "Internal error. Token::linkAt called with index outside the tokens range.", "cppcheckError", false); Check::reportError(errmsg); } return tok ? tok->link() : 0; }
void InconclusiveXml() { // Location ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile("foo.cpp"); loc.line = 5; std::list<ErrorLogger::ErrorMessage::FileLocation> locs; locs.push_back(loc); // Inconclusive error message ErrorMessage msg(locs, Severity::error, "Programming error", "errorId", true); // Don't save inconclusive messages if the xml version is 1 ASSERT_EQUALS("", msg.toXML(false, 1)); // TODO: how should inconclusive messages be saved when the xml version is 2? ASSERT_EQUALS("", msg.toXML(false, 2)); }
void ToXmlV2() { ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile("foo.cpp"); loc.line = 5; std::list<ErrorLogger::ErrorMessage::FileLocation> locs; locs.push_back(loc); ErrorMessage msg(locs, Severity::error, "Programming error.\nVerbose error", "errorId", false); std::string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<results version=\"2\">\n"); header += " <cppcheck version=\""; header += CppCheck::version(); header += "\"/>\n <errors>"; ASSERT_EQUALS(header, ErrorLogger::ErrorMessage::getXMLHeader(2)); ASSERT_EQUALS(" </errors>\n</results>", ErrorLogger::ErrorMessage::getXMLFooter(2)); std::string message(" <error id=\"errorId\" severity=\"error\""); message += " msg=\"Programming error.\" verbose=\"Verbose error\">\n"; message += " <location file=\"foo.cpp\" line=\"5\"/>\n </error>"; ASSERT_EQUALS(message, msg.toXML(false, 2)); }
void CustomFormatLocations() { // Check that first location from location stack is used in template ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile("foo.cpp"); loc.line = 5; ErrorLogger::ErrorMessage::FileLocation loc2; loc2.setfile("bar.cpp"); loc2.line = 8; std::list<ErrorLogger::ErrorMessage::FileLocation> locs; locs.push_back(loc); locs.push_back(loc2); ErrorMessage msg(locs, Severity::error, "Programming error.\nVerbose error", "errorId", false); ASSERT_EQUALS(2, (int)msg._callStack.size()); ASSERT_EQUALS("Programming error.", msg.shortMessage()); ASSERT_EQUALS("Verbose error", msg.verboseMessage()); ASSERT_EQUALS("Programming error. - bar.cpp(8):(error,errorId)", msg.toString(false, "{message} - {file}({line}):({severity},{id})")); ASSERT_EQUALS("Verbose error - bar.cpp(8):(error,errorId)", msg.toString(true, "{message} - {file}({line}):({severity},{id})")); }
void CppCheck::tooManyConfigsError(const std::string &file, const std::size_t numberOfConfigurations) { if (!_settings.isEnabled(Settings::INFORMATION) && !tooManyConfigs) return; tooManyConfigs = false; if (_settings.isEnabled(Settings::INFORMATION) && file.empty()) return; std::list<ErrorLogger::ErrorMessage::FileLocation> loclist; if (!file.empty()) { ErrorLogger::ErrorMessage::FileLocation location; location.setfile(file); loclist.push_back(location); } std::ostringstream msg; msg << "Too many #ifdef configurations - cppcheck only checks " << _settings.maxConfigs; if (numberOfConfigurations > _settings.maxConfigs) msg << " of " << numberOfConfigurations << " configurations. Use --force to check all configurations.\n"; if (file.empty()) msg << " configurations. Use --force to check all configurations. For more details, use --enable=information.\n"; msg << "The checking of the file will be interrupted because there are too many " "#ifdef configurations. Checking of all #ifdef configurations can be forced " "by --force command line option or from GUI preferences. However that may " "increase the checking time."; if (file.empty()) msg << " For more details, use --enable=information."; ErrorLogger::ErrorMessage errmsg(loclist, emptyString, Severity::information, msg.str(), "toomanyconfigs", CWE398, false); reportErr(errmsg); }
void CppCheck::purgedConfigurationMessage(const std::string &file, const std::string& configuration) { tooManyConfigs = false; if (_settings.isEnabled("information") && file.empty()) return; std::list<ErrorLogger::ErrorMessage::FileLocation> loclist; if (!file.empty()) { ErrorLogger::ErrorMessage::FileLocation location; location.setfile(file); loclist.push_back(location); } ErrorLogger::ErrorMessage errmsg(loclist, Severity::information, "The configuration '" + configuration + "' was not checked because its code equals another one.", "purgedConfiguration", false); reportErr(errmsg); }
void CppCheck::executeRules(const std::string &tokenlist, const Tokenizer &tokenizer) { (void)tokenlist; (void)tokenizer; #ifdef HAVE_RULES // Are there rules to execute? bool isrule = false; for (std::list<Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) { if (it->tokenlist == tokenlist) isrule = true; } // There is no rule to execute if (isrule == false) return; // Write all tokens in a string that can be parsed by pcre std::ostringstream ostr; for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) ostr << " " << tok->str(); const std::string str(ostr.str()); for (std::list<Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) { const Settings::Rule &rule = *it; if (rule.pattern.empty() || rule.id.empty() || rule.severity == Severity::none || rule.tokenlist != tokenlist) continue; const char *error = nullptr; int erroffset = 0; pcre *re = pcre_compile(rule.pattern.c_str(),0,&error,&erroffset,nullptr); if (!re) { if (error) { ErrorLogger::ErrorMessage errmsg(std::list<ErrorLogger::ErrorMessage::FileLocation>(), Severity::error, error, "pcre_compile", false); reportErr(errmsg); } continue; } int pos = 0; int ovector[30]= {0}; while (pos < (int)str.size() && 0 <= pcre_exec(re, nullptr, str.c_str(), (int)str.size(), pos, 0, ovector, 30)) { const unsigned int pos1 = (unsigned int)ovector[0]; const unsigned int pos2 = (unsigned int)ovector[1]; // jump to the end of the match for the next pcre_exec pos = (int)pos2; // determine location.. ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile(tokenizer.list.getSourceFilePath()); loc.line = 0; std::size_t len = 0; for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) { len = len + 1U + tok->str().size(); if (len > pos1) { loc.setfile(tokenizer.list.getFiles().at(tok->fileIndex())); loc.line = tok->linenr(); break; } } const std::list<ErrorLogger::ErrorMessage::FileLocation> callStack(1, loc); // Create error message std::string summary; if (rule.summary.empty()) summary = "found '" + str.substr(pos1, pos2 - pos1) + "'"; else summary = rule.summary; const ErrorLogger::ErrorMessage errmsg(callStack, rule.severity, summary, rule.id, false); // Report error reportErr(errmsg); } pcre_free(re); } #endif }
unsigned int CppCheck::processFile(const std::string& filename) { exitcode = 0; // only show debug warnings for accepted C/C++ source files if (!Path::acceptFile(filename)) _settings.debugwarnings = false; if (_settings.terminated()) return exitcode; if (_settings._errorsOnly == false) { std::string fixedpath = Path::simplifyPath(filename.c_str()); fixedpath = Path::toNativeSeparators(fixedpath); _errorLogger.reportOut(std::string("Checking ") + fixedpath + std::string("...")); } try { Preprocessor preprocessor(&_settings, this); std::list<std::string> configurations; std::string filedata = ""; if (!_fileContent.empty()) { // File content was given as a string std::istringstream iss(_fileContent); preprocessor.preprocess(iss, filedata, configurations, filename, _settings._includePaths); } else { // Only file name was given, read the content from file std::ifstream fin(filename.c_str()); Timer t("Preprocessor::preprocess", _settings._showtime, &S_timerResults); preprocessor.preprocess(fin, filedata, configurations, filename, _settings._includePaths); } if (_settings.checkConfiguration) { return 0; } if (!_settings.userDefines.empty()) { configurations.clear(); configurations.push_back(_settings.userDefines); } if (!_settings._force && configurations.size() > _settings._maxConfigs) { const std::string fixedpath = Path::toNativeSeparators(filename); ErrorLogger::ErrorMessage::FileLocation location; location.setfile(fixedpath); const std::list<ErrorLogger::ErrorMessage::FileLocation> loclist(1, location); std::ostringstream msg; msg << "Too many #ifdef configurations - cppcheck will only check " << _settings._maxConfigs << " of " << configurations.size() << ".\n" "The checking of the file will be interrupted because there are too many " "#ifdef configurations. Checking of all #ifdef configurations can be forced " "by --force command line option or from GUI preferences. However that may " "increase the checking time."; ErrorLogger::ErrorMessage errmsg(loclist, Severity::information, msg.str(), "toomanyconfigs", false); reportErr(errmsg); } unsigned int checkCount = 0; for (std::list<std::string>::const_iterator it = configurations.begin(); it != configurations.end(); ++it) { // Check only a few configurations (default 12), after that bail out, unless --force // was used. if (!_settings._force && checkCount >= _settings._maxConfigs) { const std::string fixedpath = Path::toNativeSeparators(filename); ErrorLogger::ErrorMessage::FileLocation location; location.setfile(fixedpath); std::list<ErrorLogger::ErrorMessage::FileLocation> loclist; loclist.push_back(location); ErrorLogger::ErrorMessage errmsg(loclist, Severity::information, "Interrupted checking because of too many #ifdef configurations.", "toomanyconfigs", false); reportInfo(errmsg); break; } cfg = *it; // If only errors are printed, print filename after the check if (_settings._errorsOnly == false && it != configurations.begin()) { std::string fixedpath = Path::simplifyPath(filename.c_str()); fixedpath = Path::toNativeSeparators(fixedpath); _errorLogger.reportOut(std::string("Checking ") + fixedpath + ": " + cfg + std::string("...")); } Timer t("Preprocessor::getcode", _settings._showtime, &S_timerResults); const std::string codeWithoutCfg = preprocessor.getcode(filedata, *it, filename, _settings.userDefines.empty()); t.Stop(); const std::string &appendCode = _settings.append(); if (_settings.debugFalsePositive) { if (findError(codeWithoutCfg + appendCode, filename.c_str())) { return exitcode; } } else { checkFile(codeWithoutCfg + appendCode, filename.c_str()); } ++checkCount; } } catch (const std::runtime_error &e) { // Exception was thrown when checking this file.. const std::string fixedpath = Path::toNativeSeparators(filename); _errorLogger.reportOut("Bailing out from checking " + fixedpath + ": " + e.what()); } if (!_settings._errorsOnly) reportUnmatchedSuppressions(_settings.nomsg.getUnmatchedLocalSuppressions(filename)); _errorList.clear(); return exitcode; }
void CppCheck::checkFile(const std::string &code, const char FileName[]) { if (_settings.terminated() || _settings.checkConfiguration) return; Tokenizer _tokenizer(&_settings, this); bool result; // Tokenize the file std::istringstream istr(code); Timer timer("Tokenizer::tokenize", _settings._showtime, &S_timerResults); result = _tokenizer.tokenize(istr, FileName, cfg); timer.Stop(); if (!result) { // File had syntax errors, abort return; } Timer timer2("Tokenizer::fillFunctionList", _settings._showtime, &S_timerResults); _tokenizer.fillFunctionList(); timer2.Stop(); // call all "runChecks" in all registered Check classes for (std::list<Check *>::iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) { if (_settings.terminated()) return; Timer timerRunChecks((*it)->name() + "::runChecks", _settings._showtime, &S_timerResults); (*it)->runChecks(&_tokenizer, &_settings, this); } Timer timer3("Tokenizer::simplifyTokenList", _settings._showtime, &S_timerResults); result = _tokenizer.simplifyTokenList(); timer3.Stop(); if (!result) return; Timer timer4("Tokenizer::fillFunctionList", _settings._showtime, &S_timerResults); _tokenizer.fillFunctionList(); timer4.Stop(); if (_settings.isEnabled("unusedFunction") && _settings._jobs == 1) _checkUnusedFunctions.parseTokens(_tokenizer); // call all "runSimplifiedChecks" in all registered Check classes for (std::list<Check *>::iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) { if (_settings.terminated()) return; Timer timerSimpleChecks((*it)->name() + "::runSimplifiedChecks", _settings._showtime, &S_timerResults); (*it)->runSimplifiedChecks(&_tokenizer, &_settings, this); } #ifdef HAVE_RULES // Are there extra rules? if (!_settings.rules.empty()) { std::ostringstream ostr; for (const Token *tok = _tokenizer.tokens(); tok; tok = tok->next()) ostr << " " << tok->str(); const std::string str(ostr.str()); for (std::list<Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) { const Settings::Rule &rule = *it; if (rule.pattern.empty() || rule.id.empty() || rule.severity.empty()) continue; const char *error = 0; int erroffset = 0; pcre *re = pcre_compile(rule.pattern.c_str(),0,&error,&erroffset,NULL); if (!re && error) { ErrorLogger::ErrorMessage errmsg(std::list<ErrorLogger::ErrorMessage::FileLocation>(), Severity::error, error, "pcre_compile", false); reportErr(errmsg); } if (!re) continue; int pos = 0; int ovector[30]; while (0 <= pcre_exec(re, NULL, str.c_str(), (int)str.size(), pos, 0, ovector, 30)) { unsigned int pos1 = (unsigned int)ovector[0]; unsigned int pos2 = (unsigned int)ovector[1]; // jump to the end of the match for the next pcre_exec pos = (int)pos2; // determine location.. ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile(_tokenizer.getFiles()->front()); loc.line = 0; unsigned int len = 0; for (const Token *tok = _tokenizer.tokens(); tok; tok = tok->next()) { len = len + 1 + tok->str().size(); if (len > pos1) { loc.setfile(_tokenizer.getFiles()->at(tok->fileIndex())); loc.line = tok->linenr(); break; } } const std::list<ErrorLogger::ErrorMessage::FileLocation> callStack(1, loc); // Create error message std::string summary; if (rule.summary.empty()) summary = "found '" + str.substr(pos1, pos2 - pos1) + "'"; else summary = rule.summary; const ErrorLogger::ErrorMessage errmsg(callStack, Severity::fromString(rule.severity), summary, rule.id, false); // Report error reportErr(errmsg); } pcre_free(re); } } #endif }
unsigned int CppCheck::processFile() { exitcode = 0; // TODO: Should this be moved out to its own function so all the files can be // analysed before any files are checked? if (_settings.test_2_pass && _settings._jobs == 1) { const std::string printname = Path::toNativeSeparators(_filename); reportOut("Analysing " + printname + "..."); std::ifstream f(_filename.c_str()); analyseFile(f, _filename); } _errout.str(""); if (_settings.terminated()) return exitcode; if (_settings._errorsOnly == false) { std::string fixedpath(_filename); fixedpath = Path::simplifyPath(fixedpath.c_str()); fixedpath = Path::toNativeSeparators(fixedpath); _errorLogger.reportOut(std::string("Checking ") + fixedpath + std::string("...")); } try { Preprocessor preprocessor(&_settings, this); std::list<std::string> configurations; std::string filedata = ""; if (!_fileContent.empty()) { // File content was given as a string std::istringstream iss(_fileContent); preprocessor.preprocess(iss, filedata, configurations, _filename, _settings._includePaths); } else { // Only file name was given, read the content from file std::ifstream fin(_filename.c_str()); Timer t("Preprocessor::preprocess", _settings._showtime, &S_timerResults); preprocessor.preprocess(fin, filedata, configurations, _filename, _settings._includePaths); } if (_settings.checkConfiguration) { return 0; } _settings.ifcfg = bool(configurations.size() > 1); if (!_settings.userDefines.empty()) { configurations.clear(); configurations.push_back(_settings.userDefines); } int checkCount = 0; for (std::list<std::string>::const_iterator it = configurations.begin(); it != configurations.end(); ++it) { // Check only 12 first configurations, after that bail out, unless --force // was used. if (!_settings._force && checkCount > 11) { const std::string fixedpath = Path::toNativeSeparators(_filename); ErrorLogger::ErrorMessage::FileLocation location; location.setfile(fixedpath); std::list<ErrorLogger::ErrorMessage::FileLocation> loclist; loclist.push_back(location); const std::string msg("Interrupted checking because of too many #ifdef configurations.\n" "The checking of the file was interrupted because there were too many " "#ifdef configurations. Checking of all #ifdef configurations can be forced " "by --force command line option or from GUI preferences. However that may " "increase the checking time."); ErrorLogger::ErrorMessage errmsg(loclist, Severity::information, msg, "toomanyconfigs", false); _errorLogger.reportErr(errmsg); break; } cfg = *it; Timer t("Preprocessor::getcode", _settings._showtime, &S_timerResults); const std::string codeWithoutCfg = Preprocessor::getcode(filedata, *it, _filename, &_settings, &_errorLogger); t.Stop(); // If only errors are printed, print filename after the check if (_settings._errorsOnly == false && it != configurations.begin()) { std::string fixedpath = Path::simplifyPath(_filename.c_str()); fixedpath = Path::toNativeSeparators(fixedpath); _errorLogger.reportOut(std::string("Checking ") + fixedpath + ": " + cfg + std::string("...")); } std::string appendCode = _settings.append(); if (!appendCode.empty()) Preprocessor::preprocessWhitespaces(appendCode); checkFile(codeWithoutCfg + appendCode, _filename.c_str()); ++checkCount; } } catch (std::runtime_error &e) { // Exception was thrown when checking this file.. const std::string fixedpath = Path::toNativeSeparators(_filename); _errorLogger.reportOut("Bailing out from checking " + fixedpath + ": " + e.what()); } reportUnmatchedSuppressions(_settings.nomsg.getUnmatchedLocalSuppressions(_filename)); // This generates false positives - especially for libraries const bool verbose_orig = _settings._verbose; _settings._verbose = false; if (_settings.isEnabled("unusedFunction") && _settings._jobs == 1) { _errout.str(""); if (_settings._errorsOnly == false) _errorLogger.reportOut("Checking usage of global functions.."); _checkUnusedFunctions.check(this); } _settings._verbose = verbose_orig; _errorList.clear(); return exitcode; }
unsigned int CppCheck::processFile() { exitcode = 0; // only show debug warnings for C/C++ source files (don't fix // debug warnings for java/c#/etc files) if (!Path::acceptFile(_filename)) _settings.debugwarnings = false; // TODO: Should this be moved out to its own function so all the files can be // analysed before any files are checked? if (_settings.test_2_pass && _settings._jobs == 1) { const std::string printname = Path::toNativeSeparators(_filename); reportOut("Analysing " + printname + "..."); std::ifstream f(_filename.c_str()); analyseFile(f, _filename); } _errout.str(""); if (_settings.terminated()) return exitcode; if (_settings._errorsOnly == false) { std::string fixedpath(_filename); fixedpath = Path::simplifyPath(fixedpath.c_str()); fixedpath = Path::toNativeSeparators(fixedpath); _errorLogger.reportOut(std::string("Checking ") + fixedpath + std::string("...")); } try { Preprocessor preprocessor(&_settings, this); std::list<std::string> configurations; std::string filedata = ""; if (!_fileContent.empty()) { // File content was given as a string std::istringstream iss(_fileContent); preprocessor.preprocess(iss, filedata, configurations, _filename, _settings._includePaths); } else { // Only file name was given, read the content from file std::ifstream fin(_filename.c_str()); Timer t("Preprocessor::preprocess", _settings._showtime, &S_timerResults); preprocessor.preprocess(fin, filedata, configurations, _filename, _settings._includePaths); } if (_settings.checkConfiguration) { return 0; } _settings.ifcfg = bool(configurations.size() > 1); if (!_settings.userDefines.empty()) { configurations.clear(); configurations.push_back(_settings.userDefines); } int checkCount = 0; for (std::list<std::string>::const_iterator it = configurations.begin(); it != configurations.end(); ++it) { // Check only a few configurations (default 12), after that bail out, unless --force // was used. if (!_settings._force && checkCount >= _settings._maxConfigs) { const std::string fixedpath = Path::toNativeSeparators(_filename); ErrorLogger::ErrorMessage::FileLocation location; location.setfile(fixedpath); std::list<ErrorLogger::ErrorMessage::FileLocation> loclist; loclist.push_back(location); const std::string msg("Interrupted checking because of too many #ifdef configurations.\n" "The checking of the file was interrupted because there were too many " "#ifdef configurations. Checking of all #ifdef configurations can be forced " "by --force command line option or from GUI preferences. However that may " "increase the checking time."); ErrorLogger::ErrorMessage errmsg(loclist, Severity::information, msg, "toomanyconfigs", false); if (!_settings.nomsg.isSuppressedLocal(errmsg._id, fixedpath, location.line)) { reportErr(errmsg); } break; } cfg = *it; Timer t("Preprocessor::getcode", _settings._showtime, &S_timerResults); const std::string codeWithoutCfg = preprocessor.getcode(filedata, *it, _filename); t.Stop(); // If only errors are printed, print filename after the check if (_settings._errorsOnly == false && it != configurations.begin()) { std::string fixedpath = Path::simplifyPath(_filename.c_str()); fixedpath = Path::toNativeSeparators(fixedpath); _errorLogger.reportOut(std::string("Checking ") + fixedpath + ": " + cfg + std::string("...")); } const std::string &appendCode = _settings.append(); if (_settings.debugFalsePositive) { if (findError(codeWithoutCfg + appendCode, _filename.c_str())) { return exitcode; } } else { checkFile(codeWithoutCfg + appendCode, _filename.c_str()); } ++checkCount; } } catch (std::runtime_error &e) { // Exception was thrown when checking this file.. const std::string fixedpath = Path::toNativeSeparators(_filename); _errorLogger.reportOut("Bailing out from checking " + fixedpath + ": " + e.what()); } if (!_settings._errorsOnly) reportUnmatchedSuppressions(_settings.nomsg.getUnmatchedLocalSuppressions(_filename)); _errorList.clear(); return exitcode; }
void CppCheck::checkFile(const std::string &code, const char FileName[]) { if (_settings.terminated() || _settings.checkConfiguration) return; Tokenizer _tokenizer(&_settings, this); if (_settings._showtime != SHOWTIME_NONE) _tokenizer.setTimerResults(&S_timerResults); try { bool result; // Execute rules for "raw" code for (std::list<Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) { if (it->tokenlist == "raw") { Tokenizer tokenizer2(&_settings, this); std::istringstream istr(code); tokenizer2.list.createTokens(istr, FileName); executeRules("raw", tokenizer2); break; } } // Tokenize the file std::istringstream istr(code); Timer timer("Tokenizer::tokenize", _settings._showtime, &S_timerResults); result = _tokenizer.tokenize(istr, FileName, cfg); timer.Stop(); if (!result) { // File had syntax errors, abort return; } // dump if (_settings.dump) { std::string dumpfile = std::string(FileName) + ".dump"; std::ofstream fdump(dumpfile.c_str()); if (fdump.is_open()) { fdump << "<?xml version=\"1.0\"?>" << std::endl; fdump << "<dump cfg=\"" << cfg << "\">" << std::endl; _tokenizer.dump(fdump); fdump << "</dump>" << std::endl; } return; } // call all "runChecks" in all registered Check classes for (std::list<Check *>::const_iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) { if (_settings.terminated()) return; Timer timerRunChecks((*it)->name() + "::runChecks", _settings._showtime, &S_timerResults); (*it)->runChecks(&_tokenizer, &_settings, this); } if (_settings.isEnabled("unusedFunction") && _settings._jobs == 1) CheckUnusedFunctions::instance.parseTokens(_tokenizer, FileName, &_settings); executeRules("normal", _tokenizer); if (!_simplify) return; Timer timer3("Tokenizer::simplifyTokenList2", _settings._showtime, &S_timerResults); result = _tokenizer.simplifyTokenList2(); timer3.Stop(); if (!result) return; // call all "runSimplifiedChecks" in all registered Check classes for (std::list<Check *>::const_iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) { if (_settings.terminated()) return; Timer timerSimpleChecks((*it)->name() + "::runSimplifiedChecks", _settings._showtime, &S_timerResults); (*it)->runSimplifiedChecks(&_tokenizer, &_settings, this); } if (_settings.terminated()) return; executeRules("simple", _tokenizer); if (_settings.terminated()) return; } catch (const InternalError &e) { std::list<ErrorLogger::ErrorMessage::FileLocation> locationList; ErrorLogger::ErrorMessage::FileLocation loc; if (e.token) { loc.line = e.token->linenr(); const std::string fixedpath = Path::toNativeSeparators(_tokenizer.list.file(e.token)); loc.setfile(fixedpath); } else { ErrorLogger::ErrorMessage::FileLocation loc2; loc2.setfile(Path::toNativeSeparators(FileName)); locationList.push_back(loc2); loc.setfile(_tokenizer.list.getSourceFilePath()); } locationList.push_back(loc); const ErrorLogger::ErrorMessage errmsg(locationList, Severity::error, e.errorMessage, e.id, false); _errorLogger.reportErr(errmsg); } }
void FileLocationDefaults() const { ErrorLogger::ErrorMessage::FileLocation loc; ASSERT_EQUALS("", loc.getfile()); ASSERT_EQUALS(0, loc.line); }
void CppCheck::executeRules(const std::string &tokenlist, const Tokenizer &tokenizer) { (void)tokenlist; (void)tokenizer; #ifdef HAVE_RULES // Are there rules to execute? bool isrule = false; for (std::list<Settings::Rule>::const_iterator it = mSettings.rules.begin(); it != mSettings.rules.end(); ++it) { if (it->tokenlist == tokenlist) isrule = true; } // There is no rule to execute if (isrule == false) return; // Write all tokens in a string that can be parsed by pcre std::ostringstream ostr; for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) ostr << " " << tok->str(); const std::string str(ostr.str()); for (std::list<Settings::Rule>::const_iterator it = mSettings.rules.begin(); it != mSettings.rules.end(); ++it) { const Settings::Rule &rule = *it; if (rule.pattern.empty() || rule.id.empty() || rule.severity == Severity::none || rule.tokenlist != tokenlist) continue; const char *pcreCompileErrorStr = nullptr; int erroffset = 0; pcre * const re = pcre_compile(rule.pattern.c_str(),0,&pcreCompileErrorStr,&erroffset,nullptr); if (!re) { if (pcreCompileErrorStr) { const std::string msg = "pcre_compile failed: " + std::string(pcreCompileErrorStr); const ErrorLogger::ErrorMessage errmsg(std::list<ErrorLogger::ErrorMessage::FileLocation>(), emptyString, Severity::error, msg, "pcre_compile", false); reportErr(errmsg); } continue; } // Optimize the regex, but only if PCRE_CONFIG_JIT is available #ifdef PCRE_CONFIG_JIT const char *pcreStudyErrorStr = nullptr; pcre_extra * const pcreExtra = pcre_study(re, PCRE_STUDY_JIT_COMPILE, &pcreStudyErrorStr); // pcre_study() returns NULL for both errors and when it can not optimize the regex. // The last argument is how one checks for errors. // It is NULL if everything works, and points to an error string otherwise. if (pcreStudyErrorStr) { const std::string msg = "pcre_study failed: " + std::string(pcreStudyErrorStr); const ErrorLogger::ErrorMessage errmsg(std::list<ErrorLogger::ErrorMessage::FileLocation>(), emptyString, Severity::error, msg, "pcre_study", false); reportErr(errmsg); // pcre_compile() worked, but pcre_study() returned an error. Free the resources allocated by pcre_compile(). pcre_free(re); continue; } #else const pcre_extra * const pcreExtra = nullptr; #endif int pos = 0; int ovector[30]= {0}; while (pos < (int)str.size()) { const int pcreExecRet = pcre_exec(re, pcreExtra, str.c_str(), (int)str.size(), pos, 0, ovector, 30); if (pcreExecRet < 0) { const std::string errorMessage = pcreErrorCodeToString(pcreExecRet); if (!errorMessage.empty()) { const ErrorLogger::ErrorMessage errmsg(std::list<ErrorLogger::ErrorMessage::FileLocation>(), emptyString, Severity::error, std::string("pcre_exec failed: ") + errorMessage, "pcre_exec", false); reportErr(errmsg); } break; } const unsigned int pos1 = (unsigned int)ovector[0]; const unsigned int pos2 = (unsigned int)ovector[1]; // jump to the end of the match for the next pcre_exec pos = (int)pos2; // determine location.. ErrorLogger::ErrorMessage::FileLocation loc; loc.setfile(tokenizer.list.getSourceFilePath()); loc.line = 0; std::size_t len = 0; for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) { len = len + 1U + tok->str().size(); if (len > pos1) { loc.setfile(tokenizer.list.getFiles().at(tok->fileIndex())); loc.line = tok->linenr(); break; } } const std::list<ErrorLogger::ErrorMessage::FileLocation> callStack(1, loc); // Create error message std::string summary; if (rule.summary.empty()) summary = "found '" + str.substr(pos1, pos2 - pos1) + "'"; else summary = rule.summary; const ErrorLogger::ErrorMessage errmsg(callStack, tokenizer.list.getSourceFilePath(), rule.severity, summary, rule.id, false); // Report error reportErr(errmsg); } pcre_free(re); #ifdef PCRE_CONFIG_JIT // Free up the EXTRA PCRE value (may be NULL at this point) if (pcreExtra) { pcre_free_study(pcreExtra); } #endif } #endif }
unsigned int CppCheck::processFile(const std::string& filename, std::istream& fileStream) { exitcode = 0; // only show debug warnings for accepted C/C++ source files if (!Path::acceptFile(filename)) _settings.debugwarnings = false; if (_settings.terminated()) return exitcode; if (_settings.quiet == false) { std::string fixedpath = Path::simplifyPath(filename); fixedpath = Path::toNativeSeparators(fixedpath); _errorLogger.reportOut(std::string("Checking ") + fixedpath + std::string("...")); } bool internalErrorFound(false); try { Preprocessor preprocessor(_settings, this); std::list<std::string> configurations; std::string filedata; { Timer t("Preprocessor::preprocess", _settings.showtime, &S_timerResults); preprocessor.preprocess(fileStream, filedata, configurations, filename, _settings.includePaths); } if (_settings.checkConfiguration) { return 0; } // Run define rules on raw code for (std::list<Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) { if (it->tokenlist == "define") { Tokenizer tokenizer2(&_settings, this); std::istringstream istr2(filedata); tokenizer2.list.createTokens(istr2, filename); for (const Token *tok = tokenizer2.list.front(); tok; tok = tok->next()) { if (tok->str() == "#define") { std::string code = std::string(tok->linenr()-1U, '\n'); for (const Token *tok2 = tok; tok2 && tok2->linenr() == tok->linenr(); tok2 = tok2->next()) code += " " + tok2->str(); Tokenizer tokenizer3(&_settings, this); std::istringstream istr3(code); tokenizer3.list.createTokens(istr3, tokenizer2.list.file(tok)); executeRules("define", tokenizer3); } } break; } } if (!_settings.userDefines.empty() && _settings.maxConfigs==1U) { configurations.clear(); configurations.push_back(_settings.userDefines); } if (!_settings.force && configurations.size() > _settings.maxConfigs) { if (_settings.isEnabled("information")) { tooManyConfigsError(Path::toNativeSeparators(filename),configurations.size()); } else { tooManyConfigs = true; } } // write dump file xml prolog std::ofstream fdump; if (_settings.dump) { const std::string dumpfile(filename + ".dump"); fdump.open(dumpfile.c_str()); if (fdump.is_open()) { fdump << "<?xml version=\"1.0\"?>" << std::endl; fdump << "<dumps>" << std::endl; } } std::set<unsigned long long> checksums; unsigned int checkCount = 0; for (std::list<std::string>::const_iterator it = configurations.begin(); it != configurations.end(); ++it) { // bail out if terminated if (_settings.terminated()) break; // Check only a few configurations (default 12), after that bail out, unless --force // was used. if (!_settings.force && ++checkCount > _settings.maxConfigs) break; cfg = *it; // If only errors are printed, print filename after the check if (_settings.quiet == false && it != configurations.begin()) { std::string fixedpath = Path::simplifyPath(filename); fixedpath = Path::toNativeSeparators(fixedpath); _errorLogger.reportOut("Checking " + fixedpath + ": " + cfg + "..."); } if (!_settings.userDefines.empty()) { if (!cfg.empty()) cfg = ";" + cfg; cfg = _settings.userDefines + cfg; } Timer t("Preprocessor::getcode", _settings.showtime, &S_timerResults); std::string codeWithoutCfg = preprocessor.getcode(filedata, cfg, filename); t.Stop(); codeWithoutCfg += _settings.append(); if (_settings.preprocessOnly) { if (codeWithoutCfg.compare(0,5,"#file") == 0) codeWithoutCfg.insert(0U, "//"); std::string::size_type pos = 0; while ((pos = codeWithoutCfg.find("\n#file",pos)) != std::string::npos) codeWithoutCfg.insert(pos+1U, "//"); pos = 0; while ((pos = codeWithoutCfg.find("\n#endfile",pos)) != std::string::npos) codeWithoutCfg.insert(pos+1U, "//"); pos = 0; while ((pos = codeWithoutCfg.find(Preprocessor::macroChar,pos)) != std::string::npos) codeWithoutCfg[pos] = ' '; reportOut(codeWithoutCfg); continue; } Tokenizer _tokenizer(&_settings, this); if (_settings.showtime != SHOWTIME_NONE) _tokenizer.setTimerResults(&S_timerResults); try { // Create tokens, skip rest of iteration if failed std::istringstream istr(codeWithoutCfg); Timer timer("Tokenizer::createTokens", _settings.showtime, &S_timerResults); bool result = _tokenizer.createTokens(istr, filename.c_str()); timer.Stop(); if (!result) continue; // skip rest of iteration if just checking configuration if (_settings.checkConfiguration) continue; // Check raw tokens checkRawTokens(_tokenizer); // Simplify tokens into normal form, skip rest of iteration if failed Timer timer2("Tokenizer::simplifyTokens1", _settings.showtime, &S_timerResults); result = _tokenizer.simplifyTokens1(cfg); timer2.Stop(); if (!result) continue; // dump xml if --dump if (_settings.dump && fdump.is_open()) { fdump << "<dump cfg=\"" << cfg << "\">" << std::endl; preprocessor.dump(fdump); _tokenizer.dump(fdump); fdump << "</dump>" << std::endl; } // Skip if we already met the same simplified token list if (_settings.force || _settings.maxConfigs > 1) { const unsigned long long checksum = _tokenizer.list.calculateChecksum(); if (checksums.find(checksum) != checksums.end()) continue; checksums.insert(checksum); } // Check normal tokens checkNormalTokens(_tokenizer); // simplify more if required, skip rest of iteration if failed if (_simplify) { // if further simplification fails then skip rest of iteration Timer timer3("Tokenizer::simplifyTokenList2", _settings.showtime, &S_timerResults); result = _tokenizer.simplifyTokenList2(); timer3.Stop(); if (!result) continue; // Check simplified tokens checkSimplifiedTokens(_tokenizer); } } catch (const InternalError &e) { if (_settings.isEnabled("information") && (_settings.debug || _settings.verbose)) purgedConfigurationMessage(filename, cfg); internalErrorFound=true; std::list<ErrorLogger::ErrorMessage::FileLocation> locationList; ErrorLogger::ErrorMessage::FileLocation loc; if (e.token) { loc.line = e.token->linenr(); const std::string fixedpath = Path::toNativeSeparators(_tokenizer.list.file(e.token)); loc.setfile(fixedpath); } else { ErrorLogger::ErrorMessage::FileLocation loc2; loc2.setfile(Path::toNativeSeparators(filename.c_str())); locationList.push_back(loc2); loc.setfile(_tokenizer.list.getSourceFilePath()); } locationList.push_back(loc); const ErrorLogger::ErrorMessage errmsg(locationList, Severity::error, e.errorMessage, e.id, false); reportErr(errmsg); } } // dumped all configs, close root </dumps> element now if (_settings.dump && fdump.is_open()) fdump << "</dumps>" << std::endl; } catch (const std::runtime_error &e) { internalError(filename, e.what()); } catch (const InternalError &e) { internalError(filename, e.errorMessage); exitcode=1; // e.g. reflect a syntax error } // In jointSuppressionReport mode, unmatched suppressions are // collected after all files are processed if (!_settings.jointSuppressionReport && (_settings.isEnabled("information") || _settings.checkConfiguration)) { reportUnmatchedSuppressions(_settings.nomsg.getUnmatchedLocalSuppressions(filename, unusedFunctionCheckIsEnabled())); } _errorList.clear(); if (internalErrorFound && (exitcode==0)) { exitcode=1; } return exitcode; }
unsigned int CppCheck::processFile(const std::string& filename,bool flag) // TSC from 20140117 { time_t ts,te; exitcode = 0; // only show debug warnings for accepted C/C++ source files if (!Path::acceptFile(filename)) _settings.debugwarnings = false; if (_settings.terminated()) return exitcode; if (_settings._errorsOnly == false) { std::string fixedpath = Path::simplifyPath(filename.c_str()); fixedpath = Path::toNativeSeparators(fixedpath); _errorLogger.reportOut(std::string("Checking ") + fixedpath + std::string("...")); } try { Preprocessor preprocessor(&_settings, this); std::list<std::string> configurations; std::string filedata = ""; TIMELOG( if (!_fileContent.empty()) { // File content was given as a string std::istringstream iss(_fileContent); preprocessor.preprocess(flag,iss, filedata, configurations, filename, _settings._includePaths); // TSC:from 20140117 } else { // Only file name was given, read the content from file std::ifstream fin(filename.c_str()); Timer t("Preprocessor::preprocess", _settings._showtime, &S_timerResults); preprocessor.preprocess(flag,fin, filedata, configurations, filename, _settings._includePaths); // TSC:from 20140117 } std::stringstream ss; ss << filedata.size(); std::string filesize = ss.str(); ,filename+" "+filesize+" preprocess ",logfile) if (_settings.checkConfiguration) { return 0; } if (!_settings.userDefines.empty()) { configurations.clear(); configurations.push_back(_settings.userDefines); } if (!_settings._force && configurations.size() > _settings._maxConfigs) { const std::string fixedpath = Path::toNativeSeparators(filename); ErrorLogger::ErrorMessage::FileLocation location; location.setfile(fixedpath); const std::list<ErrorLogger::ErrorMessage::FileLocation> loclist(1, location); std::ostringstream msg; msg << "Too many #ifdef configurations - cppcheck will only check " << _settings._maxConfigs << " of " << configurations.size() << ".\n" "The checking of the file will be interrupted because there are too many " "#ifdef configurations. Checking of all #ifdef configurations can be forced " "by --force command line option or from GUI preferences. However that may " "increase the checking time."; } TIMELOG( Timer t("Preprocessor::getcode", _settings._showtime, &S_timerResults); const std::string codeWithoutCfg = preprocessor.getcode(filedata, "", filename, _settings.userDefines.empty()); t.Stop(); ," getcode ",logfile)
unsigned int CppCheck::processFile(const std::string& filename, const std::string &cfgname, std::istream& fileStream) { exitcode = 0; // only show debug warnings for accepted C/C++ source files if (!Path::acceptFile(filename)) _settings.debugwarnings = false; if (_settings.terminated()) return exitcode; if (!_settings.quiet) { std::string fixedpath = Path::simplifyPath(filename); fixedpath = Path::toNativeSeparators(fixedpath); _errorLogger.reportOut(std::string("Checking ") + fixedpath + ' ' + cfgname + std::string("...")); if (_settings.verbose) { _errorLogger.reportOut("Defines: " + _settings.userDefines); std::string includePaths; for (std::list<std::string>::const_iterator I = _settings.includePaths.begin(); I != _settings.includePaths.end(); ++I) includePaths += " -I" + *I; _errorLogger.reportOut("Includes:" + includePaths); _errorLogger.reportOut(std::string("Platform:") + _settings.platformString()); } } if (plistFile.is_open()) { plistFile << ErrorLogger::plistFooter(); plistFile.close(); } CheckUnusedFunctions checkUnusedFunctions(nullptr, nullptr, nullptr); bool internalErrorFound(false); try { Preprocessor preprocessor(_settings, this); std::set<std::string> configurations; simplecpp::OutputList outputList; std::vector<std::string> files; simplecpp::TokenList tokens1(fileStream, files, filename, &outputList); // If there is a syntax error, report it and stop for (simplecpp::OutputList::const_iterator it = outputList.begin(); it != outputList.end(); ++it) { bool err; switch (it->type) { case simplecpp::Output::ERROR: case simplecpp::Output::INCLUDE_NESTED_TOO_DEEPLY: case simplecpp::Output::SYNTAX_ERROR: case simplecpp::Output::UNHANDLED_CHAR_ERROR: err = true; break; case simplecpp::Output::WARNING: case simplecpp::Output::MISSING_HEADER: case simplecpp::Output::PORTABILITY_BACKSLASH: err = false; break; }; if (err) { const ErrorLogger::ErrorMessage::FileLocation loc1(it->location.file(), it->location.line); std::list<ErrorLogger::ErrorMessage::FileLocation> callstack; callstack.push_back(loc1); ErrorLogger::ErrorMessage errmsg(callstack, "", Severity::error, it->msg, "syntaxError", false); _errorLogger.reportErr(errmsg); return 1; } } preprocessor.loadFiles(tokens1, files); if (!_settings.plistOutput.empty()) { std::string filename2; if (filename.find('/') != std::string::npos) filename2 = filename.substr(filename.rfind('/') + 1); else filename2 = filename; filename2 = _settings.plistOutput + filename2.substr(0, filename2.find('.')) + ".plist"; plistFile.open(filename2); plistFile << ErrorLogger::plistHeader(version(), files); } // write dump file xml prolog std::ofstream fdump; if (_settings.dump) { const std::string dumpfile(_settings.dumpFile.empty() ? (filename + ".dump") : _settings.dumpFile); fdump.open(dumpfile.c_str()); if (fdump.is_open()) { fdump << "<?xml version=\"1.0\"?>" << std::endl; fdump << "<dumps>" << std::endl; fdump << " <platform" << " name=\"" << _settings.platformString() << '\"' << " char_bit=\"" << _settings.char_bit << '\"' << " short_bit=\"" << _settings.short_bit << '\"' << " int_bit=\"" << _settings.int_bit << '\"' << " long_bit=\"" << _settings.long_bit << '\"' << " long_long_bit=\"" << _settings.long_long_bit << '\"' << " pointer_bit=\"" << (_settings.sizeof_pointer * _settings.char_bit) << '\"' << "/>\n"; fdump << " <rawtokens>" << std::endl; for (unsigned int i = 0; i < files.size(); ++i) fdump << " <file index=\"" << i << "\" name=\"" << ErrorLogger::toxml(files[i]) << "\"/>" << std::endl; for (const simplecpp::Token *tok = tokens1.cfront(); tok; tok = tok->next) { fdump << " <tok " << "fileIndex=\"" << tok->location.fileIndex << "\" " << "linenr=\"" << tok->location.line << "\" " << "str=\"" << ErrorLogger::toxml(tok->str) << "\"" << "/>" << std::endl; } fdump << " </rawtokens>" << std::endl; } } // Parse comments and then remove them preprocessor.inlineSuppressions(tokens1); tokens1.removeComments(); preprocessor.removeComments(); if (!_settings.buildDir.empty()) { // Get toolinfo std::string toolinfo; toolinfo += CPPCHECK_VERSION_STRING; toolinfo += _settings.isEnabled(Settings::WARNING) ? 'w' : ' '; toolinfo += _settings.isEnabled(Settings::STYLE) ? 's' : ' '; toolinfo += _settings.isEnabled(Settings::PERFORMANCE) ? 'p' : ' '; toolinfo += _settings.isEnabled(Settings::PORTABILITY) ? 'p' : ' '; toolinfo += _settings.isEnabled(Settings::INFORMATION) ? 'i' : ' '; toolinfo += _settings.userDefines; // Calculate checksum so it can be compared with old checksum / future checksums const unsigned int checksum = preprocessor.calculateChecksum(tokens1, toolinfo); std::list<ErrorLogger::ErrorMessage> errors; if (!analyzerInformation.analyzeFile(_settings.buildDir, filename, cfgname, checksum, &errors)) { while (!errors.empty()) { reportErr(errors.front()); errors.pop_front(); } return exitcode; // known results => no need to reanalyze file } } // Get directives preprocessor.setDirectives(tokens1); preprocessor.simplifyPragmaAsm(&tokens1); preprocessor.setPlatformInfo(&tokens1); // Get configurations.. if (_settings.userDefines.empty() || _settings.force) { Timer t("Preprocessor::getConfigs", _settings.showtime, &S_timerResults); configurations = preprocessor.getConfigs(tokens1); } else { configurations.insert(_settings.userDefines); } if (_settings.checkConfiguration) { for (std::set<std::string>::const_iterator it = configurations.begin(); it != configurations.end(); ++it) (void)preprocessor.getcode(tokens1, *it, files, true); return 0; } // Run define rules on raw code for (std::list<Settings::Rule>::const_iterator it = _settings.rules.begin(); it != _settings.rules.end(); ++it) { if (it->tokenlist != "define") continue; std::string code; const std::list<Directive> &directives = preprocessor.getDirectives(); for (std::list<Directive>::const_iterator dir = directives.begin(); dir != directives.end(); ++dir) { if (dir->str.compare(0,8,"#define ") == 0) code += "#line " + MathLib::toString(dir->linenr) + " \"" + dir->file + "\"\n" + dir->str + '\n'; } Tokenizer tokenizer2(&_settings, this); std::istringstream istr2(code); tokenizer2.list.createTokens(istr2); executeRules("define", tokenizer2); break; } if (!_settings.force && configurations.size() > _settings.maxConfigs) { if (_settings.isEnabled(Settings::INFORMATION)) { tooManyConfigsError(Path::toNativeSeparators(filename),configurations.size()); } else { tooManyConfigs = true; } } std::set<unsigned long long> checksums; unsigned int checkCount = 0; for (std::set<std::string>::const_iterator it = configurations.begin(); it != configurations.end(); ++it) { // bail out if terminated if (_settings.terminated()) break; // Check only a few configurations (default 12), after that bail out, unless --force // was used. if (!_settings.force && ++checkCount > _settings.maxConfigs) break; cfg = *it; // If only errors are printed, print filename after the check if (!_settings.quiet && (!cfg.empty() || it != configurations.begin())) { std::string fixedpath = Path::simplifyPath(filename); fixedpath = Path::toNativeSeparators(fixedpath); _errorLogger.reportOut("Checking " + fixedpath + ": " + cfg + "..."); } if (!_settings.userDefines.empty()) { if (!cfg.empty()) cfg = ";" + cfg; cfg = _settings.userDefines + cfg; } if (_settings.preprocessOnly) { Timer t("Preprocessor::getcode", _settings.showtime, &S_timerResults); std::string codeWithoutCfg = preprocessor.getcode(tokens1, cfg, files, true); t.Stop(); if (codeWithoutCfg.compare(0,5,"#file") == 0) codeWithoutCfg.insert(0U, "//"); std::string::size_type pos = 0; while ((pos = codeWithoutCfg.find("\n#file",pos)) != std::string::npos) codeWithoutCfg.insert(pos+1U, "//"); pos = 0; while ((pos = codeWithoutCfg.find("\n#endfile",pos)) != std::string::npos) codeWithoutCfg.insert(pos+1U, "//"); pos = 0; while ((pos = codeWithoutCfg.find(Preprocessor::macroChar,pos)) != std::string::npos) codeWithoutCfg[pos] = ' '; reportOut(codeWithoutCfg); continue; } Tokenizer _tokenizer(&_settings, this); if (_settings.showtime != SHOWTIME_NONE) _tokenizer.setTimerResults(&S_timerResults); try { bool result; // Create tokens, skip rest of iteration if failed Timer timer("Tokenizer::createTokens", _settings.showtime, &S_timerResults); const simplecpp::TokenList &tokensP = preprocessor.preprocess(tokens1, cfg, files); _tokenizer.createTokens(&tokensP); timer.Stop(); if (tokensP.empty()) continue; // skip rest of iteration if just checking configuration if (_settings.checkConfiguration) continue; // Check raw tokens checkRawTokens(_tokenizer); // Simplify tokens into normal form, skip rest of iteration if failed Timer timer2("Tokenizer::simplifyTokens1", _settings.showtime, &S_timerResults); result = _tokenizer.simplifyTokens1(cfg); timer2.Stop(); if (!result) continue; // dump xml if --dump if (_settings.dump && fdump.is_open()) { fdump << "<dump cfg=\"" << ErrorLogger::toxml(cfg) << "\">" << std::endl; preprocessor.dump(fdump); _tokenizer.dump(fdump); fdump << "</dump>" << std::endl; } // Skip if we already met the same simplified token list if (_settings.force || _settings.maxConfigs > 1) { const unsigned long long checksum = _tokenizer.list.calculateChecksum(); if (checksums.find(checksum) != checksums.end()) { if (_settings.isEnabled(Settings::INFORMATION) && (_settings.debug || _settings.verbose)) purgedConfigurationMessage(filename, cfg); continue; } checksums.insert(checksum); } // Check normal tokens checkNormalTokens(_tokenizer); // Analyze info.. if (!_settings.buildDir.empty()) checkUnusedFunctions.parseTokens(_tokenizer, filename.c_str(), &_settings, false); // simplify more if required, skip rest of iteration if failed if (_simplify) { // if further simplification fails then skip rest of iteration Timer timer3("Tokenizer::simplifyTokenList2", _settings.showtime, &S_timerResults); result = _tokenizer.simplifyTokenList2(); timer3.Stop(); if (!result) continue; // Check simplified tokens checkSimplifiedTokens(_tokenizer); } } catch (const InternalError &e) { internalErrorFound=true; std::list<ErrorLogger::ErrorMessage::FileLocation> locationList; ErrorLogger::ErrorMessage::FileLocation loc; if (e.token) { loc.line = e.token->linenr(); const std::string fixedpath = Path::toNativeSeparators(_tokenizer.list.file(e.token)); loc.setfile(fixedpath); } else { ErrorLogger::ErrorMessage::FileLocation loc2; loc2.setfile(Path::toNativeSeparators(filename)); locationList.push_back(loc2); loc.setfile(_tokenizer.list.getSourceFilePath()); } locationList.push_back(loc); ErrorLogger::ErrorMessage errmsg(locationList, _tokenizer.list.getSourceFilePath(), Severity::error, e.errorMessage, e.id, false); reportErr(errmsg); } } // dumped all configs, close root </dumps> element now if (_settings.dump && fdump.is_open()) fdump << "</dumps>" << std::endl; } catch (const std::runtime_error &e) { internalError(filename, e.what()); } catch (const std::bad_alloc &e) { internalError(filename, e.what()); } catch (const InternalError &e) { internalError(filename, e.errorMessage); exitcode=1; // e.g. reflect a syntax error } analyzerInformation.setFileInfo("CheckUnusedFunctions", checkUnusedFunctions.analyzerInfo()); analyzerInformation.close(); // In jointSuppressionReport mode, unmatched suppressions are // collected after all files are processed if (!_settings.jointSuppressionReport && (_settings.isEnabled(Settings::INFORMATION) || _settings.checkConfiguration)) { reportUnmatchedSuppressions(_settings.nomsg.getUnmatchedLocalSuppressions(filename, isUnusedFunctionCheckEnabled())); } _errorList.clear(); if (internalErrorFound && (exitcode==0)) { exitcode=1; } return exitcode; }