void VerifyDiagnosticConsumer::HandleDiagnostic( DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) { if (Info.hasSourceManager()) { // If this diagnostic is for a different source manager, ignore it. if (SrcManager && &Info.getSourceManager() != SrcManager) return; setSourceManager(Info.getSourceManager()); } #ifndef NDEBUG // Debug build tracks unparsed files for possible // unparsed expected-* directives. if (SrcManager) { SourceLocation Loc = Info.getLocation(); if (Loc.isValid()) { ParsedStatus PS = IsUnparsed; Loc = SrcManager->getExpansionLoc(Loc); FileID FID = SrcManager->getFileID(Loc); const FileEntry *FE = SrcManager->getFileEntryForID(FID); if (FE && CurrentPreprocessor && SrcManager->isLoadedFileID(FID)) { // If the file is a modules header file it shall not be parsed // for expected-* directives. HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo(); if (HS.findModuleForHeader(FE)) PS = IsUnparsedNoDirectives; } UpdateParsedFileStatus(*SrcManager, FID, PS); } } #endif // Send the diagnostic to the buffer, we will check it once we reach the end // of the source file (or are destructed). Buffer->HandleDiagnostic(DiagLevel, Info); }
void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) { if (DiagLevel != DiagnosticsEngine::Note) { if (inNonNoteDiagnostic) { // We have encountered a non-note diagnostic. Finish up the previous // diagnostic block before starting a new one. Stream.ExitBlock(); } inNonNoteDiagnostic = true; } // Compute the diagnostic text. diagBuf.clear(); Info.FormatDiagnostic(diagBuf); SourceManager &SM = Info.getSourceManager(); SDiagsRenderer Renderer(*this, Record, SM, *LangOpts, DiagOpts); Renderer.emitDiagnostic(Info.getLocation(), DiagLevel, diagBuf.str(), Info.getRanges(), llvm::makeArrayRef(Info.getFixItHints(), Info.getNumFixItHints()), &Info); }
void FixItRewriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) { // Default implementation (Warnings/errors count). DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info); if (!FixItOpts->Silent || DiagLevel >= DiagnosticsEngine::Error || (DiagLevel == DiagnosticsEngine::Note && !PrevDiagSilenced) || (DiagLevel > DiagnosticsEngine::Note && Info.getNumFixItHints())) { Client->HandleDiagnostic(DiagLevel, Info); PrevDiagSilenced = false; } else { PrevDiagSilenced = true; } // Skip over any diagnostics that are ignored or notes. if (DiagLevel <= DiagnosticsEngine::Note) return; // Skip over errors if we are only fixing warnings. if (DiagLevel >= DiagnosticsEngine::Error && FixItOpts->FixOnlyWarnings) { ++NumFailures; return; } // Make sure that we can perform all of the modifications we // in this diagnostic. edit::Commit commit(Editor); for (unsigned Idx = 0, Last = Info.getNumFixItHints(); Idx < Last; ++Idx) { const FixItHint &Hint = Info.getFixItHint(Idx); if (Hint.CodeToInsert.empty()) { if (Hint.InsertFromRange.isValid()) commit.insertFromRange(Hint.RemoveRange.getBegin(), Hint.InsertFromRange, /*afterToken=*/false, Hint.BeforePreviousInsertions); else commit.remove(Hint.RemoveRange); } else { if (Hint.RemoveRange.isTokenRange() || Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd()) commit.replace(Hint.RemoveRange, Hint.CodeToInsert); else commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert, /*afterToken=*/false, Hint.BeforePreviousInsertions); } } bool CanRewrite = Info.getNumFixItHints() > 0 && commit.isCommitable(); if (!CanRewrite) { if (Info.getNumFixItHints() > 0) Diag(Info.getLocation(), diag::note_fixit_in_macro); // If this was an error, refuse to perform any rewriting. if (DiagLevel >= DiagnosticsEngine::Error) { if (++NumFailures == 1) Diag(Info.getLocation(), diag::note_fixit_unfixed_error); } return; } if (!Editor.commit(commit)) { ++NumFailures; Diag(Info.getLocation(), diag::note_fixit_failed); return; } Diag(Info.getLocation(), diag::note_fixit_applied); }
void FixItRewriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) { // Default implementation (Warnings/errors count). DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info); if (!FixItOpts->Silent || DiagLevel >= DiagnosticsEngine::Error || (DiagLevel == DiagnosticsEngine::Note && !PrevDiagSilenced) || (DiagLevel > DiagnosticsEngine::Note && Info.getNumFixItHints())) { Client->HandleDiagnostic(DiagLevel, Info); PrevDiagSilenced = false; } else { PrevDiagSilenced = true; } // Skip over any diagnostics that are ignored or notes. if (DiagLevel <= DiagnosticsEngine::Note) return; // Skip over errors if we are only fixing warnings. if (DiagLevel >= DiagnosticsEngine::Error && FixItOpts->FixOnlyWarnings) { ++NumFailures; return; } // Make sure that we can perform all of the modifications we // in this diagnostic. bool CanRewrite = Info.getNumFixItHints() > 0; for (unsigned Idx = 0, Last = Info.getNumFixItHints(); Idx < Last; ++Idx) { const FixItHint &Hint = Info.getFixItHint(Idx); if (Hint.RemoveRange.isValid() && Rewrite.getRangeSize(Hint.RemoveRange) == -1) { CanRewrite = false; break; } } if (!CanRewrite) { if (Info.getNumFixItHints() > 0) Diag(Info.getLocation(), diag::note_fixit_in_macro); // If this was an error, refuse to perform any rewriting. if (DiagLevel >= DiagnosticsEngine::Error) { if (++NumFailures == 1) Diag(Info.getLocation(), diag::note_fixit_unfixed_error); } return; } bool Failed = false; for (unsigned Idx = 0, Last = Info.getNumFixItHints(); Idx < Last; ++Idx) { const FixItHint &Hint = Info.getFixItHint(Idx); if (Hint.CodeToInsert.empty()) { // We're removing code. if (Rewrite.RemoveText(Hint.RemoveRange)) Failed = true; continue; } // We're replacing code. if (Rewrite.ReplaceText(Hint.RemoveRange.getBegin(), Rewrite.getRangeSize(Hint.RemoveRange), Hint.CodeToInsert)) Failed = true; } if (Failed) { ++NumFailures; Diag(Info.getLocation(), diag::note_fixit_failed); return; } Diag(Info.getLocation(), diag::note_fixit_applied); }
void ClangTidyDiagnosticConsumer::HandleDiagnostic( DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) { if (LastErrorWasIgnored && DiagLevel == DiagnosticsEngine::Note) return; if (Info.getLocation().isValid() && DiagLevel != DiagnosticsEngine::Error && DiagLevel != DiagnosticsEngine::Fatal && LineIsMarkedWithNOLINTinMacro(Diags->getSourceManager(), Info.getLocation())) { ++Context.Stats.ErrorsIgnoredNOLINT; // Ignored a warning, should ignore related notes as well LastErrorWasIgnored = true; return; } LastErrorWasIgnored = false; // Count warnings/errors. DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info); if (DiagLevel == DiagnosticsEngine::Note) { assert(!Errors.empty() && "A diagnostic note can only be appended to a message."); } else { finalizeLastError(); StringRef WarningOption = Context.DiagEngine->getDiagnosticIDs()->getWarningOptionForDiag( Info.getID()); std::string CheckName = !WarningOption.empty() ? ("clang-diagnostic-" + WarningOption).str() : Context.getCheckName(Info.getID()).str(); if (CheckName.empty()) { // This is a compiler diagnostic without a warning option. Assign check // name based on its level. switch (DiagLevel) { case DiagnosticsEngine::Error: case DiagnosticsEngine::Fatal: CheckName = "clang-diagnostic-error"; break; case DiagnosticsEngine::Warning: CheckName = "clang-diagnostic-warning"; break; default: CheckName = "clang-diagnostic-unknown"; break; } } ClangTidyError::Level Level = ClangTidyError::Warning; if (DiagLevel == DiagnosticsEngine::Error || DiagLevel == DiagnosticsEngine::Fatal) { // Force reporting of Clang errors regardless of filters and non-user // code. Level = ClangTidyError::Error; LastErrorRelatesToUserCode = true; LastErrorPassesLineFilter = true; } bool IsWarningAsError = DiagLevel == DiagnosticsEngine::Warning && Context.getWarningAsErrorFilter().contains(CheckName); Errors.emplace_back(CheckName, Level, Context.getCurrentBuildDirectory(), IsWarningAsError); } ClangTidyDiagnosticRenderer Converter( Context.getLangOpts(), &Context.DiagEngine->getDiagnosticOptions(), Errors.back()); SmallString<100> Message; Info.FormatDiagnostic(Message); SourceManager *Sources = nullptr; if (Info.hasSourceManager()) Sources = &Info.getSourceManager(); Converter.emitDiagnostic(Info.getLocation(), DiagLevel, Message, Info.getRanges(), Info.getFixItHints(), Sources); checkFilters(Info.getLocation()); }