diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 96fdd2011..1f2fb5997 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -187,6 +187,52 @@ static std::vector split(const std::string &str, const std::string return ret; } +static void createDumpFile(const Settings& settings, + const std::string& filename, + const std::vector& files, + const simplecpp::Token* rawtokens, + std::ofstream& fdump, + std::string& dumpFile) +{ + if (!settings.dump && settings.addons.empty()) + return; + if (!settings.dumpFile.empty()) + dumpFile = settings.dumpFile; + else if (!settings.dump && !settings.buildDir.empty()) + dumpFile = AnalyzerInformation::getAnalyzerInfoFile(settings.buildDir, filename, "") + ".dump"; + else + dumpFile = filename + ".dump"; + + fdump.open(dumpFile); + if (!fdump.is_open()) + return; + fdump << "" << std::endl; + fdump << "" << std::endl; + fdump << " \n"; + if (rawtokens) { + fdump << " " << std::endl; + for (unsigned int i = 0; i < files.size(); ++i) + fdump << " " << std::endl; + for (const simplecpp::Token *tok = rawtokens; tok; tok = tok->next) { + fdump << " location.fileIndex << "\" " + << "linenr=\"" << tok->location.line << "\" " + << "column=\"" << tok->location.col << "\" " + << "str=\"" << ErrorLogger::toxml(tok->str()) << "\"" + << "/>" << std::endl; + } + fdump << " " << std::endl; + } +} + static std::string executeAddon(const AddonInfo &addonInfo, const std::string &defaultPythonExe, const std::string &dumpFile, @@ -392,6 +438,26 @@ unsigned int CppCheck::check(const std::string &path) if (mSettings.debugnormal) tokenizer.printDebugOutput(1); checkNormalTokens(tokenizer); + + // create dumpfile + std::ofstream fdump; + std::string dumpFile; + createDumpFile(mSettings, path, tokenizer.list.getFiles(), nullptr, fdump, dumpFile); + if (fdump.is_open()) { + fdump << "" << std::endl; + fdump << " " << std::endl; + fdump << " " << std::endl; + fdump << " " << std::endl; + fdump << " " << std::endl; + tokenizer.dump(fdump); + fdump << "" << std::endl; + fdump << "" << std::endl; + fdump.close(); + } + + // run addons + executeAddons(dumpFile); + } catch (const InternalError &e) { internalError(path, e.errorMessage); mExitCode = 1; // e.g. reflect a syntax error @@ -540,41 +606,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string // write dump file xml prolog std::ofstream fdump; std::string dumpFile; - if (mSettings.dump || !mSettings.addons.empty()) { - if (!mSettings.dumpFile.empty()) - dumpFile = mSettings.dumpFile; - else if (!mSettings.dump && !mSettings.buildDir.empty()) - dumpFile = AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, filename, "") + ".dump"; - else - dumpFile = filename + ".dump"; - - fdump.open(dumpFile); - if (fdump.is_open()) { - fdump << "" << std::endl; - fdump << "" << std::endl; - fdump << " \n"; - fdump << " " << std::endl; - for (unsigned int i = 0; i < files.size(); ++i) - fdump << " " << std::endl; - for (const simplecpp::Token *tok = tokens1.cfront(); tok; tok = tok->next) { - fdump << " location.fileIndex << "\" " - << "linenr=\"" << tok->location.line << "\" " - << "column=\"" << tok->location.col << "\" " - << "str=\"" << ErrorLogger::toxml(tok->str()) << "\"" - << "/>" << std::endl; - } - fdump << " " << std::endl; - } - } + createDumpFile(mSettings, filename, files, tokens1.cfront(), fdump, dumpFile); // Parse comments and then remove them preprocessor.inlineSuppressions(tokens1); @@ -834,60 +866,13 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string } // dumped all configs, close root element now - if ((mSettings.dump || !mSettings.addons.empty()) && fdump.is_open()) + if (fdump.is_open()) { fdump << "" << std::endl; - - if (!mSettings.addons.empty()) { fdump.close(); - - for (const std::string &addon : mSettings.addons) { - struct AddonInfo addonInfo; - const std::string &failedToGetAddonInfo = addonInfo.getAddonInfo(addon, mSettings.exename); - if (!failedToGetAddonInfo.empty()) { - reportOut(failedToGetAddonInfo); - mExitCode = 1; - continue; - } - const std::string results = - executeAddon(addonInfo, mSettings.addonPython, dumpFile, mExecuteCommand); - std::istringstream istr(results); - std::string line; - - while (std::getline(istr, line)) { - if (line.compare(0,1,"{") != 0) - continue; - - picojson::value res; - std::istringstream istr2(line); - istr2 >> res; - if (!res.is()) - continue; - - picojson::object obj = res.get(); - - const std::string fileName = obj["file"].get(); - const int64_t lineNumber = obj["linenr"].get(); - const int64_t column = obj["column"].get(); - - ErrorMessage errmsg; - - errmsg.callStack.emplace_back(ErrorMessage::FileLocation(fileName, lineNumber, column)); - - errmsg.id = obj["addon"].get() + "-" + obj["errorId"].get(); - const std::string text = obj["message"].get(); - errmsg.setmsg(text); - const std::string severity = obj["severity"].get(); - errmsg.severity = Severity::fromString(severity); - if (errmsg.severity == Severity::SeverityType::none) - continue; - errmsg.file0 = fileName; - - reportErr(errmsg); - } - } - std::remove(dumpFile.c_str()); } + executeAddons(dumpFile); + } catch (const std::runtime_error &e) { internalError(filename, e.what()); } catch (const std::bad_alloc &e) { @@ -1270,6 +1255,60 @@ void CppCheck::executeRules(const std::string &tokenlist, const Tokenizer &token #endif } +void CppCheck::executeAddons(const std::string& dumpFile) +{ + + if (!mSettings.addons.empty() && !dumpFile.empty()) { + for (const std::string &addon : mSettings.addons) { + struct AddonInfo addonInfo; + const std::string &failedToGetAddonInfo = addonInfo.getAddonInfo(addon, mSettings.exename); + if (!failedToGetAddonInfo.empty()) { + reportOut(failedToGetAddonInfo); + mExitCode = 1; + continue; + } + const std::string results = + executeAddon(addonInfo, mSettings.addonPython, dumpFile, mExecuteCommand); + std::istringstream istr(results); + std::string line; + + while (std::getline(istr, line)) { + if (line.compare(0,1,"{") != 0) + continue; + + picojson::value res; + std::istringstream istr2(line); + istr2 >> res; + if (!res.is()) + continue; + + picojson::object obj = res.get(); + + const std::string fileName = obj["file"].get(); + const int64_t lineNumber = obj["linenr"].get(); + const int64_t column = obj["column"].get(); + + ErrorMessage errmsg; + + errmsg.callStack.emplace_back(ErrorMessage::FileLocation(fileName, lineNumber, column)); + + errmsg.id = obj["addon"].get() + "-" + obj["errorId"].get(); + const std::string text = obj["message"].get(); + errmsg.setmsg(text); + const std::string severity = obj["severity"].get(); + errmsg.severity = Severity::fromString(severity); + if (errmsg.severity == Severity::SeverityType::none) + continue; + errmsg.file0 = fileName; + + reportErr(errmsg); + } + } + std::remove(dumpFile.c_str()); + } + +} + Settings &CppCheck::settings() { return mSettings; diff --git a/lib/cppcheck.h b/lib/cppcheck.h index e202b51e4..ad8d6519d 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -143,7 +143,6 @@ public: bool isUnusedFunctionCheckEnabled() const; private: - /** Are there "simple" rules */ bool hasRule(const std::string &tokenlist) const; @@ -171,6 +170,11 @@ private: */ void checkNormalTokens(const Tokenizer &tokenizer); + /** + * Execute addons + */ + void executeAddons(const std::string &dumpFile); + /** * @brief Execute rules, if any * @param tokenlist token list to use (normal / simple) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index e1969d715..1e01525db 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -3705,7 +3705,8 @@ void SymbolDatabase::printXml(std::ostream &out) const out << " typeEndToken=\"" << var->typeEndToken() << '\"'; out << " access=\"" << accessControlToString(var->mAccess) << '\"'; out << " scope=\"" << var->scope() << '\"'; - out << " constness=\"" << var->valueType()->constness << '\"'; + if (var->valueType()) + out << " constness=\"" << var->valueType()->constness << '\"'; out << " isArgument=\"" << var->isArgument() << '\"'; out << " isArray=\"" << var->isArray() << '\"'; out << " isClass=\"" << var->isClass() << '\"';