Refactoring of Diagnostic class.

-Move the stuff of Diagnostic related to creating/querying diagnostic IDs into a new DiagnosticIDs class.
-DiagnosticIDs can be shared among multiple Diagnostics for multiple translation units.
-The rest of the state in Diagnostic object is considered related and tied to one translation unit.
-Have Diagnostic point to the SourceManager that is related with. Diagnostic can now accept just a
   SourceLocation instead of a FullSourceLoc.
-Reflect the changes to various interfaces.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119730 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index b4edc5f..7b16809 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -137,9 +137,6 @@
     /// \brief AST contexts for which we are checking structural equivalence.
     ASTContext &C1, &C2;
     
-    /// \brief Diagnostic object used to emit diagnostics.
-    Diagnostic &Diags;
-    
     /// \brief The set of "tentative" equivalences between two canonical 
     /// declarations, mapping from a declaration in the first context to the
     /// declaration in the second context that we believe to be equivalent.
@@ -158,10 +155,9 @@
     bool StrictTypeSpelling;
     
     StructuralEquivalenceContext(ASTContext &C1, ASTContext &C2,
-                                 Diagnostic &Diags,
                llvm::DenseSet<std::pair<Decl *, Decl *> > &NonEquivalentDecls,
                                  bool StrictTypeSpelling = false)
-      : C1(C1), C2(C2), Diags(Diags), NonEquivalentDecls(NonEquivalentDecls),
+      : C1(C1), C2(C2), NonEquivalentDecls(NonEquivalentDecls),
         StrictTypeSpelling(StrictTypeSpelling) { }
 
     /// \brief Determine whether the two declarations are structurally
@@ -179,11 +175,11 @@
     
   public:
     DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID) {
-      return Diags.Report(FullSourceLoc(Loc, C1.getSourceManager()), DiagID);
+      return C1.getDiagnostics().Report(Loc, DiagID);
     }
 
     DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID) {
-      return Diags.Report(FullSourceLoc(Loc, C2.getSourceManager()), DiagID);
+      return C2.getDiagnostics().Report(Loc, DiagID);
     }
   };
 }
@@ -1432,7 +1428,6 @@
                                         RecordDecl *ToRecord) {
   StructuralEquivalenceContext Ctx(Importer.getFromContext(),
                                    Importer.getToContext(),
-                                   Importer.getDiags(),
                                    Importer.getNonEquivalentDecls());
   return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord);
 }
@@ -1440,7 +1435,6 @@
 bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) {
   StructuralEquivalenceContext Ctx(Importer.getFromContext(),
                                    Importer.getToContext(),
-                                   Importer.getDiags(),
                                    Importer.getNonEquivalentDecls());
   return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum);
 }
@@ -2983,15 +2977,13 @@
                                 Importer.Import(E->getRParenLoc()));
 }
 
-ASTImporter::ASTImporter(Diagnostic &Diags,
-                         ASTContext &ToContext, FileManager &ToFileManager,
+ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
                          const FileSystemOptions &ToFileSystemOpts,
                          ASTContext &FromContext, FileManager &FromFileManager,
                          const FileSystemOptions &FromFileSystemOpts)
   : ToContext(ToContext), FromContext(FromContext),
     ToFileManager(ToFileManager), FromFileManager(FromFileManager),
-    ToFileSystemOpts(ToFileSystemOpts), FromFileSystemOpts(FromFileSystemOpts),
-    Diags(Diags) {
+    ToFileSystemOpts(ToFileSystemOpts), FromFileSystemOpts(FromFileSystemOpts) {
   ImportedDecls[FromContext.getTranslationUnitDecl()]
     = ToContext.getTranslationUnitDecl();
 }
@@ -3167,7 +3159,8 @@
                              FromSLoc.getFile().getFileCharacteristic());
   } else {
     // FIXME: We want to re-use the existing MemoryBuffer!
-    const llvm::MemoryBuffer *FromBuf = Cache->getBuffer(getDiags(), FromSM);
+    const llvm::MemoryBuffer *
+        FromBuf = Cache->getBuffer(FromContext.getDiagnostics(), FromSM);
     llvm::MemoryBuffer *ToBuf
       = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(),
                                              FromBuf->getBufferIdentifier());
@@ -3263,13 +3256,11 @@
 }
 
 DiagnosticBuilder ASTImporter::ToDiag(SourceLocation Loc, unsigned DiagID) {
-  return Diags.Report(FullSourceLoc(Loc, ToContext.getSourceManager()), 
-                      DiagID);
+  return ToContext.getDiagnostics().Report(Loc, DiagID);
 }
 
 DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) {
-  return Diags.Report(FullSourceLoc(Loc, FromContext.getSourceManager()), 
-                      DiagID);
+  return FromContext.getDiagnostics().Report(Loc, DiagID);
 }
 
 Decl *ASTImporter::Imported(Decl *From, Decl *To) {
@@ -3283,7 +3274,6 @@
   if (Pos != ImportedTypes.end() && ToContext.hasSameType(Import(From), To))
     return true;
       
-  StructuralEquivalenceContext Ctx(FromContext, ToContext, Diags, 
-                                   NonEquivalentDecls);
+  StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls);
   return Ctx.IsStructurallyEquivalent(From, To);
 }
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 0fe180d..34df1d9 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -1633,8 +1633,7 @@
 
 DiagnosticBuilder
 RecordLayoutBuilder::Diag(SourceLocation Loc, unsigned DiagID) {
-  return Context.getDiagnostics().Report(
-                        FullSourceLoc(Loc, Context.getSourceManager()), DiagID);
+  return Context.getDiagnostics().Report(Loc, DiagID);
 }
 
 namespace {
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index cbc340e..a26f497 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -11,227 +11,13 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/AST/ASTDiagnostic.h"
-#include "clang/Analysis/AnalysisDiagnostic.h"
 #include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/FileManager.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/PartialDiagnostic.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Lex/LexDiagnostic.h"
-#include "clang/Parse/ParseDiagnostic.h"
-#include "clang/Sema/SemaDiagnostic.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
-
-#include <vector>
-#include <map>
-#include <cstring>
 using namespace clang;
 
-//===----------------------------------------------------------------------===//
-// Builtin Diagnostic information
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-// Diagnostic classes.
-enum {
-  CLASS_NOTE       = 0x01,
-  CLASS_WARNING    = 0x02,
-  CLASS_EXTENSION  = 0x03,
-  CLASS_ERROR      = 0x04
-};
-
-struct StaticDiagInfoRec {
-  unsigned short DiagID;
-  unsigned Mapping : 3;
-  unsigned Class : 3;
-  bool SFINAE : 1;
-  unsigned Category : 5;
-  
-  const char *Description;
-  const char *OptionGroup;
-
-  bool operator<(const StaticDiagInfoRec &RHS) const {
-    return DiagID < RHS.DiagID;
-  }
-};
-
-}
-
-static const StaticDiagInfoRec StaticDiagInfo[] = {
-#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE, CATEGORY)    \
-  { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, CATEGORY, DESC, GROUP },
-#include "clang/Basic/DiagnosticCommonKinds.inc"
-#include "clang/Basic/DiagnosticDriverKinds.inc"
-#include "clang/Basic/DiagnosticFrontendKinds.inc"
-#include "clang/Basic/DiagnosticLexKinds.inc"
-#include "clang/Basic/DiagnosticParseKinds.inc"
-#include "clang/Basic/DiagnosticASTKinds.inc"
-#include "clang/Basic/DiagnosticSemaKinds.inc"
-#include "clang/Basic/DiagnosticAnalysisKinds.inc"
-  { 0, 0, 0, 0, 0, 0, 0}
-};
-#undef DIAG
-
-/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
-/// or null if the ID is invalid.
-static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
-  unsigned NumDiagEntries = sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
-
-  // If assertions are enabled, verify that the StaticDiagInfo array is sorted.
-#ifndef NDEBUG
-  static bool IsFirst = true;
-  if (IsFirst) {
-    for (unsigned i = 1; i != NumDiagEntries; ++i) {
-      assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
-             "Diag ID conflict, the enums at the start of clang::diag (in "
-             "Diagnostic.h) probably need to be increased");
-
-      assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
-             "Improperly sorted diag info");
-    }
-    IsFirst = false;
-  }
-#endif
-
-  // Search the diagnostic table with a binary search.
-  StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0, 0 };
-
-  const StaticDiagInfoRec *Found =
-    std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find);
-  if (Found == StaticDiagInfo + NumDiagEntries ||
-      Found->DiagID != DiagID)
-    return 0;
-
-  return Found;
-}
-
-static unsigned GetDefaultDiagMapping(unsigned DiagID) {
-  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
-    return Info->Mapping;
-  return diag::MAP_FATAL;
-}
-
-/// getWarningOptionForDiag - Return the lowest-level warning option that
-/// enables the specified diagnostic.  If there is no -Wfoo flag that controls
-/// the diagnostic, this returns null.
-const char *Diagnostic::getWarningOptionForDiag(unsigned DiagID) {
-  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
-    return Info->OptionGroup;
-  return 0;
-}
-
-/// getWarningOptionForDiag - Return the category number that a specified
-/// DiagID belongs to, or 0 if no category.
-unsigned Diagnostic::getCategoryNumberForDiag(unsigned DiagID) {
-  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
-    return Info->Category;
-  return 0;
-}
-
-/// getCategoryNameFromID - Given a category ID, return the name of the
-/// category, an empty string if CategoryID is zero, or null if CategoryID is
-/// invalid.
-const char *Diagnostic::getCategoryNameFromID(unsigned CategoryID) {
-  // Second the table of options, sorted by name for fast binary lookup.
-  static const char *CategoryNameTable[] = {
-#define GET_CATEGORY_TABLE
-#define CATEGORY(X) X,
-#include "clang/Basic/DiagnosticGroups.inc"
-#undef GET_CATEGORY_TABLE
-    "<<END>>"
-  };
-  static const size_t CategoryNameTableSize =
-    sizeof(CategoryNameTable) / sizeof(CategoryNameTable[0])-1;
-  
-  if (CategoryID >= CategoryNameTableSize) return 0;
-  return CategoryNameTable[CategoryID];
-}
-
-
-
-Diagnostic::SFINAEResponse 
-Diagnostic::getDiagnosticSFINAEResponse(unsigned DiagID) {
-  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) {
-    if (!Info->SFINAE)
-      return SFINAE_Report;
-
-    if (Info->Class == CLASS_ERROR)
-      return SFINAE_SubstitutionFailure;
-    
-    // Suppress notes, warnings, and extensions;
-    return SFINAE_Suppress;
-  }
-  
-  return SFINAE_Report;
-}
-
-/// getDiagClass - Return the class field of the diagnostic.
-///
-static unsigned getBuiltinDiagClass(unsigned DiagID) {
-  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
-    return Info->Class;
-  return ~0U;
-}
-
-//===----------------------------------------------------------------------===//
-// Custom Diagnostic information
-//===----------------------------------------------------------------------===//
-
-namespace clang {
-  namespace diag {
-    class CustomDiagInfo {
-      typedef std::pair<Diagnostic::Level, std::string> DiagDesc;
-      std::vector<DiagDesc> DiagInfo;
-      std::map<DiagDesc, unsigned> DiagIDs;
-    public:
-
-      /// getDescription - Return the description of the specified custom
-      /// diagnostic.
-      const char *getDescription(unsigned DiagID) const {
-        assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
-               "Invalid diagnosic ID");
-        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second.c_str();
-      }
-
-      /// getLevel - Return the level of the specified custom diagnostic.
-      Diagnostic::Level getLevel(unsigned DiagID) const {
-        assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
-               "Invalid diagnosic ID");
-        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
-      }
-
-      unsigned getOrCreateDiagID(Diagnostic::Level L, llvm::StringRef Message,
-                                 Diagnostic &Diags) {
-        DiagDesc D(L, Message);
-        // Check to see if it already exists.
-        std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
-        if (I != DiagIDs.end() && I->first == D)
-          return I->second;
-
-        // If not, assign a new ID.
-        unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
-        DiagIDs.insert(std::make_pair(D, ID));
-        DiagInfo.push_back(D);
-        return ID;
-      }
-    };
-
-  } // end diag namespace
-} // end clang namespace
-
-
-//===----------------------------------------------------------------------===//
-// Common Diagnostic implementation
-//===----------------------------------------------------------------------===//
-
 static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT,
                                const char *Modifier, unsigned ML,
                                const char *Argument, unsigned ArgLen,
@@ -244,7 +30,10 @@
 }
 
 
-Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
+Diagnostic::Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &diags,
+                       DiagnosticClient *client, bool ShouldOwnClient)
+  : Diags(diags), Client(client), OwnsDiagClient(ShouldOwnClient),
+    SourceMgr(0) {
   ArgToStringFn = DummyArgToStringFn;
   ArgToStringCookie = 0;
 
@@ -259,7 +48,6 @@
 
   ErrorLimit = 0;
   TemplateBacktraceLimit = 0;
-  CustomDiagInfo = 0;
 
   // Set all mappings to 'unset'.
   DiagMappingsStack.clear();
@@ -269,7 +57,8 @@
 }
 
 Diagnostic::~Diagnostic() {
-  delete CustomDiagInfo;
+  if (OwnsDiagClient)
+    delete Client;
 }
 
 
@@ -287,47 +76,6 @@
   return true;
 }
 
-/// getCustomDiagID - Return an ID for a diagnostic with the specified message
-/// and level.  If this is the first request for this diagnosic, it is
-/// registered and created, otherwise the existing ID is returned.
-unsigned Diagnostic::getCustomDiagID(Level L, llvm::StringRef Message) {
-  if (CustomDiagInfo == 0)
-    CustomDiagInfo = new diag::CustomDiagInfo();
-  return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
-}
-
-
-/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
-/// level of the specified diagnostic ID is a Warning or Extension.
-/// This only works on builtin diagnostics, not custom ones, and is not legal to
-/// call on NOTEs.
-bool Diagnostic::isBuiltinWarningOrExtension(unsigned DiagID) {
-  return DiagID < diag::DIAG_UPPER_LIMIT &&
-         getBuiltinDiagClass(DiagID) != CLASS_ERROR;
-}
-
-/// \brief Determine whether the given built-in diagnostic ID is a
-/// Note.
-bool Diagnostic::isBuiltinNote(unsigned DiagID) {
-  return DiagID < diag::DIAG_UPPER_LIMIT &&
-    getBuiltinDiagClass(DiagID) == CLASS_NOTE;
-}
-
-/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
-/// ID is for an extension of some sort.  This also returns EnabledByDefault,
-/// which is set to indicate whether the diagnostic is ignored by default (in
-/// which case -pedantic enables it) or treated as a warning/error by default.
-///
-bool Diagnostic::isBuiltinExtensionDiag(unsigned DiagID,
-                                        bool &EnabledByDefault) {
-  if (DiagID >= diag::DIAG_UPPER_LIMIT ||
-      getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
-    return false;
-  
-  EnabledByDefault = GetDefaultDiagMapping(DiagID) != diag::MAP_IGNORE;
-  return true;
-}
-
 void Diagnostic::Reset() {
   ErrorOccurred = false;
   FatalErrorOccurred = false;
@@ -336,18 +84,14 @@
   NumErrors = 0;
   NumErrorsSuppressed = 0;
   CurDiagID = ~0U;
-  LastDiagLevel = Ignored;
+  // Set LastDiagLevel to an "unset" state. If we set it to 'Ignored', notes
+  // using a Diagnostic associated to a translation unit that follow
+  // diagnostics from a Diagnostic associated to anoter t.u. will not be
+  // displayed.
+  LastDiagLevel = (DiagnosticIDs::Level)-1;
   DelayedDiagID = 0;
 }
 
-/// getDescription - Given a diagnostic ID, return a description of the
-/// issue.
-const char *Diagnostic::getDescription(unsigned DiagID) const {
-  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
-    return Info->Description;
-  return CustomDiagInfo->getDescription(DiagID);
-}
-
 void Diagnostic::SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1,
                                       llvm::StringRef Arg2) {
   if (DelayedDiagID)
@@ -365,266 +109,6 @@
   DelayedDiagArg2.clear();
 }
 
-/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
-/// object, classify the specified diagnostic ID into a Level, consumable by
-/// the DiagnosticClient.
-Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
-  // Handle custom diagnostics, which cannot be mapped.
-  if (DiagID >= diag::DIAG_UPPER_LIMIT)
-    return CustomDiagInfo->getLevel(DiagID);
-
-  unsigned DiagClass = getBuiltinDiagClass(DiagID);
-  assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
-  return getDiagnosticLevel(DiagID, DiagClass);
-}
-
-/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
-/// object, classify the specified diagnostic ID into a Level, consumable by
-/// the DiagnosticClient.
-Diagnostic::Level
-Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const {
-  // Specific non-error diagnostics may be mapped to various levels from ignored
-  // to error.  Errors can only be mapped to fatal.
-  Diagnostic::Level Result = Diagnostic::Fatal;
-
-  // Get the mapping information, if unset, compute it lazily.
-  unsigned MappingInfo = getDiagnosticMappingInfo((diag::kind)DiagID);
-  if (MappingInfo == 0) {
-    MappingInfo = GetDefaultDiagMapping(DiagID);
-    setDiagnosticMappingInternal(DiagID, MappingInfo, false);
-  }
-
-  switch (MappingInfo & 7) {
-  default: assert(0 && "Unknown mapping!");
-  case diag::MAP_IGNORE:
-    // Ignore this, unless this is an extension diagnostic and we're mapping
-    // them onto warnings or errors.
-    if (!isBuiltinExtensionDiag(DiagID) ||  // Not an extension
-        ExtBehavior == Ext_Ignore ||        // Extensions ignored anyway
-        (MappingInfo & 8) != 0)             // User explicitly mapped it.
-      return Diagnostic::Ignored;
-    Result = Diagnostic::Warning;
-    if (ExtBehavior == Ext_Error) Result = Diagnostic::Error;
-    if (Result == Diagnostic::Error && ErrorsAsFatal)
-      Result = Diagnostic::Fatal;
-    break;
-  case diag::MAP_ERROR:
-    Result = Diagnostic::Error;
-    if (ErrorsAsFatal)
-      Result = Diagnostic::Fatal;
-    break;
-  case diag::MAP_FATAL:
-    Result = Diagnostic::Fatal;
-    break;
-  case diag::MAP_WARNING:
-    // If warnings are globally mapped to ignore or error, do it.
-    if (IgnoreAllWarnings)
-      return Diagnostic::Ignored;
-
-    Result = Diagnostic::Warning;
-
-    // If this is an extension diagnostic and we're in -pedantic-error mode, and
-    // if the user didn't explicitly map it, upgrade to an error.
-    if (ExtBehavior == Ext_Error &&
-        (MappingInfo & 8) == 0 &&
-        isBuiltinExtensionDiag(DiagID))
-      Result = Diagnostic::Error;
-
-    if (WarningsAsErrors)
-      Result = Diagnostic::Error;
-    if (Result == Diagnostic::Error && ErrorsAsFatal)
-      Result = Diagnostic::Fatal;
-    break;
-
-  case diag::MAP_WARNING_NO_WERROR:
-    // Diagnostics specified with -Wno-error=foo should be set to warnings, but
-    // not be adjusted by -Werror or -pedantic-errors.
-    Result = Diagnostic::Warning;
-
-    // If warnings are globally mapped to ignore or error, do it.
-    if (IgnoreAllWarnings)
-      return Diagnostic::Ignored;
-
-    break;
-
-  case diag::MAP_ERROR_NO_WFATAL:
-    // Diagnostics specified as -Wno-fatal-error=foo should be errors, but
-    // unaffected by -Wfatal-errors.
-    Result = Diagnostic::Error;
-    break;
-  }
-
-  // Okay, we're about to return this as a "diagnostic to emit" one last check:
-  // if this is any sort of extension warning, and if we're in an __extension__
-  // block, silence it.
-  if (AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
-    return Diagnostic::Ignored;
-
-  return Result;
-}
-
-struct WarningOption {
-  const char  *Name;
-  const short *Members;
-  const short *SubGroups;
-};
-
-#define GET_DIAG_ARRAYS
-#include "clang/Basic/DiagnosticGroups.inc"
-#undef GET_DIAG_ARRAYS
-
-// Second the table of options, sorted by name for fast binary lookup.
-static const WarningOption OptionTable[] = {
-#define GET_DIAG_TABLE
-#include "clang/Basic/DiagnosticGroups.inc"
-#undef GET_DIAG_TABLE
-};
-static const size_t OptionTableSize =
-sizeof(OptionTable) / sizeof(OptionTable[0]);
-
-static bool WarningOptionCompare(const WarningOption &LHS,
-                                 const WarningOption &RHS) {
-  return strcmp(LHS.Name, RHS.Name) < 0;
-}
-
-static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
-                            Diagnostic &Diags) {
-  // Option exists, poke all the members of its diagnostic set.
-  if (const short *Member = Group->Members) {
-    for (; *Member != -1; ++Member)
-      Diags.setDiagnosticMapping(*Member, Mapping);
-  }
-
-  // Enable/disable all subgroups along with this one.
-  if (const short *SubGroups = Group->SubGroups) {
-    for (; *SubGroups != (short)-1; ++SubGroups)
-      MapGroupMembers(&OptionTable[(short)*SubGroups], Mapping, Diags);
-  }
-}
-
-/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
-/// "unknown-pragmas" to have the specified mapping.  This returns true and
-/// ignores the request if "Group" was unknown, false otherwise.
-bool Diagnostic::setDiagnosticGroupMapping(const char *Group,
-                                           diag::Mapping Map) {
-
-  WarningOption Key = { Group, 0, 0 };
-  const WarningOption *Found =
-  std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
-                   WarningOptionCompare);
-  if (Found == OptionTable + OptionTableSize ||
-      strcmp(Found->Name, Group) != 0)
-    return true;  // Option not found.
-
-  MapGroupMembers(Found, Map, *this);
-  return false;
-}
-
-
-/// ProcessDiag - This is the method used to report a diagnostic that is
-/// finally fully formed.
-bool Diagnostic::ProcessDiag() {
-  DiagnosticInfo Info(this);
-
-  if (SuppressAllDiagnostics)
-    return false;
-  
-  // Figure out the diagnostic level of this message.
-  Diagnostic::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 = Diagnostic::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);
-    }
-  }
-
-  if (DiagLevel != Diagnostic::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 (LastDiagLevel == Diagnostic::Fatal)
-      FatalErrorOccurred = true;
-
-    LastDiagLevel = DiagLevel;
-  }
-
-  // If a fatal error has already been emitted, silence all subsequent
-  // diagnostics.
-  if (FatalErrorOccurred) {
-    if (DiagLevel >= Diagnostic::Error && Client->IncludeInDiagnosticCounts()) {
-      ++NumErrors;
-      ++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 == Diagnostic::Ignored ||
-      (DiagLevel == Diagnostic::Note && LastDiagLevel == Diagnostic::Ignored))
-    return false;
-
-  // If this diagnostic is in a system header and is not a clang error, suppress
-  // it.
-  if (SuppressSystemWarnings && !ShouldEmitInSystemHeader &&
-      Info.getLocation().isValid() &&
-      Info.getLocation().getInstantiationLoc().isInSystemHeader() &&
-      (DiagLevel != Diagnostic::Note || LastDiagLevel == Diagnostic::Ignored)) {
-    LastDiagLevel = Diagnostic::Ignored;
-    return false;
-  }
-
-  if (DiagLevel >= Diagnostic::Error) {
-    if (Client->IncludeInDiagnosticCounts()) {
-      ErrorOccurred = true;
-      ++NumErrors;
-    }
-
-    // If we've emitted a lot of errors, emit a fatal error after it to stop a
-    // flood of bogus errors.
-    if (ErrorLimit && NumErrors >= ErrorLimit &&
-        DiagLevel == Diagnostic::Error)
-      SetDelayedDiagnostic(diag::fatal_too_many_errors);
-  }
-
-  // Finally, report it.
-  Client->HandleDiagnostic(DiagLevel, Info);
-  if (Client->IncludeInDiagnosticCounts()) {
-    if (DiagLevel == Diagnostic::Warning)
-      ++NumWarnings;
-  }
-
-  CurDiagID = ~0U;
-
-  return true;
-}
-
 void DiagnosticBuilder::FlushCounts() {
   DiagObj->NumDiagArgs = NumArgs;
   DiagObj->NumDiagRanges = NumRanges;
@@ -889,7 +373,7 @@
 /// array.
 void DiagnosticInfo::
 FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
-  const char *DiagStr = getDiags()->getDescription(getID());
+  const char *DiagStr = getDiags()->getDiagnosticIDs()->getDescription(getID());
   const char *DiagEnd = DiagStr+strlen(DiagStr);
 
   FormatDiagnostic(DiagStr, DiagEnd, OutStr);
@@ -1059,7 +543,11 @@
 
 StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level, 
                                    const DiagnosticInfo &Info)
-  : Level(Level), Loc(Info.getLocation()) {
+  : Level(Level) {
+  assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) &&
+       "Valid source location without setting a source manager for diagnostic");
+  if (Info.getLocation().isValid())
+    Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
   llvm::SmallString<64> Message;
   Info.FormatDiagnostic(Message);
   this->Message.assign(Message.begin(), Message.end());
diff --git a/lib/Basic/DiagnosticIDs.cpp b/lib/Basic/DiagnosticIDs.cpp
new file mode 100644
index 0000000..5d5bf7b
--- /dev/null
+++ b/lib/Basic/DiagnosticIDs.cpp
@@ -0,0 +1,547 @@
+//===--- DiagnosticIDs.cpp - Diagnostic IDs Handling ----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the Diagnostic IDs-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/Analysis/AnalysisDiagnostic.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Sema/SemaDiagnostic.h"
+
+#include <map>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Builtin Diagnostic information
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+// Diagnostic classes.
+enum {
+  CLASS_NOTE       = 0x01,
+  CLASS_WARNING    = 0x02,
+  CLASS_EXTENSION  = 0x03,
+  CLASS_ERROR      = 0x04
+};
+
+struct StaticDiagInfoRec {
+  unsigned short DiagID;
+  unsigned Mapping : 3;
+  unsigned Class : 3;
+  bool SFINAE : 1;
+  unsigned Category : 5;
+  
+  const char *Description;
+  const char *OptionGroup;
+
+  bool operator<(const StaticDiagInfoRec &RHS) const {
+    return DiagID < RHS.DiagID;
+  }
+};
+
+}
+
+static const StaticDiagInfoRec StaticDiagInfo[] = {
+#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE, CATEGORY)    \
+  { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, CATEGORY, DESC, GROUP },
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+  { 0, 0, 0, 0, 0, 0, 0}
+};
+#undef DIAG
+
+/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
+/// or null if the ID is invalid.
+static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
+  unsigned NumDiagEntries = sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
+
+  // If assertions are enabled, verify that the StaticDiagInfo array is sorted.
+#ifndef NDEBUG
+  static bool IsFirst = true;
+  if (IsFirst) {
+    for (unsigned i = 1; i != NumDiagEntries; ++i) {
+      assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
+             "Diag ID conflict, the enums at the start of clang::diag (in "
+             "Diagnostic.h) probably need to be increased");
+
+      assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
+             "Improperly sorted diag info");
+    }
+    IsFirst = false;
+  }
+#endif
+
+  // Search the diagnostic table with a binary search.
+  StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0, 0 };
+
+  const StaticDiagInfoRec *Found =
+    std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find);
+  if (Found == StaticDiagInfo + NumDiagEntries ||
+      Found->DiagID != DiagID)
+    return 0;
+
+  return Found;
+}
+
+static unsigned GetDefaultDiagMapping(unsigned DiagID) {
+  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+    return Info->Mapping;
+  return diag::MAP_FATAL;
+}
+
+/// getWarningOptionForDiag - Return the lowest-level warning option that
+/// enables the specified diagnostic.  If there is no -Wfoo flag that controls
+/// the diagnostic, this returns null.
+const char *DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
+  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+    return Info->OptionGroup;
+  return 0;
+}
+
+/// getWarningOptionForDiag - Return the category number that a specified
+/// DiagID belongs to, or 0 if no category.
+unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
+  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+    return Info->Category;
+  return 0;
+}
+
+/// getCategoryNameFromID - Given a category ID, return the name of the
+/// category, an empty string if CategoryID is zero, or null if CategoryID is
+/// invalid.
+const char *DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
+  // Second the table of options, sorted by name for fast binary lookup.
+  static const char *CategoryNameTable[] = {
+#define GET_CATEGORY_TABLE
+#define CATEGORY(X) X,
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef GET_CATEGORY_TABLE
+    "<<END>>"
+  };
+  static const size_t CategoryNameTableSize =
+    sizeof(CategoryNameTable) / sizeof(CategoryNameTable[0])-1;
+  
+  if (CategoryID >= CategoryNameTableSize) return 0;
+  return CategoryNameTable[CategoryID];
+}
+
+
+
+DiagnosticIDs::SFINAEResponse 
+DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
+  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) {
+    if (!Info->SFINAE)
+      return SFINAE_Report;
+
+    if (Info->Class == CLASS_ERROR)
+      return SFINAE_SubstitutionFailure;
+    
+    // Suppress notes, warnings, and extensions;
+    return SFINAE_Suppress;
+  }
+  
+  return SFINAE_Report;
+}
+
+/// getDiagClass - Return the class field of the diagnostic.
+///
+static unsigned getBuiltinDiagClass(unsigned DiagID) {
+  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+    return Info->Class;
+  return ~0U;
+}
+
+//===----------------------------------------------------------------------===//
+// Custom Diagnostic information
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+  namespace diag {
+    class CustomDiagInfo {
+      typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
+      std::vector<DiagDesc> DiagInfo;
+      std::map<DiagDesc, unsigned> DiagIDs;
+    public:
+
+      /// getDescription - Return the description of the specified custom
+      /// diagnostic.
+      const char *getDescription(unsigned DiagID) const {
+        assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
+               "Invalid diagnosic ID");
+        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second.c_str();
+      }
+
+      /// getLevel - Return the level of the specified custom diagnostic.
+      DiagnosticIDs::Level getLevel(unsigned DiagID) const {
+        assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
+               "Invalid diagnosic ID");
+        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
+      }
+
+      unsigned getOrCreateDiagID(DiagnosticIDs::Level L, llvm::StringRef Message,
+                                 DiagnosticIDs &Diags) {
+        DiagDesc D(L, Message);
+        // Check to see if it already exists.
+        std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
+        if (I != DiagIDs.end() && I->first == D)
+          return I->second;
+
+        // If not, assign a new ID.
+        unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
+        DiagIDs.insert(std::make_pair(D, ID));
+        DiagInfo.push_back(D);
+        return ID;
+      }
+    };
+
+  } // end diag namespace
+} // end clang namespace
+
+
+//===----------------------------------------------------------------------===//
+// Common Diagnostic implementation
+//===----------------------------------------------------------------------===//
+
+DiagnosticIDs::DiagnosticIDs() {
+  CustomDiagInfo = 0;
+}
+
+DiagnosticIDs::~DiagnosticIDs() {
+  delete CustomDiagInfo;
+}
+
+/// getCustomDiagID - Return an ID for a diagnostic with the specified message
+/// and level.  If this is the first request for this diagnosic, it is
+/// registered and created, otherwise the existing ID is returned.
+unsigned DiagnosticIDs::getCustomDiagID(Level L, llvm::StringRef Message) {
+  if (CustomDiagInfo == 0)
+    CustomDiagInfo = new diag::CustomDiagInfo();
+  return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
+}
+
+
+/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
+/// level of the specified diagnostic ID is a Warning or Extension.
+/// This only works on builtin diagnostics, not custom ones, and is not legal to
+/// call on NOTEs.
+bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
+  return DiagID < diag::DIAG_UPPER_LIMIT &&
+         getBuiltinDiagClass(DiagID) != CLASS_ERROR;
+}
+
+/// \brief Determine whether the given built-in diagnostic ID is a
+/// Note.
+bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
+  return DiagID < diag::DIAG_UPPER_LIMIT &&
+    getBuiltinDiagClass(DiagID) == CLASS_NOTE;
+}
+
+/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
+/// ID is for an extension of some sort.  This also returns EnabledByDefault,
+/// which is set to indicate whether the diagnostic is ignored by default (in
+/// which case -pedantic enables it) or treated as a warning/error by default.
+///
+bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
+                                        bool &EnabledByDefault) {
+  if (DiagID >= diag::DIAG_UPPER_LIMIT ||
+      getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
+    return false;
+  
+  EnabledByDefault = GetDefaultDiagMapping(DiagID) != diag::MAP_IGNORE;
+  return true;
+}
+
+/// getDescription - Given a diagnostic ID, return a description of the
+/// issue.
+const char *DiagnosticIDs::getDescription(unsigned DiagID) const {
+  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+    return Info->Description;
+  return CustomDiagInfo->getDescription(DiagID);
+}
+
+/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
+/// object, classify the specified diagnostic ID into a Level, consumable by
+/// the DiagnosticClient.
+DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID,
+                                        const Diagnostic &Diag) const {
+  // Handle custom diagnostics, which cannot be mapped.
+  if (DiagID >= diag::DIAG_UPPER_LIMIT)
+    return CustomDiagInfo->getLevel(DiagID);
+
+  unsigned DiagClass = getBuiltinDiagClass(DiagID);
+  assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
+  return getDiagnosticLevel(DiagID, DiagClass, Diag);
+}
+
+/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
+/// object, classify the specified diagnostic ID into a Level, consumable by
+/// the DiagnosticClient.
+DiagnosticIDs::Level
+DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
+                               const Diagnostic &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;
+
+  // Get the mapping information, if unset, compute it lazily.
+  unsigned MappingInfo = Diag.getDiagnosticMappingInfo((diag::kind)DiagID);
+  if (MappingInfo == 0) {
+    MappingInfo = GetDefaultDiagMapping(DiagID);
+    Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, false);
+  }
+
+  switch (MappingInfo & 7) {
+  default: assert(0 && "Unknown mapping!");
+  case diag::MAP_IGNORE:
+    // Ignore this, unless this is an extension diagnostic and we're mapping
+    // them onto warnings or errors.
+    if (!isBuiltinExtensionDiag(DiagID) ||  // Not an extension
+        Diag.ExtBehavior == Diagnostic::Ext_Ignore || // Ext ignored
+        (MappingInfo & 8) != 0)             // User explicitly mapped it.
+      return DiagnosticIDs::Ignored;
+    Result = DiagnosticIDs::Warning;
+    if (Diag.ExtBehavior == Diagnostic::Ext_Error) Result = DiagnosticIDs::Error;
+    if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal)
+      Result = DiagnosticIDs::Fatal;
+    break;
+  case diag::MAP_ERROR:
+    Result = DiagnosticIDs::Error;
+    if (Diag.ErrorsAsFatal)
+      Result = DiagnosticIDs::Fatal;
+    break;
+  case diag::MAP_FATAL:
+    Result = DiagnosticIDs::Fatal;
+    break;
+  case diag::MAP_WARNING:
+    // If warnings are globally mapped to ignore or error, do it.
+    if (Diag.IgnoreAllWarnings)
+      return DiagnosticIDs::Ignored;
+
+    Result = DiagnosticIDs::Warning;
+
+    // If this is an extension diagnostic and we're in -pedantic-error mode, and
+    // if the user didn't explicitly map it, upgrade to an error.
+    if (Diag.ExtBehavior == Diagnostic::Ext_Error &&
+        (MappingInfo & 8) == 0 &&
+        isBuiltinExtensionDiag(DiagID))
+      Result = DiagnosticIDs::Error;
+
+    if (Diag.WarningsAsErrors)
+      Result = DiagnosticIDs::Error;
+    if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal)
+      Result = DiagnosticIDs::Fatal;
+    break;
+
+  case diag::MAP_WARNING_NO_WERROR:
+    // Diagnostics specified with -Wno-error=foo should be set to warnings, but
+    // not be adjusted by -Werror or -pedantic-errors.
+    Result = DiagnosticIDs::Warning;
+
+    // If warnings are globally mapped to ignore or error, do it.
+    if (Diag.IgnoreAllWarnings)
+      return DiagnosticIDs::Ignored;
+
+    break;
+
+  case diag::MAP_ERROR_NO_WFATAL:
+    // Diagnostics specified as -Wno-fatal-error=foo should be errors, but
+    // unaffected by -Wfatal-errors.
+    Result = DiagnosticIDs::Error;
+    break;
+  }
+
+  // Okay, we're about to return this as a "diagnostic to emit" one last check:
+  // if this is any sort of extension warning, and if we're in an __extension__
+  // block, silence it.
+  if (Diag.AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
+    return DiagnosticIDs::Ignored;
+
+  return Result;
+}
+
+struct WarningOption {
+  const char  *Name;
+  const short *Members;
+  const short *SubGroups;
+};
+
+#define GET_DIAG_ARRAYS
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef GET_DIAG_ARRAYS
+
+// Second the table of options, sorted by name for fast binary lookup.
+static const WarningOption OptionTable[] = {
+#define GET_DIAG_TABLE
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef GET_DIAG_TABLE
+};
+static const size_t OptionTableSize =
+sizeof(OptionTable) / sizeof(OptionTable[0]);
+
+static bool WarningOptionCompare(const WarningOption &LHS,
+                                 const WarningOption &RHS) {
+  return strcmp(LHS.Name, RHS.Name) < 0;
+}
+
+static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
+                            Diagnostic &Diag) {
+  // Option exists, poke all the members of its diagnostic set.
+  if (const short *Member = Group->Members) {
+    for (; *Member != -1; ++Member)
+      Diag.setDiagnosticMapping(*Member, Mapping);
+  }
+
+  // Enable/disable all subgroups along with this one.
+  if (const short *SubGroups = Group->SubGroups) {
+    for (; *SubGroups != (short)-1; ++SubGroups)
+      MapGroupMembers(&OptionTable[(short)*SubGroups], Mapping, Diag);
+  }
+}
+
+/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
+/// "unknown-pragmas" to have the specified mapping.  This returns true and
+/// ignores the request if "Group" was unknown, false otherwise.
+bool DiagnosticIDs::setDiagnosticGroupMapping(const char *Group,
+                                           diag::Mapping Map,
+                                           Diagnostic &Diag) const {
+  WarningOption Key = { Group, 0, 0 };
+  const WarningOption *Found =
+  std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
+                   WarningOptionCompare);
+  if (Found == OptionTable + OptionTableSize ||
+      strcmp(Found->Name, Group) != 0)
+    return true;  // Option not found.
+
+  MapGroupMembers(Found, Map, Diag);
+  return false;
+}
+
+/// 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, 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);
+  }
+
+  // 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;
+}
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index e576b8d..4fa7d1d 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -100,7 +100,7 @@
         Diag.SetDelayedDiagnostic(diag::err_cannot_open_file, 
                                   Entry->getName(), ErrorStr);
       else 
-        Diag.Report(FullSourceLoc(Loc, SM), diag::err_cannot_open_file)
+        Diag.Report(Loc, diag::err_cannot_open_file)
           << Entry->getName() << ErrorStr;
 
       Buffer.setInt(Buffer.getInt() | InvalidFlag);
@@ -120,7 +120,7 @@
         Diag.SetDelayedDiagnostic(diag::err_file_modified,
                                   Entry->getName());
       else
-        Diag.Report(FullSourceLoc(Loc, SM), diag::err_file_modified)
+        Diag.Report(Loc, diag::err_file_modified)
           << Entry->getName();
 
       Buffer.setInt(Buffer.getInt() | InvalidFlag);
@@ -147,7 +147,7 @@
         .Default(0);
 
       if (BOM) {
-        Diag.Report(FullSourceLoc(Loc, SM), diag::err_unsupported_bom)
+        Diag.Report(Loc, diag::err_unsupported_bom)
           << BOM << Entry->getName();
         Buffer.setInt(1);
       }
@@ -342,6 +342,15 @@
 // Private 'Create' methods.
 //===----------------------------------------------------------------------===//
 
+SourceManager::SourceManager(Diagnostic &Diag, FileManager &FileMgr,
+                             const FileSystemOptions &FSOpts)
+  : Diag(Diag), FileMgr(FileMgr), FileSystemOpts(FSOpts),
+    ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
+    NumBinaryProbes(0) {
+  clearIDTables();
+  Diag.setSourceManager(this);
+}
+
 SourceManager::~SourceManager() {
   delete LineTable;
 
diff --git a/lib/Checker/PathDiagnostic.cpp b/lib/Checker/PathDiagnostic.cpp
index cf05a7d..1ddc08e 100644
--- a/lib/Checker/PathDiagnostic.cpp
+++ b/lib/Checker/PathDiagnostic.cpp
@@ -104,7 +104,9 @@
   Info.FormatDiagnostic(StrC);
 
   PathDiagnosticPiece *P =
-    new PathDiagnosticEventPiece(Info.getLocation(), StrC.str());
+    new PathDiagnosticEventPiece(FullSourceLoc(Info.getLocation(),
+                                               Info.getSourceManager()),
+                                 StrC.str());
 
   for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i)
     P->addRange(Info.getRange(i).getAsRange());
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 29276c3..cc5b198 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1529,7 +1529,7 @@
   assert(Diag && "Fall through without a diagnostic?");
   unsigned DiagID = CGM.getDiags().getCustomDiagID(Diagnostic::Error,
                                "debug information for %0 is not yet supported");
-  CGM.getDiags().Report(FullSourceLoc(), DiagID)
+  CGM.getDiags().Report(DiagID)
     << Diag;
   return llvm::DIType();
 }
diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp
index 6614531..9660e68 100644
--- a/lib/CodeGen/CodeGenAction.cpp
+++ b/lib/CodeGen/CodeGenAction.cpp
@@ -209,8 +209,7 @@
   // issue as being an error in the source with a note showing the instantiated
   // code.
   if (LocCookie.isValid()) {
-    Diags.Report(FullSourceLoc(LocCookie, Context->getSourceManager()),
-                 diag::err_fe_inline_asm).AddString(Message);
+    Diags.Report(LocCookie, diag::err_fe_inline_asm).AddString(Message);
     
     if (D.getLoc().isValid())
       Diags.Report(Loc, diag::note_fe_inline_asm_here);
@@ -318,7 +317,7 @@
       unsigned DiagID = CI.getDiagnostics().getCustomDiagID(Diagnostic::Error,
                                                             Msg);
 
-      CI.getDiagnostics().Report(FullSourceLoc(Loc, SM), DiagID);
+      CI.getDiagnostics().Report(Loc, DiagID);
       return;
     }
 
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 602c5f0..b240103 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -525,7 +525,7 @@
     Diagnostic &Diags = Context.getDiags();
     unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
                                       "cannot mangle dependent operator name");
-    Diags.Report(FullSourceLoc(), DiagID);
+    Diags.Report(DiagID);
     return;
   }
   
@@ -1672,9 +1672,7 @@
     Diagnostic &Diags = Context.getDiags();
     unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
                                      "cannot yet mangle expression type %0");
-    Diags.Report(FullSourceLoc(E->getExprLoc(),
-                               getASTContext().getSourceManager()),
-                 DiagID)
+    Diags.Report(E->getExprLoc(), DiagID)
       << E->getStmtClassName() << E->getSourceRange();
     break;
   }
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index c7a7434..3cb0aa6 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -404,7 +404,7 @@
 /// option.
 static void PrintDiagnosticCategories(llvm::raw_ostream &OS) {
   for (unsigned i = 1; // Skip the empty category.
-       const char *CategoryName = Diagnostic::getCategoryNameFromID(i); ++i)
+       const char *CategoryName = DiagnosticIDs::getCategoryNameFromID(i); ++i)
     OS << i << ',' << CategoryName << '\n';
 }
 
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
index f270846..7c8763d 100644
--- a/lib/Frontend/ASTMerge.cpp
+++ b/lib/Frontend/ASTMerge.cpp
@@ -38,21 +38,18 @@
                                          CI.getASTContext().getLangOptions());
   CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
                                        &CI.getASTContext());
-  llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics());
+  llvm::IntrusiveRefCntPtr<DiagnosticIDs>
+      DiagIDs(CI.getDiagnostics().getDiagnosticIDs());
   for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
+    llvm::IntrusiveRefCntPtr<Diagnostic>
+        Diags(new Diagnostic(DiagIDs, CI.getDiagnostics().getClient(),
+                             /*ShouldOwnClient=*/false));
     ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags,
                                              CI.getFileSystemOpts(), false);
     if (!Unit)
       continue;
 
-    // Reset the argument -> string function so that it has the AST
-    // context we want, since the Sema object created by
-    // LoadFromASTFile will override it.
-    CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
-                                         &CI.getASTContext());
-
-    ASTImporter Importer(CI.getDiagnostics(),
-                         CI.getASTContext(), 
+    ASTImporter Importer(CI.getASTContext(), 
                          CI.getFileManager(),
                          CI.getFileSystemOpts(),
                          Unit->getASTContext(), 
@@ -72,6 +69,15 @@
       Importer.Import(*D);
     }
 
+    // Aggregate the number of warnings/errors from all diagnostics so
+    // that at CompilerInstance::ExecuteAction we can report the total numbers.
+    // FIXME: This is hacky, maybe keep track of total number of warnings/errors
+    // in DiagnosticClient and have CompilerInstance query that ?
+    CI.getDiagnostics().setNumWarnings(CI.getDiagnostics().getNumWarnings() +
+                                       Diags->getNumWarnings());
+    CI.getDiagnostics().setNumErrors(CI.getDiagnostics().getNumErrors() +
+                                     Diags->getNumErrors());
+
     delete Unit;
   }
 
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 7cfcd1c..dafbef1 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -122,7 +122,8 @@
 CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
                                     int Argc, const char* const *Argv,
                                     DiagnosticClient *Client) {
-  llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic());
+  llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+  llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic(DiagID));
 
   // Create the diagnostic client for reporting errors or for
   // implementing -verify.
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 4fd0552..2528777 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -776,7 +776,7 @@
   // If the location is specified, print out a file/line/col and include trace
   // if enabled.
   if (Info.getLocation().isValid()) {
-    const SourceManager &SM = Info.getLocation().getManager();
+    const SourceManager &SM = Info.getSourceManager();
     PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation());
     if (PLoc.isInvalid())
       return;
@@ -884,7 +884,8 @@
 
   std::string OptionName;
   if (DiagOpts->ShowOptionNames) {
-    if (const char *Opt = Diagnostic::getWarningOptionForDiag(Info.getID())) {
+    if (const char *
+          Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID())) {
       OptionName = "-W";
       OptionName += Opt;
     } else if (Info.getID() == diag::fatal_too_many_errors) {
@@ -893,7 +894,8 @@
       // If the diagnostic is an extension diagnostic and not enabled by default
       // then it must have been turned on with -pedantic.
       bool EnabledByDefault;
-      if (Diagnostic::isBuiltinExtensionDiag(Info.getID(), EnabledByDefault) &&
+      if (DiagnosticIDs::isBuiltinExtensionDiag(Info.getID(),
+                                                EnabledByDefault) &&
           !EnabledByDefault)
         OptionName = "-pedantic";
     }
@@ -902,7 +904,7 @@
   // If the user wants to see category information, include it too.
   unsigned DiagCategory = 0;
   if (DiagOpts->ShowCategories)
-    DiagCategory = Diagnostic::getCategoryNumberForDiag(Info.getID());
+    DiagCategory = DiagnosticIDs::getCategoryNumberForDiag(Info.getID());
 
   // If there is any categorization information, include it.
   if (!OptionName.empty() || DiagCategory != 0) {
@@ -920,7 +922,7 @@
         OutStr += llvm::utostr(DiagCategory);
       else {
         assert(DiagOpts->ShowCategories == 2 && "Invalid ShowCategories value");
-        OutStr += Diagnostic::getCategoryNameFromID(DiagCategory);
+        OutStr += DiagnosticIDs::getCategoryNameFromID(DiagCategory);
       }
     }
     
@@ -962,7 +964,7 @@
        (LastCaretDiagnosticWasNote && Level != Diagnostic::Note) ||
        Info.getNumFixItHints())) {
     // Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
-    LastLoc = Info.getLocation();
+    LastLoc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
     LastCaretDiagnosticWasNote = (Level == Diagnostic::Note);
 
     // Get the ranges into a local array we can hack on.
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 13c25f4..918c671 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -78,7 +78,7 @@
 
 
 DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) {
-  return Diags.Report(FullSourceLoc(Loc, PP.getSourceManager()), DiagID);
+  return Diags.Report(Loc, DiagID);
 }
 
 DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) {
diff --git a/lib/Rewrite/FixItRewriter.cpp b/lib/Rewrite/FixItRewriter.cpp
index 5820969..9d42ac2 100644
--- a/lib/Rewrite/FixItRewriter.cpp
+++ b/lib/Rewrite/FixItRewriter.cpp
@@ -141,7 +141,7 @@
 }
 
 /// \brief Emit a diagnostic via the adapted diagnostic client.
-void FixItRewriter::Diag(FullSourceLoc Loc, unsigned DiagID) {
+void FixItRewriter::Diag(SourceLocation Loc, unsigned DiagID) {
   // When producing this diagnostic, we temporarily bypass ourselves,
   // clear out any current diagnostic, and let the downstream client
   // format the diagnostic.
diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp
index b461df4..e6b9aa3 100644
--- a/lib/Rewrite/HTMLRewrite.cpp
+++ b/lib/Rewrite/HTMLRewrite.cpp
@@ -486,7 +486,8 @@
 
   // Temporarily change the diagnostics object so that we ignore any generated
   // diagnostics from this pass.
-  Diagnostic TmpDiags(new IgnoringDiagClient);
+  Diagnostic TmpDiags(PP.getDiagnostics().getDiagnosticIDs(),
+                      new IgnoringDiagClient);
 
   // FIXME: This is a huge hack; we reuse the input preprocessor because we want
   // its state, but we aren't actually changing it (we hope). This should really
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 979b76a..5304193 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -23,8 +23,8 @@
 
 
 static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc,
-                              SourceManager &SrcMgr, unsigned DiagID) {
-  return D.Report(FullSourceLoc(Loc, SrcMgr), DiagID);
+                              unsigned DiagID) {
+  return D.Report(Loc, DiagID);
 }
 
 
@@ -512,28 +512,27 @@
   SaveStorageSpecifierAsWritten();
 
   // Check the type specifier components first.
-  SourceManager &SrcMgr = PP.getSourceManager();
 
   // Validate and finalize AltiVec vector declspec.
   if (TypeAltiVecVector) {
     if (TypeAltiVecBool) {
       // Sign specifiers are not allowed with vector bool. (PIM 2.1)
       if (TypeSpecSign != TSS_unspecified) {
-        Diag(D, TSSLoc, SrcMgr, diag::err_invalid_vector_bool_decl_spec)
+        Diag(D, TSSLoc, diag::err_invalid_vector_bool_decl_spec)
           << getSpecifierName((TSS)TypeSpecSign);
       }
 
       // Only char/int are valid with vector bool. (PIM 2.1)
       if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) &&
            (TypeSpecType != TST_int)) || TypeAltiVecPixel) {
-        Diag(D, TSTLoc, SrcMgr, diag::err_invalid_vector_bool_decl_spec)
+        Diag(D, TSTLoc, diag::err_invalid_vector_bool_decl_spec)
           << (TypeAltiVecPixel ? "__pixel" :
                                  getSpecifierName((TST)TypeSpecType));
       }
 
       // Only 'short' is valid with vector bool. (PIM 2.1)
       if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short))
-        Diag(D, TSWLoc, SrcMgr, diag::err_invalid_vector_bool_decl_spec)
+        Diag(D, TSWLoc, diag::err_invalid_vector_bool_decl_spec)
           << getSpecifierName((TSW)TypeSpecWidth);
 
       // Elements of vector bool are interpreted as unsigned. (PIM 2.1)
@@ -557,7 +556,7 @@
       TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
     else if (TypeSpecType != TST_int  &&
              TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
-      Diag(D, TSSLoc, SrcMgr, diag::err_invalid_sign_spec)
+      Diag(D, TSSLoc, diag::err_invalid_sign_spec)
         << getSpecifierName((TST)TypeSpecType);
       // signed double -> double.
       TypeSpecSign = TSS_unspecified;
@@ -572,7 +571,7 @@
     if (TypeSpecType == TST_unspecified)
       TypeSpecType = TST_int; // short -> short int, long long -> long long int.
     else if (TypeSpecType != TST_int) {
-      Diag(D, TSWLoc, SrcMgr,
+      Diag(D, TSWLoc,
            TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
                                       : diag::err_invalid_longlong_spec)
         <<  getSpecifierName((TST)TypeSpecType);
@@ -584,7 +583,7 @@
     if (TypeSpecType == TST_unspecified)
       TypeSpecType = TST_int;  // long -> long int.
     else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
-      Diag(D, TSWLoc, SrcMgr, diag::err_invalid_long_spec)
+      Diag(D, TSWLoc, diag::err_invalid_long_spec)
         << getSpecifierName((TST)TypeSpecType);
       TypeSpecType = TST_int;
       TypeSpecOwned = false;
@@ -596,16 +595,16 @@
   // disallow their use.  Need information about the backend.
   if (TypeSpecComplex != TSC_unspecified) {
     if (TypeSpecType == TST_unspecified) {
-      Diag(D, TSCLoc, SrcMgr, diag::ext_plain_complex)
+      Diag(D, TSCLoc, diag::ext_plain_complex)
         << FixItHint::CreateInsertion(
                               PP.getLocForEndOfToken(getTypeSpecComplexLoc()),
                                                  " double");
       TypeSpecType = TST_double;   // _Complex -> _Complex double.
     } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
       // Note that this intentionally doesn't include _Complex _Bool.
-      Diag(D, TSTLoc, SrcMgr, diag::ext_integer_complex);
+      Diag(D, TSTLoc, diag::ext_integer_complex);
     } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
-      Diag(D, TSCLoc, SrcMgr, diag::err_invalid_complex_spec)
+      Diag(D, TSCLoc, diag::err_invalid_complex_spec)
         << getSpecifierName((TST)TypeSpecType);
       TypeSpecComplex = TSC_unspecified;
     }
@@ -621,7 +620,7 @@
     SourceLocation SCLoc = getStorageClassSpecLoc();
     SourceLocation SCEndLoc = SCLoc.getFileLocWithOffset(strlen(SpecName));
 
-    Diag(D, SCLoc, SrcMgr, diag::err_friend_storage_spec)
+    Diag(D, SCLoc, diag::err_friend_storage_spec)
       << SpecName
       << FixItHint::CreateRemoval(SourceRange(SCLoc, SCEndLoc));
 
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 042f605..8c1d5f4 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -438,12 +438,12 @@
     return;
   
   if (TemplateDeductionInfo *Info = SemaRef.isSFINAEContext()) {
-    switch (Diagnostic::getDiagnosticSFINAEResponse(getDiagID())) {
-    case Diagnostic::SFINAE_Report:
+    switch (DiagnosticIDs::getDiagnosticSFINAEResponse(getDiagID())) {
+    case DiagnosticIDs::SFINAE_Report:
       // Fall through; we'll report the diagnostic below.
       break;
       
-    case Diagnostic::SFINAE_SubstitutionFailure:
+    case DiagnosticIDs::SFINAE_SubstitutionFailure:
       // Count this failure so that we know that template argument deduction
       // has failed.
       ++SemaRef.NumSFINAEErrors;
@@ -452,7 +452,7 @@
       Clear();
       return;
       
-    case Diagnostic::SFINAE_Suppress:
+    case DiagnosticIDs::SFINAE_Suppress:
       // Make a copy of this suppressed diagnostic and store it with the
       // template-deduction information;
       FlushCounts();
@@ -478,7 +478,7 @@
   // that is different from the last template instantiation where
   // we emitted an error, print a template instantiation
   // backtrace.
-  if (!SemaRef.Diags.isBuiltinNote(DiagID) &&
+  if (!DiagnosticIDs::isBuiltinNote(DiagID) &&
       !SemaRef.ActiveTemplateInstantiations.empty() &&
       SemaRef.ActiveTemplateInstantiations.back()
         != SemaRef.LastTemplateInstantiationErrorContext) {
@@ -489,7 +489,7 @@
 }
 
 Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID) {
-  DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
+  DiagnosticBuilder DB = Diags.Report(Loc, DiagID);
   return SemaDiagnosticBuilder(DB, *this, DiagID);
 }
 
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index c0e0427..2a7343f 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -382,7 +382,7 @@
     if (InstantiationIdx >= SkipStart && InstantiationIdx < SkipEnd) {
       if (InstantiationIdx == SkipStart) {
         // Note that we're skipping instantiations.
-        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+        Diags.Report(Active->PointOfInstantiation,
                      diag::note_instantiation_contexts_suppressed)
           << unsigned(ActiveTemplateInstantiations.size() - Limit);
       }
@@ -396,8 +396,7 @@
         unsigned DiagID = diag::note_template_member_class_here;
         if (isa<ClassTemplateSpecializationDecl>(Record))
           DiagID = diag::note_template_class_instantiation_here;
-        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
-                     DiagID)
+        Diags.Report(Active->PointOfInstantiation, DiagID)
           << Context.getTypeDeclType(Record)
           << Active->InstantiationRange;
       } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
@@ -406,12 +405,11 @@
           DiagID = diag::note_function_template_spec_here;
         else
           DiagID = diag::note_template_member_function_here;
-        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
-                     DiagID)
+        Diags.Report(Active->PointOfInstantiation, DiagID)
           << Function
           << Active->InstantiationRange;
       } else {
-        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+        Diags.Report(Active->PointOfInstantiation,
                      diag::note_template_static_data_member_def_here)
           << cast<VarDecl>(D)
           << Active->InstantiationRange;
@@ -426,7 +424,7 @@
                                                          Active->TemplateArgs,
                                                       Active->NumTemplateArgs,
                                                       Context.PrintingPolicy);
-      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+      Diags.Report(Active->PointOfInstantiation,
                    diag::note_default_arg_instantiation_here)
         << (Template->getNameAsString() + TemplateArgsStr)
         << Active->InstantiationRange;
@@ -436,7 +434,7 @@
     case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: {
       FunctionTemplateDecl *FnTmpl
         = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
-      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+      Diags.Report(Active->PointOfInstantiation,
                    diag::note_explicit_template_arg_substitution_here)
         << FnTmpl 
         << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(), 
@@ -450,7 +448,7 @@
       if (ClassTemplatePartialSpecializationDecl *PartialSpec
             = dyn_cast<ClassTemplatePartialSpecializationDecl>(
                                                     (Decl *)Active->Entity)) {
-        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+        Diags.Report(Active->PointOfInstantiation,
                      diag::note_partial_spec_deduct_instantiation_here)
           << Context.getTypeDeclType(PartialSpec)
           << getTemplateArgumentBindingsText(
@@ -461,7 +459,7 @@
       } else {
         FunctionTemplateDecl *FnTmpl
           = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
-        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+        Diags.Report(Active->PointOfInstantiation,
                      diag::note_function_template_deduction_instantiation_here)
           << FnTmpl
           << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(), 
@@ -480,7 +478,7 @@
                                                          Active->TemplateArgs,
                                                       Active->NumTemplateArgs,
                                                       Context.PrintingPolicy);
-      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+      Diags.Report(Active->PointOfInstantiation,
                    diag::note_default_function_arg_instantiation_here)
         << (FD->getNameAsString() + TemplateArgsStr)
         << Active->InstantiationRange;
@@ -493,7 +491,7 @@
       if (!Parm->getName().empty())
         Name = std::string(" '") + Parm->getName().str() + "'";
                                         
-      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+      Diags.Report(Active->PointOfInstantiation,
                    diag::note_prior_template_arg_substitution)
         << isa<TemplateTemplateParmDecl>(Parm)
         << Name
@@ -506,7 +504,7 @@
     }
 
     case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: {
-      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+      Diags.Report(Active->PointOfInstantiation,
                    diag::note_template_default_arg_checking)
         << getTemplateArgumentBindingsText(
                                      Active->Template->getTemplateParameters(), 
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 2a6692a..68f8b53 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -4383,7 +4383,7 @@
 }
 
 DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) {
-  return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
+  return Diags.Report(Loc, DiagID);
 }
 
 /// \brief Retrieve the identifier table associated with the