Index: include/clang/Basic/Diagnostic.h =================================================================== --- include/clang/Basic/Diagnostic.h +++ include/clang/Basic/Diagnostic.h @@ -230,7 +230,10 @@ }; /// \brief Keeps and automatically disposes all DiagStates that we create. - std::list DiagStates; + /// + /// The first DiagState represents the state set by the command line. But it + /// also contains a cache for the defaults that is lazily populated. + mutable std::list DiagStates; /// \brief Represents a point in source where the diagnostic state was /// modified because of a pragma. Index: include/clang/Basic/DiagnosticIDs.h =================================================================== --- include/clang/Basic/DiagnosticIDs.h +++ include/clang/Basic/DiagnosticIDs.h @@ -84,6 +84,7 @@ unsigned IsPragma : 1; unsigned HasNoWarningAsError : 1; unsigned HasNoErrorAsFatal : 1; + unsigned MightBeOverriden : 1; public: static DiagnosticMapping Make(diag::Severity Severity, bool IsUser, @@ -94,6 +95,8 @@ Result.IsPragma = IsPragma; Result.HasNoWarningAsError = 0; Result.HasNoErrorAsFatal = 0; + Result.MightBeOverriden = 0; + return Result; } @@ -108,6 +111,11 @@ bool hasNoErrorAsFatal() const { return HasNoErrorAsFatal; } void setNoErrorAsFatal(bool Value) { HasNoErrorAsFatal = Value; } + + /// Only makes sense for the base state: specify if the diagnostic might be + /// changed for other source location + bool mightBeOverriden() const { return MightBeOverriden; } + void setMightBeOverriden(bool Value) { MightBeOverriden = Value; } }; /// \brief Used for handling and querying diagnostic IDs. @@ -261,6 +269,10 @@ getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, const DiagnosticsEngine &Diag) const LLVM_READONLY; + DiagnosticMapping & + getDiagnosticMapping(unsigned DiagID, SourceLocation Loc, + const DiagnosticsEngine &Diag) const LLVM_READONLY; + diag::Severity getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, const DiagnosticsEngine &Diag) const LLVM_READONLY; Index: lib/Basic/Diagnostic.cpp =================================================================== --- lib/Basic/Diagnostic.cpp +++ lib/Basic/Diagnostic.cpp @@ -201,6 +201,11 @@ } DiagnosticMapping Mapping = makeUserMapping(Map, L); + if (Loc.isValid()) { + // We are potentially overriding a default behavior + DiagStates.front().getOrAddMapping(Diag).setMightBeOverriden(true); + } + // Common case; setting all the diagnostics of a group in one place. if (Loc.isInvalid() || Loc == LastStateChangePos) { GetCurDiagState()->setMapping(Diag, Mapping); Index: lib/Basic/DiagnosticIDs.cpp =================================================================== --- lib/Basic/DiagnosticIDs.cpp +++ lib/Basic/DiagnosticIDs.cpp @@ -396,6 +396,23 @@ return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag)); } +DiagnosticMapping & +DiagnosticIDs::getDiagnosticMapping(unsigned DiagID, SourceLocation Loc, + const DiagnosticsEngine &Diag) const { + // Calling GetDiagStatePointForLoc might be costly as it needs to create + // FullSourceLoc and compare them to the ones in the states. So first query + // the base state and check if it might be overridden. + DiagnosticsEngine::DiagState &BaseState = Diag.DiagStates.front(); + assert(&BaseState == Diag.DiagStatePoints.front().State); + DiagnosticMapping &Mapping = BaseState.getOrAddMapping((diag::kind)DiagID); + if (!Mapping.mightBeOverriden()) + return Mapping; + + DiagnosticsEngine::DiagStatePointsTy::iterator Pos = + Diag.GetDiagStatePointForLoc(Loc); + return Pos->State->getOrAddMapping((diag::kind)DiagID); +} + /// \brief Based on the way the client configured the Diagnostic /// object, classify the specified diagnostic ID into a Level, consumable by /// the DiagnosticClient. @@ -406,17 +423,11 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, const DiagnosticsEngine &Diag) const { assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE); - // Specific non-error diagnostics may be mapped to various levels from ignored // to error. Errors can only be mapped to fatal. diag::Severity Result = diag::Severity::Fatal; - DiagnosticsEngine::DiagStatePointsTy::iterator - Pos = Diag.GetDiagStatePointForLoc(Loc); - DiagnosticsEngine::DiagState *State = Pos->State; - - // Get the mapping information, or compute it lazily. - DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID); + DiagnosticMapping &Mapping = getDiagnosticMapping(DiagID, Loc, Diag); // TODO: Can a null severity really get here? if (Mapping.getSeverity() != diag::Severity()) Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -5328,6 +5328,10 @@ diag::Severity Map = (diag::Severity)F.PragmaDiagMappings[Idx++]; DiagnosticMapping Mapping = Diag.makeUserMapping(Map, Loc); Diag.GetCurDiagState()->setMapping(DiagID, Mapping); + + // We are overriding a default behavior + Diag.DiagStates.front().getOrAddMapping(DiagID).setMightBeOverriden( + true); } } }