FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr, const LangOptions &LangOpts, FixItPathRewriter *PathRewriter) : Diags(Diags), Rewrite(SourceMgr, LangOpts), PathRewriter(PathRewriter), NumFailures(0) { Client = Diags.getClient(); Diags.setClient(this); }
/// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const { DiagnosticInfo Info(&Diag); if (Diag.SuppressAllDiagnostics) return false; assert(Diag.getClient() && "DiagnosticClient not set!"); // Figure out the diagnostic level of this message. DiagnosticIDs::Level DiagLevel; unsigned DiagID = Info.getID(); if (DiagID >= diag::DIAG_UPPER_LIMIT) { // Handle custom diagnostics, which cannot be mapped. DiagLevel = CustomDiagInfo->getLevel(DiagID); } else { // Get the class of the diagnostic. If this is a NOTE, map it onto whatever // the diagnostic level was for the previous diagnostic so that it is // filtered the same as the previous diagnostic. unsigned DiagClass = getBuiltinDiagClass(DiagID); if (DiagClass == CLASS_NOTE) { DiagLevel = DiagnosticIDs::Note; } else { DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Info.getLocation(), Diag); } } if (DiagLevel != DiagnosticIDs::Note) { // Record that a fatal error occurred only when we see a second // non-note diagnostic. This allows notes to be attached to the // fatal error, but suppresses any diagnostics that follow those // notes. if (Diag.LastDiagLevel == DiagnosticIDs::Fatal) Diag.FatalErrorOccurred = true; Diag.LastDiagLevel = DiagLevel; } // If a fatal error has already been emitted, silence all subsequent // diagnostics. if (Diag.FatalErrorOccurred) { if (DiagLevel >= DiagnosticIDs::Error && Diag.Client->IncludeInDiagnosticCounts()) { ++Diag.NumErrors; ++Diag.NumErrorsSuppressed; } return false; } // If the client doesn't care about this message, don't issue it. If this is // a note and the last real diagnostic was ignored, ignore it too. if (DiagLevel == DiagnosticIDs::Ignored || (DiagLevel == DiagnosticIDs::Note && Diag.LastDiagLevel == DiagnosticIDs::Ignored)) return false; if (DiagLevel >= DiagnosticIDs::Error) { Diag.TrapErrorOccurred = true; if (isUnrecoverable(DiagID)) { Diag.TrapUnrecoverableErrorOccurred = true; Diag.UnrecoverableErrorOccurred = true; } if (Diag.Client->IncludeInDiagnosticCounts()) { Diag.ErrorOccurred = true; ++Diag.NumErrors; } // If we've emitted a lot of errors, emit a fatal error after it to stop a // flood of bogus errors. if (Diag.ErrorLimit && Diag.NumErrors >= Diag.ErrorLimit && DiagLevel == DiagnosticIDs::Error) Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors); } // If we have any Fix-Its, make sure that all of the Fix-Its point into // source locations that aren't macro instantiations. If any point into // macro instantiations, remove all of the Fix-Its. for (unsigned I = 0, N = Diag.NumFixItHints; I != N; ++I) { const FixItHint &FixIt = Diag.FixItHints[I]; if (FixIt.RemoveRange.isInvalid() || FixIt.RemoveRange.getBegin().isMacroID() || FixIt.RemoveRange.getEnd().isMacroID()) { Diag.NumFixItHints = 0; break; } } // Finally, report it. Diag.Client->HandleDiagnostic((Diagnostic::Level)DiagLevel, Info); if (Diag.Client->IncludeInDiagnosticCounts()) { if (DiagLevel == DiagnosticIDs::Warning) ++Diag.NumWarnings; } Diag.CurDiagID = ~0U; return true; }
/// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const { DiagnosticInfo Info(&Diag); if (Diag.SuppressAllDiagnostics) return false; assert(Diag.getClient() && "DiagnosticClient not set!"); // Figure out the diagnostic level of this message. DiagnosticIDs::Level DiagLevel; unsigned DiagID = Info.getID(); // ShouldEmitInSystemHeader - True if this diagnostic should be produced even // in a system header. bool ShouldEmitInSystemHeader; if (DiagID >= diag::DIAG_UPPER_LIMIT) { // Handle custom diagnostics, which cannot be mapped. DiagLevel = CustomDiagInfo->getLevel(DiagID); // Custom diagnostics always are emitted in system headers. ShouldEmitInSystemHeader = true; } else { // Get the class of the diagnostic. If this is a NOTE, map it onto whatever // the diagnostic level was for the previous diagnostic so that it is // filtered the same as the previous diagnostic. unsigned DiagClass = getBuiltinDiagClass(DiagID); if (DiagClass == CLASS_NOTE) { DiagLevel = DiagnosticIDs::Note; ShouldEmitInSystemHeader = false; // extra consideration is needed } else { // If this is not an error and we are in a system header, we ignore it. // Check the original Diag ID here, because we also want to ignore // extensions and warnings in -Werror and -pedantic-errors modes, which // *map* warnings/extensions to errors. ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR; DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Info.getLocation(), Diag); } } if (DiagLevel != DiagnosticIDs::Note) { // Record that a fatal error occurred only when we see a second // non-note diagnostic. This allows notes to be attached to the // fatal error, but suppresses any diagnostics that follow those // notes. if (Diag.LastDiagLevel == DiagnosticIDs::Fatal) Diag.FatalErrorOccurred = true; Diag.LastDiagLevel = DiagLevel; } // If a fatal error has already been emitted, silence all subsequent // diagnostics. if (Diag.FatalErrorOccurred) { if (DiagLevel >= DiagnosticIDs::Error && Diag.Client->IncludeInDiagnosticCounts()) { ++Diag.NumErrors; ++Diag.NumErrorsSuppressed; } return false; } // If the client doesn't care about this message, don't issue it. If this is // a note and the last real diagnostic was ignored, ignore it too. if (DiagLevel == DiagnosticIDs::Ignored || (DiagLevel == DiagnosticIDs::Note && Diag.LastDiagLevel == DiagnosticIDs::Ignored)) return false; // If this diagnostic is in a system header and is not a clang error, suppress // it. if (Diag.SuppressSystemWarnings && !ShouldEmitInSystemHeader && Info.getLocation().isValid() && Diag.getSourceManager().isInSystemHeader( Diag.getSourceManager().getInstantiationLoc(Info.getLocation())) && (DiagLevel != DiagnosticIDs::Note || Diag.LastDiagLevel == DiagnosticIDs::Ignored)) { Diag.LastDiagLevel = DiagnosticIDs::Ignored; return false; } if (DiagLevel >= DiagnosticIDs::Error) { if (Diag.Client->IncludeInDiagnosticCounts()) { Diag.ErrorOccurred = true; ++Diag.NumErrors; } // If we've emitted a lot of errors, emit a fatal error after it to stop a // flood of bogus errors. if (Diag.ErrorLimit && Diag.NumErrors >= Diag.ErrorLimit && DiagLevel == DiagnosticIDs::Error) Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors); } // If we have any Fix-Its, make sure that all of the Fix-Its point into // source locations that aren't macro instantiations. If any point into // macro instantiations, remove all of the Fix-Its. for (unsigned I = 0, N = Diag.NumFixItHints; I != N; ++I) { const FixItHint &FixIt = Diag.FixItHints[I]; if (FixIt.RemoveRange.isInvalid() || FixIt.RemoveRange.getBegin().isMacroID() || FixIt.RemoveRange.getEnd().isMacroID()) { Diag.NumFixItHints = 0; break; } } // Finally, report it. Diag.Client->HandleDiagnostic((Diagnostic::Level)DiagLevel, Info); if (Diag.Client->IncludeInDiagnosticCounts()) { if (DiagLevel == DiagnosticIDs::Warning) ++Diag.NumWarnings; } Diag.CurDiagID = ~0U; return true; }