Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 38 additions & 21 deletions cli/cppcheckexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,21 +361,11 @@ bool CppCheckExecutor::reportUnmatchedSuppressions(const Settings &settings, con
supprlist.addSuppression(std::move(s));
}

const auto reportErrorsFn = [&](const std::string& sourcefile, std::size_t fsFileId, const std::vector<ErrorMessage>& errors) -> bool {
const auto reportErrorsFn = [&](const std::vector<ErrorMessage>& errors) -> bool {
if (errors.empty())
return false;

// TODO: what if sourcefile is empty?

AnalyzerInformation analyzerInfo;
// FIXME: this is a horrible hack
// we need to "re-open" the file so we can add the unmatchedSuppression findings.
// we cannot keep it open conditionally because the whole program analysis reads the XML.
// re-ordering the code is also not an option because the unmatched suppression reporting needs to be run after all other checks.
analyzerInfo.reopen(settings.buildDir, sourcefile, /*cfgname*/ "", fsFileId);

for (const auto& errmsg : errors) {
analyzerInfo.reportErr(errmsg);
errorLogger.reportErr(errmsg);
}
return true;
Expand All @@ -385,30 +375,24 @@ bool CppCheckExecutor::reportUnmatchedSuppressions(const Settings &settings, con

for (auto i = files.cbegin(); i != files.cend(); ++i) {
const std::vector<ErrorMessage> errors = getUnmatchedSuppressions(supprlist.getUnmatchedLocalSuppressions(*i), settings.unmatchedSuppressionFilters);
err |= reportErrorsFn(i->spath(), i->fsFileId(), errors);
err |= reportErrorsFn(errors);
}

for (auto i = fileSettings.cbegin(); i != fileSettings.cend(); ++i) {
const std::vector<ErrorMessage> errors = getUnmatchedSuppressions(supprlist.getUnmatchedLocalSuppressions(i->file), settings.unmatchedSuppressionFilters);
err |= reportErrorsFn(i->file.spath(), i->file.fsFileId(), errors);
err |= reportErrorsFn(errors);
}

if (settings.inlineSuppressions) {
const std::vector<ErrorMessage> errors = getUnmatchedSuppressions(supprlist.getUnmatchedInlineSuppressions(), settings.unmatchedSuppressionFilters);
for (const auto& errmsg : errors) {
std::string sourcefile;
if (!errmsg.callStack.empty())
sourcefile = errmsg.callStack.cbegin()->getfile(false); // TODO: simplify path?
err |= reportErrorsFn(sourcefile, 0, {errmsg});
err |= reportErrorsFn({errmsg});
}
}

const std::vector<ErrorMessage> errors = getUnmatchedSuppressions(supprlist.getUnmatchedGlobalSuppressions(), settings.unmatchedSuppressionFilters);
for (const auto& errmsg : errors) {
std::string sourcefile;
if (!errmsg.callStack.empty())
sourcefile = errmsg.callStack.cbegin()->getfile(false); // TODO: simplify path?
err |= reportErrorsFn(sourcefile, 0, {errmsg});
err |= reportErrorsFn({errmsg});
}
return err;
}
Expand Down Expand Up @@ -469,6 +453,39 @@ int CppCheckExecutor::check_internal(const Settings& settings, Suppressions& sup
// TODO: is this run again instead of using previously cached results?
returnValue |= cppcheck.analyseWholeProgram(settings.buildDir, mFiles, mFileSettings, stdLogger.getCtuInfo());

if (settings.inlineSuppressions && !settings.buildDir.empty())
{
auto s = supprs.nomsg.getSuppressions();
if (!s.empty()) {
std::ofstream fout(Path::join(settings.buildDir, "supprstate.xml"));

/*
{
const char * const supprStr = e->Attribute("str");
const char * const supprChecked = e->Attribute("checked");
const char * const supprMatched = e->Attribute("matched");
SuppressionList::Suppression s = SuppressionList::parseLine(supprStr);
s.checked = supprChecked == "true";
s.matched = supprMatched == "true";
mSuppressions.nomsg.updateSuppressionState(s); // TODO: check result
}
*/

fout << "<suppressions>";

for (const auto& suppr : s)
{
if (!suppr.isInline)
continue;
if (!suppr.checked)
continue;
fout << "<suppression str=\"\"" << suppr.toString() << "\"" << " checked=\"" << suppr.checked << " matched=\"" << suppr.matched << "\"/>";
}

fout << "</suppressions>";
}
}

if ((settings.severity.isEnabled(Severity::information) || settings.checkConfiguration) && !supprs.nomsg.getSuppressions().empty()) {
const bool err = reportUnmatchedSuppressions(settings, supprs.nomsg, mFiles, mFileSettings, stdLogger);
if (err && returnValue == 0)
Expand Down
21 changes: 0 additions & 21 deletions lib/analyzerinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,24 +293,3 @@ std::string AnalyzerInformation::processFilesTxt(const std::string& buildDir, co
// TODO: error on empty file?
return "";
}

void AnalyzerInformation::reopen(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t fsFileId)
{
if (buildDir.empty() || sourcefile.empty())
return;

const std::string analyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(buildDir,sourcefile,cfg,fsFileId);
std::ifstream ifs(analyzerInfoFile);
if (!ifs.is_open())
return;

std::ostringstream iss;
iss << ifs.rdbuf();
ifs.close();

std::string content = iss.str();
content.resize(content.find("</analyzerinfo>"));

mOutputStream.open(analyzerInfoFile, std::ios::trunc);
mOutputStream << content;
}
2 changes: 0 additions & 2 deletions lib/analyzerinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ class CPPCHECKLIB AnalyzerInformation {
void setFileInfo(const std::string &check, const std::string &fileInfo);
static std::string getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t fsFileId);

void reopen(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t fsFileId);

static const char sep = ':';

class CPPCHECKLIB Info {
Expand Down
1 change: 1 addition & 0 deletions lib/cppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,7 @@ std::size_t CppCheck::calculateHash(const Preprocessor& preprocessor, const std:
toolinfo << a.args;
}
toolinfo << mSettings.premiumArgs;
toolinfo << mSettings.inlineSuppressions;
// TODO: do we need to add more options?
mSuppressions.nomsg.dump(toolinfo, filePath);
return preprocessor.calculateHash(toolinfo.str());
Expand Down