@@ -299,9 +299,10 @@ int CppCheckExecutor::check_wrapper(const Settings& settings, Suppressions& supp
299299 * @param unmatched list of unmatched suppressions (from Settings::Suppressions::getUnmatched(Local|Global)Suppressions)
300300 * @return true is returned if errors are reported
301301 */
302- static bool reportUnmatchedSuppressions (const std::list<SuppressionList::Suppression> &unmatched, ErrorLogger &errorLogger , const std::vector<std::string>& filters)
302+ static std::vector<::ErrorMessage> reportUnmatchedSuppressions (const std::list<SuppressionList::Suppression> &unmatched, const std::vector<std::string>& filters)
303303{
304- bool err = false ;
304+ std::vector<::ErrorMessage> errors;
305+
305306 // Report unmatched suppressions
306307 for (const SuppressionList::Suppression &s : unmatched) {
307308 // check if this unmatched suppression is suppressed
@@ -329,10 +330,11 @@ static bool reportUnmatchedSuppressions(const std::list<SuppressionList::Suppres
329330 if (!s.fileName .empty ()) {
330331 callStack.emplace_back (s.fileName , s.lineNumber , 0 );
331332 }
332- errorLogger. reportErr ( ::ErrorMessage (std::move (callStack), " " , Severity::information, " Unmatched suppression: " + s.errorId , " unmatchedSuppression" , Certainty::normal) );
333- err = true ;
333+ auto errmsg = ::ErrorMessage (std::move (callStack), " " , Severity::information, " Unmatched suppression: " + s.errorId , " unmatchedSuppression" , Certainty::normal);
334+ errors. emplace_back ( std::move (errmsg)) ;
334335 }
335- return err;
336+
337+ return errors;
336338}
337339
338340bool CppCheckExecutor::reportUnmatchedSuppressions (const Settings &settings, const SuppressionList& suppressions, const std::list<FileWithDetails> &files, const std::list<FileSettings>& fileSettings, ErrorLogger& errorLogger) {
@@ -358,21 +360,55 @@ bool CppCheckExecutor::reportUnmatchedSuppressions(const Settings &settings, con
358360 supprlist.addSuppression (std::move (s));
359361 }
360362
363+ const auto reportErrorsFn = [&](const std::string& sourcefile, std::size_t fsFileId, const std::vector<::ErrorMessage>& errors) -> bool {
364+ if (errors.empty ())
365+ return false ;
366+
367+ // TODO: what if sourcefile is empty?
368+
369+ AnalyzerInformation analyzerInfo;
370+ // FIXME: this is a horrible hack
371+ // we need to "re-open" the file so we can add the unmatchedSuppression findings.
372+ // we cannot keep it open conditionally because the whole program analysis read the XML.
373+ // re-ordering is also not an option because the unmatched suppression reporting needs to be run after all other checks.
374+ analyzerInfo.reopen (settings.buildDir , sourcefile, /* cfgname*/ " " , fsFileId);
375+
376+ for (const auto & errmsg : errors) {
377+ analyzerInfo.reportErr (errmsg);
378+ errorLogger.reportErr (errmsg);
379+ }
380+ return true ;
381+ };
382+
361383 bool err = false ;
362384
363385 for (auto i = files.cbegin (); i != files.cend (); ++i) {
364- err |= ::reportUnmatchedSuppressions (supprlist.getUnmatchedLocalSuppressions (*i), errorLogger, settings.unmatchedSuppressionFilters );
386+ const std::vector<ErrorMessage> errors = ::reportUnmatchedSuppressions (supprlist.getUnmatchedLocalSuppressions (*i), settings.unmatchedSuppressionFilters );
387+ err |= reportErrorsFn (i->spath (), 0 , errors);
365388 }
366389
367390 for (auto i = fileSettings.cbegin (); i != fileSettings.cend (); ++i) {
368- err |= ::reportUnmatchedSuppressions (supprlist.getUnmatchedLocalSuppressions (i->file ), errorLogger, settings.unmatchedSuppressionFilters );
391+ const std::vector<ErrorMessage> errors = ::reportUnmatchedSuppressions (supprlist.getUnmatchedLocalSuppressions (i->file ), settings.unmatchedSuppressionFilters );
392+ err |= reportErrorsFn (i->file .spath (), i->fileIndex , errors);
369393 }
370394
371395 if (settings.inlineSuppressions ) {
372- err |= ::reportUnmatchedSuppressions (supprlist.getUnmatchedInlineSuppressions (), errorLogger, settings.unmatchedSuppressionFilters );
396+ const std::vector<ErrorMessage> errors = ::reportUnmatchedSuppressions (supprlist.getUnmatchedInlineSuppressions (), settings.unmatchedSuppressionFilters );
397+ for (const auto & errmsg : errors) {
398+ std::string sourcefile;
399+ if (!errmsg.callStack .empty ())
400+ sourcefile = errmsg.callStack .cbegin ()->getfile ();
401+ err |= reportErrorsFn (sourcefile, 0 , {errmsg});
402+ }
373403 }
374404
375- err |= ::reportUnmatchedSuppressions (supprlist.getUnmatchedGlobalSuppressions (), errorLogger, settings.unmatchedSuppressionFilters );
405+ const std::vector<ErrorMessage> errors = ::reportUnmatchedSuppressions (supprlist.getUnmatchedGlobalSuppressions (), settings.unmatchedSuppressionFilters );
406+ for (const auto & errmsg : errors) {
407+ std::string sourcefile;
408+ if (!errmsg.callStack .empty ())
409+ sourcefile = errmsg.callStack .cbegin ()->getfile ();
410+ err |= reportErrorsFn (sourcefile, 0 , {errmsg});
411+ }
376412 return err;
377413}
378414
@@ -425,9 +461,10 @@ int CppCheckExecutor::check_internal(const Settings& settings, Suppressions& sup
425461#endif
426462 }
427463
464+ // TODO: is this run again instead of using previously cached results?
428465 returnValue |= cppcheck.analyseWholeProgram (settings.buildDir , mFiles , mFileSettings , stdLogger.getCtuInfo ());
429466
430- if (settings.severity .isEnabled (Severity::information) || settings.checkConfiguration ) {
467+ if (( settings.severity .isEnabled (Severity::information) || settings.checkConfiguration ) && !supprs. nomsg . getSuppressions (). empty () ) {
431468 const bool err = reportUnmatchedSuppressions (settings, supprs.nomsg , mFiles , mFileSettings , stdLogger);
432469 if (err && returnValue == 0 )
433470 returnValue = settings.exitCode ;
0 commit comments