/// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { Diagnostic Info(&Diag); if (Diag.SuppressAllDiagnostics) return false; assert(Diag.getClient() && "DiagnosticClient not set!"); // Figure out the diagnostic level of this message. unsigned DiagID = Info.getID(); DiagnosticIDs::Level DiagLevel = getDiagnosticLevel(DiagID, 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; } // Update counts for DiagnosticErrorTrap even if a fatal error occurred. if (DiagLevel >= DiagnosticIDs::Error) { ++Diag.TrapNumErrorsOccurred; if (isUnrecoverable(DiagID)) ++Diag.TrapNumUnrecoverableErrorsOccurred; } // 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) { if (isUnrecoverable(DiagID)) Diag.UnrecoverableErrorOccurred = true; // Warnings which have been upgraded to errors do not prevent compilation. if (isDefaultMappingAsError(DiagID)) Diag.UncompilableErrorOccurred = true; Diag.ErrorOccurred = true; if (Diag.Client->IncludeInDiagnosticCounts()) { ++Diag.NumErrors; } // If we've emitted a lot of errors, emit a fatal error instead of 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); return false; } } // Finally, report it. EmitDiag(Diag, DiagLevel); return true; }
/// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { Diagnostic 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; } // Update counts for DiagnosticErrorTrap even if a fatal error occurred. if (DiagLevel >= DiagnosticIDs::Error) { ++Diag.TrapNumErrorsOccurred; if (isUnrecoverable(DiagID)) ++Diag.TrapNumUnrecoverableErrorsOccurred; } // 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) { if (isUnrecoverable(DiagID)) Diag.UnrecoverableErrorOccurred = true; if (Diag.Client->IncludeInDiagnosticCounts()) { Diag.ErrorOccurred = true; ++Diag.NumErrors; } // If we've emitted a lot of errors, emit a fatal error instead of 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); return false; } } // If we have any Fix-Its, make sure that all of the Fix-Its point into // source locations that aren't macro expansions. If any point into macro // expansions, 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((DiagnosticsEngine::Level)DiagLevel, Info); if (Diag.Client->IncludeInDiagnosticCounts()) { if (DiagLevel == DiagnosticIDs::Warning) ++Diag.NumWarnings; } Diag.CurDiagID = ~0U; return true; }