/// \brief Based on the way the client configured the Diagnostic /// object, classify the specified diagnostic ID into a Level, consumable by /// the DiagnosticClient. /// /// \param Loc The source location we are interested in finding out the /// diagnostic state. Can be null in order to query the latest state. DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, SourceLocation Loc, const DiagnosticsEngine &Diag) const { // Specific non-error diagnostics may be mapped to various levels from ignored // to error. Errors can only be mapped to fatal. DiagnosticIDs::Level Result = DiagnosticIDs::Fatal; DiagnosticsEngine::DiagStatePointsTy::iterator Pos = Diag.GetDiagStatePointForLoc(Loc); DiagnosticsEngine::DiagState *State = Pos->State; // Get the mapping information, or compute it lazily. DiagnosticMappingInfo &MappingInfo = State->getOrAddMappingInfo( (diag::kind)DiagID); switch (MappingInfo.getMapping()) { case diag::MAP_IGNORE: Result = DiagnosticIDs::Ignored; break; case diag::MAP_WARNING: Result = DiagnosticIDs::Warning; break; case diag::MAP_ERROR: Result = DiagnosticIDs::Error; break; case diag::MAP_FATAL: Result = DiagnosticIDs::Fatal; break; } // Upgrade ignored diagnostics if -Weverything is enabled. if (Diag.EnableAllWarnings && Result == DiagnosticIDs::Ignored && !MappingInfo.isUser()) Result = DiagnosticIDs::Warning; // Ignore -pedantic diagnostics inside __extension__ blocks. // (The diagnostics controlled by -pedantic are the extension diagnostics // that are not enabled by default.) bool EnabledByDefault = false; bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault); if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault) return DiagnosticIDs::Ignored; // For extension diagnostics that haven't been explicitly mapped, check if we // should upgrade the diagnostic. if (IsExtensionDiag && !MappingInfo.isUser()) { switch (Diag.ExtBehavior) { case DiagnosticsEngine::Ext_Ignore: break; case DiagnosticsEngine::Ext_Warn: // Upgrade ignored diagnostics to warnings. if (Result == DiagnosticIDs::Ignored) Result = DiagnosticIDs::Warning; break; case DiagnosticsEngine::Ext_Error: // Upgrade ignored or warning diagnostics to errors. if (Result == DiagnosticIDs::Ignored || Result == DiagnosticIDs::Warning) Result = DiagnosticIDs::Error; break; } } // At this point, ignored errors can no longer be upgraded. if (Result == DiagnosticIDs::Ignored) return Result; // Honor -w, which is lower in priority than pedantic-errors, but higher than // -Werror. if (Result == DiagnosticIDs::Warning && Diag.IgnoreAllWarnings) return DiagnosticIDs::Ignored; // If -Werror is enabled, map warnings to errors unless explicitly disabled. if (Result == DiagnosticIDs::Warning) { if (Diag.WarningsAsErrors && !MappingInfo.hasNoWarningAsError()) Result = DiagnosticIDs::Error; } // If -Wfatal-errors is enabled, map errors to fatal unless explicity // disabled. if (Result == DiagnosticIDs::Error) { if (Diag.ErrorsAsFatal && !MappingInfo.hasNoErrorAsFatal()) Result = DiagnosticIDs::Fatal; } // If we are in a system header, we ignore it. We look at the diagnostic class // because we also want to ignore extensions and warnings in -Werror and // -pedantic-errors modes, which *map* warnings/extensions to errors. if (Result >= DiagnosticIDs::Warning && DiagClass != CLASS_ERROR && // Custom diagnostics always are emitted in system headers. DiagID < diag::DIAG_UPPER_LIMIT && !MappingInfo.hasShowInSystemHeader() && Diag.SuppressSystemWarnings && Loc.isValid() && Diag.getSourceManager().isInSystemHeader( Diag.getSourceManager().getExpansionLoc(Loc))) return DiagnosticIDs::Ignored; return Result; }