sanwou01 updated this revision to Diff 95548.
sanwou01 added a comment.
Herald added subscribers: mgorny, klimek.

Rebase on top of https://reviews.llvm.org/D31709 and 
https://reviews.llvm.org/D32159


https://reviews.llvm.org/D31501

Files:
  include/clang/Basic/Diagnostic.h
  include/clang/Basic/SourceLocation.h
  include/clang/Driver/Options.h
  include/clang/Driver/Options.td
  include/clang/Frontend/CompilerInvocation.h
  include/clang/Frontend/DiagnosticOptions.h
  include/clang/Frontend/DiagnosticRenderer.h
  include/clang/Frontend/TextDiagnostic.h
  lib/Basic/SourceLocation.cpp
  lib/Driver/DriverOptions.cpp
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CMakeLists.txt
  lib/Frontend/CompilerInvocation.cpp
  lib/Frontend/DiagnosticOptions.cpp
  lib/Frontend/DiagnosticRenderer.cpp
  lib/Frontend/SerializedDiagnosticPrinter.cpp
  lib/Frontend/TextDiagnostic.cpp
  lib/Frontend/TextDiagnosticPrinter.cpp
  lib/Tooling/Tooling.cpp
  test/Driver/asm-diags.s
  tools/driver/cc1as_main.cpp
  tools/driver/driver.cpp
  tools/libclang/CIndexDiagnostic.cpp

Index: tools/libclang/CIndexDiagnostic.cpp
===================================================================
--- tools/libclang/CIndexDiagnostic.cpp
+++ tools/libclang/CIndexDiagnostic.cpp
@@ -110,40 +110,34 @@
       CurrentSet = &CD.getChildDiagnostics();
   }
 
-  void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
-                             DiagnosticsEngine::Level Level,
-                             StringRef Message,
+  void emitDiagnosticMessage(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
+                             DiagnosticsEngine::Level Level, StringRef Message,
                              ArrayRef<CharSourceRange> Ranges,
-                             const SourceManager *SM,
                              DiagOrStoredDiag D) override {
     if (!D.isNull())
       return;
     
     CXSourceLocation L;
-    if (SM)
-      L = translateSourceLocation(*SM, LangOpts, Loc);
+    if (Loc.hasManager())
+      L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
     else
       L = clang_getNullLocation();
     CurrentSet->appendDiagnostic(
         llvm::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
   }
 
-  void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
+  void emitDiagnosticLoc(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
                          DiagnosticsEngine::Level Level,
-                         ArrayRef<CharSourceRange> Ranges,
-                         const SourceManager &SM) override {}
+                         ArrayRef<CharSourceRange> Ranges) override {}
 
-  void emitCodeContext(SourceLocation Loc,
-                       DiagnosticsEngine::Level Level,
-                       SmallVectorImpl<CharSourceRange>& Ranges,
-                       ArrayRef<FixItHint> Hints,
-                       const SourceManager &SM) override {}
+  void emitCodeContext(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level,
+                       SmallVectorImpl<CharSourceRange> &Ranges,
+                       ArrayRef<FixItHint> Hints) override {}
 
-  void emitNote(SourceLocation Loc, StringRef Message,
-                const SourceManager *SM) override {
+  void emitNote(UnifiedSourceLoc Loc, StringRef Message) override {
     CXSourceLocation L;
-    if (SM)
-      L = translateSourceLocation(*SM, LangOpts, Loc);
+    if (Loc.hasManager())
+      L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
     else
       L = clang_getNullLocation();
     CurrentSet->appendDiagnostic(
Index: tools/driver/driver.cpp
===================================================================
--- tools/driver/driver.cpp
+++ tools/driver/driver.cpp
@@ -20,6 +20,7 @@
 #include "clang/Driver/ToolChain.h"
 #include "clang/Frontend/ChainedDiagnosticConsumer.h"
 #include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/DiagnosticOptions.h"
 #include "clang/Frontend/SerializedDiagnosticPrinter.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Frontend/Utils.h"
Index: tools/driver/cc1as_main.cpp
===================================================================
--- tools/driver/cc1as_main.cpp
+++ tools/driver/cc1as_main.cpp
@@ -14,8 +14,13 @@
 
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
 #include "clang/Driver/DriverDiagnostic.h"
 #include "clang/Driver/Options.h"
+#include "clang/Frontend/DiagnosticOptions.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Frontend/Utils.h"
@@ -45,6 +50,7 @@
 #include "llvm/Support/Host.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetRegistry.h"
@@ -209,6 +215,8 @@
   Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
   Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
 
+  ParseDiagnosticArgs(Diags.getDiagnosticOptions(), Args, &Diags, false, false);
+
   // Frontend Options
   if (Args.hasArg(OPT_INPUT)) {
     bool First = true;
@@ -281,6 +289,29 @@
   return Out;
 }
 
+struct DiagsHandlerContext {
+  DiagnosticsEngine &Diags;
+  const SourceMgr *SrcMgr;
+};
+
+static void AssemblerDiagsHandler(const SMDiagnostic &D, void *Context) {
+  auto &Diags = *static_cast<DiagnosticsEngine *>(Context);
+  unsigned DiagID;
+  switch (D.getKind()) {
+  case llvm::SourceMgr::DK_Error:
+    DiagID = diag::err_fe_inline_asm;
+    break;
+  case llvm::SourceMgr::DK_Warning:
+    DiagID = diag::warn_fe_inline_asm;
+    break;
+  case llvm::SourceMgr::DK_Note:
+    DiagID = diag::note_fe_inline_asm;
+    break;
+  }
+
+  Diags.Report(D.getSourceMgr(), D.getLoc(), DiagID) << D.getMessage();
+}
+
 static bool ExecuteAssembler(AssemblerInvocation &Opts,
                              DiagnosticsEngine &Diags) {
   // Get the target specific parser.
@@ -306,6 +337,8 @@
   // it later.
   SrcMgr.setIncludeDirs(Opts.IncludePaths);
 
+  SrcMgr.setDiagHandler(AssemblerDiagsHandler, &Diags);
+
   std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
   assert(MRI && "Unable to create target register info!");
 
@@ -472,7 +505,6 @@
   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
   TextDiagnosticPrinter *DiagClient
     = new TextDiagnosticPrinter(errs(), &*DiagOpts);
-  DiagClient->setPrefix("clang -cc1as");
   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
   DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
 
@@ -514,9 +546,35 @@
     llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args);
   }
 
+  ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), true);
+
+  LangOptions LangOpts;
+  DiagClient->BeginSourceFile(LangOpts, nullptr);
+
   // Execute the invocation, unless there were parsing errors.
   bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags);
 
+  DiagClient->EndSourceFile();
+
+  // Notify the diagnostic client that all files were processed.
+  Diags.getClient()->finish();
+
+  if (Diags.getDiagnosticOptions().ShowCarets) {
+    // We can have multiple diagnostics sharing one diagnostic client.
+    // Get the total number of warnings/errors from the client.
+    unsigned NumWarnings = Diags.getClient()->getNumWarnings();
+    unsigned NumErrors = Diags.getClient()->getNumErrors();
+
+    if (NumWarnings)
+      errs() << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
+    if (NumWarnings && NumErrors)
+      errs() << " and ";
+    if (NumErrors)
+      errs() << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
+    if (NumWarnings || NumErrors)
+      errs() << " generated.\n";
+  }
+
   // If any timers were active but haven't been destroyed yet, print their
   // results now.
   TimerGroup::printAll(errs());
Index: test/Driver/asm-diags.s
===================================================================
--- /dev/null
+++ test/Driver/asm-diags.s
@@ -0,0 +1,23 @@
+# RUN: not %clang --target=arm-linux-gnueabi -march=armv8-m.main -c %s 2>&1 | FileCheck %s
+# RUN: not %clang --target=arm-linux-gnueabi -march=armv8-m.main -w -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-NO-WARNINGS
+# RUN: not %clang --target=arm-linux-gnueabi -march=armv8-m.main -Werror -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-FATAL-WARNINGS
+
+.thumb
+	ADD r0, r0, #0xFFFF0001
+	LDM r0, {r1, r0}
+
+# CHECK: asm-diags.s:6:14: error:
+# CHECK: 	ADD r0, r0, #0xFFFF0001
+# CHECK: asm-diags.s:7:15: warning:
+# CHECK: 	LDM r0, {r1, r0}
+# CHECK: 1 warning and 1 error generated.
+
+# CHECK-NO-WARNINGS: asm-diags.s:6:14: error:
+# CHECK-NO-WARNINGS: 	ADD r0, r0, #0xFFFF0001
+# CHECK-NO-WARNINGS: 1 error generated.
+
+# CHECK-FATAL-WARNINGS: asm-diags.s:6:14: error:
+# CHECK-FATAL-WARNINGS: 	ADD r0, r0, #0xFFFF0001
+# CHECK-FATAL-WARNINGS: asm-diags.s:7:15: error:
+# CHECK-FATAL-WARNINGS: 	LDM r0, {r1, r0}
+# CHECK-FATAL-WARNINGS: 2 errors generated.
Index: lib/Tooling/Tooling.cpp
===================================================================
--- lib/Tooling/Tooling.cpp
+++ lib/Tooling/Tooling.cpp
@@ -20,6 +20,7 @@
 #include "clang/Driver/ToolChain.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/DiagnosticOptions.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Lex/PreprocessorOptions.h"
Index: lib/Frontend/TextDiagnosticPrinter.cpp
===================================================================
--- lib/Frontend/TextDiagnosticPrinter.cpp
+++ lib/Frontend/TextDiagnosticPrinter.cpp
@@ -146,14 +146,9 @@
 
   // Assert that the rest of our infrastructure is setup properly.
   assert(DiagOpts && "Unexpected diagnostic without options set");
-  assert(Info.hasSourceManager() &&
-         "Unexpected diagnostic with no source manager");
   assert(TextDiag && "Unexpected diagnostic outside source file processing");
 
   TextDiag->emitDiagnostic(Info.getLocation(), Level, DiagMessageStream.str(),
-                           Info.getRanges(),
-                           Info.getFixItHints(),
-                           &Info.getSourceManager());
-
+                           Info.getRanges(), Info.getFixItHints());
   OS.flush();
 }
Index: lib/Frontend/TextDiagnostic.cpp
===================================================================
--- lib/Frontend/TextDiagnostic.cpp
+++ lib/Frontend/TextDiagnostic.cpp
@@ -672,20 +672,16 @@
 
 TextDiagnostic::~TextDiagnostic() {}
 
-void
-TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc,
-                                      PresumedLoc PLoc,
-                                      DiagnosticsEngine::Level Level,
-                                      StringRef Message,
-                                      ArrayRef<clang::CharSourceRange> Ranges,
-                                      const SourceManager *SM,
-                                      DiagOrStoredDiag D) {
+void TextDiagnostic::emitDiagnosticMessage(
+    UnifiedSourceLoc Loc, UnifiedPLoc PLoc, DiagnosticsEngine::Level Level,
+    StringRef Message, ArrayRef<clang::CharSourceRange> Ranges,
+    DiagOrStoredDiag D) {
   uint64_t StartOfLocationInfo = OS.tell();
 
   // Emit the location of this particular diagnostic.
   if (Loc.isValid())
-    emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM);
-  
+    emitDiagnosticLoc(Loc, PLoc, Level, Ranges);
+
   if (DiagOpts->ShowColors)
     OS.resetColor();
   
@@ -765,13 +761,13 @@
   OS << '\n';
 }
 
-void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) {
+void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager *SM) {
   SmallVector<char, 128> AbsoluteFilename;
-  if (DiagOpts->AbsolutePath) {
-    const DirectoryEntry *Dir = SM.getFileManager().getDirectory(
+  if (SM && DiagOpts->AbsolutePath) {
+    const DirectoryEntry *Dir = SM->getFileManager().getDirectory(
         llvm::sys::path::parent_path(Filename));
     if (Dir) {
-      StringRef DirName = SM.getFileManager().getCanonicalName(Dir);
+      StringRef DirName = SM->getFileManager().getCanonicalName(Dir);
       llvm::sys::path::append(AbsoluteFilename, DirName,
                               llvm::sys::path::filename(Filename));
       Filename = StringRef(AbsoluteFilename.data(), AbsoluteFilename.size());
@@ -787,17 +783,16 @@
 /// This includes extracting as much location information as is present for
 /// the diagnostic and printing it, as well as any include stack or source
 /// ranges necessary.
-void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
+void TextDiagnostic::emitDiagnosticLoc(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
                                        DiagnosticsEngine::Level Level,
-                                       ArrayRef<CharSourceRange> Ranges,
-                                       const SourceManager &SM) {
+                                       ArrayRef<CharSourceRange> Ranges) {
   if (PLoc.isInvalid()) {
     // At least print the file name if available:
-    FileID FID = SM.getFileID(Loc);
+    FileID FID = Loc.getFileID();
     if (FID.isValid()) {
-      const FileEntry* FE = SM.getFileEntryForID(FID);
+      const FileEntry *FE = Loc.getFileEntry();
       if (FE && FE->isValid()) {
-        emitFilename(FE->getName(), SM);
+        emitFilename(FE->getName(), &Loc.getManager());
         if (FE->isInPCH())
           OS << " (in PCH)";
         OS << ": ";
@@ -813,7 +808,8 @@
   if (DiagOpts->ShowColors)
     OS.changeColor(savedColor, true);
 
-  emitFilename(PLoc.getFilename(), SM);
+  emitFilename(PLoc.getFilename(),
+               Loc.hasManager() ? &Loc.getManager() : nullptr);
   switch (DiagOpts->getFormat()) {
   case DiagnosticOptions::Clang: OS << ':'  << LineNo; break;
   case DiagnosticOptions::MSVC:  OS << '('  << LineNo; break;
@@ -848,29 +844,32 @@
   }
 
   if (DiagOpts->ShowSourceRanges && !Ranges.empty()) {
-    FileID CaretFileID =
-      SM.getFileID(SM.getExpansionLoc(Loc));
+    FileID CaretFileID = Loc.getExpansionLoc().getFileID();
     bool PrintedRange = false;
 
     for (ArrayRef<CharSourceRange>::const_iterator RI = Ranges.begin(),
          RE = Ranges.end();
          RI != RE; ++RI) {
       // Ignore invalid ranges.
       if (!RI->isValid()) continue;
 
-      SourceLocation B = SM.getExpansionLoc(RI->getBegin());
-      SourceLocation E = SM.getExpansionLoc(RI->getEnd());
+      UnifiedSourceLoc B =
+          UnifiedSourceLoc(RI->getBegin(), Loc.getManager()).getExpansionLoc();
+      UnifiedSourceLoc E =
+          UnifiedSourceLoc(RI->getEnd(), Loc.getManager()).getExpansionLoc();
 
       // If the End location and the start location are the same and are a
       // macro location, then the range was something that came from a
       // macro expansion or _Pragma.  If this is an object-like macro, the
       // best we can do is to highlight the range.  If this is a
       // function-like macro, we'd also like to highlight the arguments.
       if (B == E && RI->getEnd().isMacroID())
-        E = SM.getExpansionRange(RI->getEnd()).second;
+        E = UnifiedSourceLoc(RI->getEnd(), Loc.getManager())
+                .getExpansionRange()
+                .second;
 
-      std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
-      std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
+      std::pair<FileID, unsigned> BInfo = B.getDecomposedLoc();
+      std::pair<FileID, unsigned> EInfo = E.getDecomposedLoc();
 
       // If the start or end of the range is in another file, just discard
       // it.
@@ -881,13 +880,10 @@
       // tokens.
       unsigned TokSize = 0;
       if (RI->isTokenRange())
-        TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts);
+        TokSize = Lexer::MeasureTokenLength(E, E.getManager(), LangOpts);
 
-      OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
-        << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
-        << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
-        << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize)
-        << '}';
+      OS << '{' << B.getLineNumber() << ':' << B.getColumnNumber() << '-'
+         << E.getLineNumber() << ':' << (E.getColumnNumber() + TokSize) << '}';
       PrintedRange = true;
     }
 
@@ -897,30 +893,27 @@
   OS << ' ';
 }
 
-void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
-                                         PresumedLoc PLoc,
-                                         const SourceManager &SM) {
+void TextDiagnostic::emitIncludeLocation(UnifiedSourceLoc Loc,
+                                         UnifiedPLoc PLoc) {
   if (DiagOpts->ShowLocation && PLoc.isValid())
     OS << "In file included from " << PLoc.getFilename() << ':'
        << PLoc.getLine() << ":\n";
   else
     OS << "In included file:\n"; 
 }
 
-void TextDiagnostic::emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
-                                        StringRef ModuleName,
-                                        const SourceManager &SM) {
+void TextDiagnostic::emitImportLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
+                                        StringRef ModuleName) {
   if (DiagOpts->ShowLocation && PLoc.isValid())
     OS << "In module '" << ModuleName << "' imported from "
        << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n";
   else
     OS << "In module '" << ModuleName << "':\n";
 }
 
-void TextDiagnostic::emitBuildingModuleLocation(SourceLocation Loc,
-                                                PresumedLoc PLoc,
-                                                StringRef ModuleName,
-                                                const SourceManager &SM) {
+void TextDiagnostic::emitBuildingModuleLocation(UnifiedSourceLoc Loc,
+                                                UnifiedPLoc PLoc,
+                                                StringRef ModuleName) {
   if (DiagOpts->ShowLocation && PLoc.isValid())
     OS << "While building module '" << ModuleName << "' imported from "
       << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n";
@@ -1081,10 +1074,8 @@
 /// \param Ranges The underlined ranges for this code snippet.
 /// \param Hints The FixIt hints active for this diagnostic.
 void TextDiagnostic::emitSnippetAndCaret(
-    SourceLocation Loc, DiagnosticsEngine::Level Level,
-    SmallVectorImpl<CharSourceRange>& Ranges,
-    ArrayRef<FixItHint> Hints,
-    const SourceManager &SM) {
+    UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level,
+    SmallVectorImpl<CharSourceRange> &Ranges, ArrayRef<FixItHint> Hints) {
   assert(Loc.isValid() && "must have a valid source location here");
   assert(Loc.isFileID() && "must have a file location here");
 
@@ -1096,27 +1087,29 @@
   // multiple times if one loc has multiple diagnostics.
   if (!DiagOpts->ShowCarets)
     return;
+
   if (Loc == LastLoc && Ranges.empty() && Hints.empty() &&
-      (LastLevel != DiagnosticsEngine::Note || Level == LastLevel))
+      (LastLevel != DiagnosticsEngine::Note || Level == LastLevel)) {
     return;
+  }
 
   // Decompose the location into a FID/Offset pair.
-  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+  std::pair<FileID, unsigned> LocInfo = Loc.getDecomposedLoc();
   FileID FID = LocInfo.first;
   unsigned FileOffset = LocInfo.second;
 
   // Get information about the buffer it points into.
   bool Invalid = false;
-  StringRef BufData = SM.getBufferData(FID, &Invalid);
+  StringRef BufData = Loc.getBufferData(&Invalid);
   if (Invalid)
     return;
 
   const char *BufStart = BufData.data();
   const char *BufEnd = BufStart + BufData.size();
 
-  unsigned LineNo = SM.getLineNumber(FID, FileOffset);
-  unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
-  
+  unsigned LineNo = Loc.getLineNumber();
+  unsigned ColNo = Loc.getColumnNumber();
+
   // Arbitrarily stop showing snippets when the line is too long.
   static const size_t MaxLineLengthToPrint = 4096;
   if (ColNo > MaxLineLengthToPrint)
@@ -1155,18 +1148,19 @@
   for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
                                                   E = Ranges.end();
        I != E; ++I)
-    highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM, LangOpts);
+    highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, Loc.getManager(),
+                   LangOpts);
 
   // Next, insert the caret itself.
   ColNo = sourceColMap.byteToContainingColumn(ColNo-1);
   if (CaretLine.size()<ColNo+1)
     CaretLine.resize(ColNo+1, ' ');
   CaretLine[ColNo] = '^';
 
-  std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
-                                                           sourceColMap,
-                                                           Hints, SM,
-                                                           DiagOpts.get());
+  std::string FixItInsertionLine;
+  if (!Hints.empty())
+    FixItInsertionLine = buildFixItInsertionLine(
+        LineNo, sourceColMap, Hints, Loc.getManager(), DiagOpts.get());
 
   // If the source line is too long for our terminal, select only the
   // "interesting" source region within that line.
@@ -1209,7 +1203,8 @@
   }
 
   // Print out any parseable fixit information requested by the options.
-  emitParseableFixits(Hints, SM);
+  if (!Hints.empty())
+    emitParseableFixits(Hints, Loc.getManager());
 }
 
 void TextDiagnostic::emitSnippet(StringRef line) {
@@ -1277,7 +1272,7 @@
 
     // We specifically do not do word-wrapping or tab-expansion here,
     // because this is supposed to be easy to parse.
-    PresumedLoc PLoc = SM.getPresumedLoc(BLoc);
+    UnifiedPLoc PLoc = SM.getPresumedLoc(BLoc);
     if (PLoc.isInvalid())
       break;
 
Index: lib/Frontend/SerializedDiagnosticPrinter.cpp
===================================================================
--- lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -63,27 +63,20 @@
   ~SDiagsRenderer() override {}
 
 protected:
-  void emitDiagnosticMessage(SourceLocation Loc,
-                             PresumedLoc PLoc,
-                             DiagnosticsEngine::Level Level,
-                             StringRef Message,
+  void emitDiagnosticMessage(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
+                             DiagnosticsEngine::Level Level, StringRef Message,
                              ArrayRef<CharSourceRange> Ranges,
-                             const SourceManager *SM,
                              DiagOrStoredDiag D) override;
 
-  void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
+  void emitDiagnosticLoc(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
                          DiagnosticsEngine::Level Level,
-                         ArrayRef<CharSourceRange> Ranges,
-                         const SourceManager &SM) override {}
+                         ArrayRef<CharSourceRange> Ranges) override {}
 
-  void emitNote(SourceLocation Loc, StringRef Message,
-                const SourceManager *SM) override;
+  void emitNote(UnifiedSourceLoc Loc, StringRef Message) override;
 
-  void emitCodeContext(SourceLocation Loc,
-                       DiagnosticsEngine::Level Level,
-                       SmallVectorImpl<CharSourceRange>& Ranges,
-                       ArrayRef<FixItHint> Hints,
-                       const SourceManager &SM) override;
+  void emitCodeContext(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level,
+                       SmallVectorImpl<CharSourceRange> &Ranges,
+                       ArrayRef<FixItHint> Hints) override;
 
   void beginDiagnostic(DiagOrStoredDiag D,
                        DiagnosticsEngine::Level Level) override;
@@ -193,11 +186,8 @@
   void ExitDiagBlock();
 
   /// \brief Emit a DIAG record.
-  void EmitDiagnosticMessage(SourceLocation Loc,
-                             PresumedLoc PLoc,
-                             DiagnosticsEngine::Level Level,
-                             StringRef Message,
-                             const SourceManager *SM,
+  void EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
+                             DiagnosticsEngine::Level Level, StringRef Message,
                              DiagOrStoredDiag D);
 
   /// \brief Emit FIXIT and SOURCE_RANGE records for a diagnostic.
@@ -220,16 +210,14 @@
   /// \brief Emit (lazily) the file string and retrieved the file identifier.
   unsigned getEmitFile(const char *Filename);
 
-  /// \brief Add SourceLocation information the specified record.  
-  void AddLocToRecord(SourceLocation Loc, const SourceManager *SM,
-                      PresumedLoc PLoc, RecordDataImpl &Record,
-                      unsigned TokSize = 0);
+  /// \brief Add SourceLocation information the specified record.
+  void AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc,
+                      RecordDataImpl &Record, unsigned TokSize = 0);
 
   /// \brief Add SourceLocation information the specified record.
-  void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record,
-                      const SourceManager *SM,
+  void AddLocToRecord(FullSourceLoc Loc, RecordDataImpl &Record,
                       unsigned TokSize = 0) {
-    AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(),
+    AddLocToRecord(Loc, Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc(),
                    Record, TokSize);
   }
 
@@ -350,11 +338,8 @@
   Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
 }
 
-void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
-                                  const SourceManager *SM,
-                                  PresumedLoc PLoc,
-                                  RecordDataImpl &Record,
-                                  unsigned TokSize) {
+void SDiagsWriter::AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc,
+                                  RecordDataImpl &Record, unsigned TokSize) {
   if (PLoc.isInvalid()) {
     // Emit a "sentinel" location.
     Record.push_back((unsigned)0); // File.
@@ -367,19 +352,19 @@
   Record.push_back(getEmitFile(PLoc.getFilename()));
   Record.push_back(PLoc.getLine());
   Record.push_back(PLoc.getColumn()+TokSize);
-  Record.push_back(SM->getFileOffset(Loc));
+  Record.push_back(Loc.getFileOffset());
 }
 
 void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
                                               RecordDataImpl &Record,
                                               const SourceManager &SM) {
-  AddLocToRecord(Range.getBegin(), Record, &SM);
+  AddLocToRecord(FullSourceLoc(Range.getBegin(), SM), Record);
   unsigned TokSize = 0;
   if (Range.isTokenRange())
     TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
                                         SM, *LangOpts);
-  
-  AddLocToRecord(Range.getEnd(), Record, &SM, TokSize);
+
+  AddLocToRecord(FullSourceLoc(Range.getEnd(), SM), Record, TokSize);
 }
 
 unsigned SDiagsWriter::getEmitFile(const char *FileName){
@@ -606,8 +591,8 @@
     if (DiagLevel == DiagnosticsEngine::Note)
       EnterDiagBlock();
 
-    EmitDiagnosticMessage(SourceLocation(), PresumedLoc(), DiagLevel,
-                          State->diagBuf, nullptr, &Info);
+    EmitDiagnosticMessage(FullSourceLoc(), PresumedLoc(), DiagLevel,
+                          State->diagBuf, &Info);
 
     if (DiagLevel == DiagnosticsEngine::Note)
       ExitDiagBlock();
@@ -618,12 +603,9 @@
   assert(Info.hasSourceManager() && LangOpts &&
          "Unexpected diagnostic with valid location outside of a source file");
   SDiagsRenderer Renderer(*this, *LangOpts, &*State->DiagOpts);
-  Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
-                          State->diagBuf,
-                          Info.getRanges(),
-                          Info.getFixItHints(),
-                          &Info.getSourceManager(),
-                          &Info);
+  Renderer.emitDiagnostic(
+      FullSourceLoc(Info.getLocation(), Info.getSourceManager()), DiagLevel,
+      State->diagBuf, Info.getRanges(), Info.getFixItHints(), &Info);
 }
 
 static serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) {
@@ -641,11 +623,9 @@
   llvm_unreachable("invalid diagnostic level");
 }
 
-void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc,
-                                         PresumedLoc PLoc,
+void SDiagsWriter::EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
                                          DiagnosticsEngine::Level Level,
                                          StringRef Message,
-                                         const SourceManager *SM,
                                          DiagOrStoredDiag D) {
   llvm::BitstreamWriter &Stream = State->Stream;
   RecordData &Record = State->Record;
@@ -655,7 +635,7 @@
   Record.clear();
   Record.push_back(RECORD_DIAG);
   Record.push_back(getStableLevel(Level));
-  AddLocToRecord(Loc, SM, PLoc, Record);
+  AddLocToRecord(Loc, PLoc, Record);
 
   if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) {
     // Emit the category string lazily and get the category ID.
@@ -672,15 +652,11 @@
   Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message);
 }
 
-void
-SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
-                                      PresumedLoc PLoc,
-                                      DiagnosticsEngine::Level Level,
-                                      StringRef Message,
-                                      ArrayRef<clang::CharSourceRange> Ranges,
-                                      const SourceManager *SM,
-                                      DiagOrStoredDiag D) {
-  Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, SM, D);
+void SDiagsRenderer::emitDiagnosticMessage(
+    UnifiedSourceLoc Loc, UnifiedPLoc PLoc, DiagnosticsEngine::Level Level,
+    StringRef Message, ArrayRef<clang::CharSourceRange> Ranges,
+    DiagOrStoredDiag D) {
+  Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, D);
 }
 
 void SDiagsWriter::EnterDiagBlock() {
@@ -733,20 +709,18 @@
   }
 }
 
-void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
+void SDiagsRenderer::emitCodeContext(UnifiedSourceLoc Loc,
                                      DiagnosticsEngine::Level Level,
                                      SmallVectorImpl<CharSourceRange> &Ranges,
-                                     ArrayRef<FixItHint> Hints,
-                                     const SourceManager &SM) {
-  Writer.EmitCodeContext(Ranges, Hints, SM);
+                                     ArrayRef<FixItHint> Hints) {
+  Writer.EmitCodeContext(Ranges, Hints, Loc.getManager());
 }
 
-void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message,
-                              const SourceManager *SM) {
+void SDiagsRenderer::emitNote(UnifiedSourceLoc Loc, StringRef Message) {
   Writer.EnterDiagBlock();
-  PresumedLoc PLoc = SM ? SM->getPresumedLoc(Loc) : PresumedLoc();
-  Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note,
-                               Message, SM, DiagOrStoredDiag());
+  PresumedLoc PLoc = Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc();
+  Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note, Message,
+                               DiagOrStoredDiag());
   Writer.ExitDiagBlock();
 }
 
Index: lib/Frontend/DiagnosticRenderer.cpp
===================================================================
--- lib/Frontend/DiagnosticRenderer.cpp
+++ lib/Frontend/DiagnosticRenderer.cpp
@@ -76,28 +76,25 @@
   }
 }
 
-void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
+void DiagnosticRenderer::emitDiagnostic(UnifiedSourceLoc Loc,
                                         DiagnosticsEngine::Level Level,
                                         StringRef Message,
                                         ArrayRef<CharSourceRange> Ranges,
                                         ArrayRef<FixItHint> FixItHints,
-                                        const SourceManager *SM,
                                         DiagOrStoredDiag D) {
-  assert(SM || Loc.isInvalid());
-
   beginDiagnostic(D, Level);
 
   if (!Loc.isValid())
     // If we have no source location, just emit the diagnostic message.
-    emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, SM, D);
+    emitDiagnosticMessage(Loc, UnifiedPLoc(), Level, Message, Ranges, D);
   else {
     // Get the ranges into a local array we can hack on.
     SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(),
                                                    Ranges.end());
 
     SmallVector<FixItHint, 8> MergedFixits;
     if (!FixItHints.empty()) {
-      mergeFixits(FixItHints, *SM, LangOpts, MergedFixits);
+      mergeFixits(FixItHints, Loc.getManager(), LangOpts, MergedFixits);
       FixItHints = MergedFixits;
     }
 
@@ -107,25 +104,26 @@
       if (I->RemoveRange.isValid())
         MutableRanges.push_back(I->RemoveRange);
 
-    SourceLocation UnexpandedLoc = Loc;
+    UnifiedSourceLoc UnexpandedLoc = Loc;
 
     // Find the ultimate expansion location for the diagnostic.
-    Loc = SM->getFileLoc(Loc);
+    Loc = Loc.getFileLoc();
 
-    PresumedLoc PLoc = SM->getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
+    UnifiedPLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc);
 
     // First, if this diagnostic is not in the main file, print out the
     // "included from" lines.
-    emitIncludeStack(Loc, PLoc, Level, *SM);
+    if (!Loc.isLLVMLocation())
+      emitIncludeStack(Loc, PLoc, Level);
 
     // Next, emit the actual diagnostic message and caret.
-    emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D);
-    emitCaret(Loc, Level, MutableRanges, FixItHints, *SM);
+    emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, D);
+    emitCaret(Loc, Level, MutableRanges, FixItHints);
 
     // If this location is within a macro, walk from UnexpandedLoc up to Loc
     // and produce a macro backtrace.
     if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) {
-      emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM);
+      emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints);
     }
   }
 
@@ -137,17 +135,18 @@
 
 
 void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
-  emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
-                 Diag.getRanges(), Diag.getFixIts(),
-                 Diag.getLocation().isValid() ? &Diag.getLocation().getManager()
-                                              : nullptr,
-                 &Diag);
+  emitDiagnostic(
+      Diag.getLocation().isValid()
+          ? FullSourceLoc(Diag.getLocation(), Diag.getLocation().getManager())
+          : FullSourceLoc(),
+      Diag.getLevel(), Diag.getMessage(), Diag.getRanges(), Diag.getFixIts(),
+      &Diag);
 }
 
 void DiagnosticRenderer::emitBasicNote(StringRef Message) {
-  emitDiagnosticMessage(
-      SourceLocation(), PresumedLoc(), DiagnosticsEngine::Note, Message,
-      None, nullptr, DiagOrStoredDiag());
+  emitDiagnosticMessage(UnifiedSourceLoc(), UnifiedPLoc(),
+                        DiagnosticsEngine::Note, Message, None,
+                        DiagOrStoredDiag());
 }
 
 /// \brief Prints an include stack when appropriate for a particular
@@ -161,12 +160,13 @@
 /// \param Loc   The diagnostic location.
 /// \param PLoc  The presumed location of the diagnostic location.
 /// \param Level The diagnostic level of the message this stack pertains to.
-void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
-                                          PresumedLoc PLoc,
-                                          DiagnosticsEngine::Level Level,
-                                          const SourceManager &SM) {
-  SourceLocation IncludeLoc =
-      PLoc.isInvalid() ? SourceLocation() : PLoc.getIncludeLoc();
+void DiagnosticRenderer::emitIncludeStack(UnifiedSourceLoc Loc,
+                                          UnifiedPLoc PLoc,
+                                          DiagnosticsEngine::Level Level) {
+  UnifiedSourceLoc IncludeLoc =
+      PLoc.isInvalid()
+          ? UnifiedSourceLoc()
+          : UnifiedSourceLoc(PLoc.getIncludeLoc(), Loc.getManager());
 
   // Skip redundant include stacks altogether.
   if (LastIncludeLoc == IncludeLoc)
@@ -178,88 +178,82 @@
     return;
 
   if (IncludeLoc.isValid())
-    emitIncludeStackRecursively(IncludeLoc, SM);
+    emitIncludeStackRecursively(IncludeLoc);
   else {
-    emitModuleBuildStack(SM);
-    emitImportStack(Loc, SM);
+    emitModuleBuildStack(Loc.getManager());
+    emitImportStack(Loc);
   }
 }
 
 /// \brief Helper to recursivly walk up the include stack and print each layer
 /// on the way back down.
-void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc,
-                                                     const SourceManager &SM) {
+void DiagnosticRenderer::emitIncludeStackRecursively(UnifiedSourceLoc Loc) {
   if (Loc.isInvalid()) {
-    emitModuleBuildStack(SM);
+    emitModuleBuildStack(Loc.getManager());
     return;
   }
-  
-  PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
+
+  UnifiedPLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc);
   if (PLoc.isInvalid())
     return;
 
   // If this source location was imported from a module, print the module
   // import stack rather than the 
   // FIXME: We want submodule granularity here.
-  std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc);
+  std::pair<UnifiedSourceLoc, StringRef> Imported = Loc.getModuleImportLoc();
   if (!Imported.second.empty()) {
     // This location was imported by a module. Emit the module import stack.
-    emitImportStackRecursively(Imported.first, Imported.second, SM);
+    emitImportStackRecursively(Imported.first, Imported.second);
     return;
   }
 
   // Emit the other include frames first.
-  emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM);
-  
+  emitIncludeStackRecursively(
+      UnifiedSourceLoc(PLoc.getIncludeLoc(), Loc.getManager()));
+
   // Emit the inclusion text/note.
-  emitIncludeLocation(Loc, PLoc, SM);
+  emitIncludeLocation(Loc, PLoc);
 }
 
 /// \brief Emit the module import stack associated with the current location.
-void DiagnosticRenderer::emitImportStack(SourceLocation Loc,
-                                         const SourceManager &SM) {
+void DiagnosticRenderer::emitImportStack(UnifiedSourceLoc Loc) {
   if (Loc.isInvalid()) {
-    emitModuleBuildStack(SM);
+    emitModuleBuildStack(Loc.getManager());
     return;
   }
 
-  std::pair<SourceLocation, StringRef> NextImportLoc
-    = SM.getModuleImportLoc(Loc);
-  emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
+  std::pair<UnifiedSourceLoc, StringRef> NextImportLoc =
+      Loc.getModuleImportLoc();
+  emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second);
 }
 
 /// \brief Helper to recursivly walk up the import stack and print each layer
 /// on the way back down.
-void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc,
-                                                    StringRef ModuleName,
-                                                    const SourceManager &SM) {
+void DiagnosticRenderer::emitImportStackRecursively(UnifiedSourceLoc Loc,
+                                                    StringRef ModuleName) {
   if (ModuleName.empty()) {
     return;
   }
 
-  PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
+  UnifiedPLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc);
 
   // Emit the other import frames first.
-  std::pair<SourceLocation, StringRef> NextImportLoc
-    = SM.getModuleImportLoc(Loc);
-  emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
+  std::pair<UnifiedSourceLoc, StringRef> NextImportLoc =
+      Loc.getModuleImportLoc();
+  emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second);
 
   // Emit the inclusion text/note.
-  emitImportLocation(Loc, PLoc, ModuleName, SM);
+  emitImportLocation(Loc, PLoc, ModuleName);
 }
 
 /// \brief Emit the module build stack, for cases where a module is (re-)built
 /// on demand.
 void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) {
   ModuleBuildStack Stack = SM.getModuleBuildStack();
   for (unsigned I = 0, N = Stack.size(); I != N; ++I) {
-    const SourceManager &CurSM = Stack[I].second.getManager();
-    SourceLocation CurLoc = Stack[I].second;
-    emitBuildingModuleLocation(CurLoc,
-                               CurSM.getPresumedLoc(CurLoc,
+    emitBuildingModuleLocation(Stack[I].second, Stack[I].second.getPresumedLoc(
                                                     DiagOpts->ShowPresumedLoc),
-                               Stack[I].first,
-                               CurSM);
+                               Stack[I].first);
   }
 }
 
@@ -348,12 +342,12 @@
 // in the same expansion as the caret; otherwise, we crawl to the top of
 // each chain. Two locations are part of the same macro expansion
 // iff the FileID is the same.
-static void mapDiagnosticRanges(
-    SourceLocation CaretLoc,
-    ArrayRef<CharSourceRange> Ranges,
-    SmallVectorImpl<CharSourceRange> &SpellingRanges,
-    const SourceManager *SM) {
-  FileID CaretLocFileID = SM->getFileID(CaretLoc);
+static void
+mapDiagnosticRanges(UnifiedSourceLoc CaretLoc, ArrayRef<CharSourceRange> Ranges,
+                    SmallVectorImpl<CharSourceRange> &SpellingRanges) {
+  FileID CaretLocFileID = CaretLoc.getFileID();
+
+  const SourceManager *SM = &CaretLoc.getManager();
 
   for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
     if (I->isInvalid()) continue;
@@ -404,42 +398,40 @@
   }
 }
 
-void DiagnosticRenderer::emitCaret(SourceLocation Loc,
+void DiagnosticRenderer::emitCaret(UnifiedSourceLoc Loc,
                                    DiagnosticsEngine::Level Level,
                                    ArrayRef<CharSourceRange> Ranges,
-                                   ArrayRef<FixItHint> Hints,
-                                   const SourceManager &SM) {
+                                   ArrayRef<FixItHint> Hints) {
   SmallVector<CharSourceRange, 4> SpellingRanges;
-  mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
-  emitCodeContext(Loc, Level, SpellingRanges, Hints, SM);
+  if (!Ranges.empty())
+    mapDiagnosticRanges(Loc, Ranges, SpellingRanges);
+  emitCodeContext(Loc, Level, SpellingRanges, Hints);
 }
 
 /// \brief A helper function for emitMacroExpansion to print the
 /// macro expansion message
 void DiagnosticRenderer::emitSingleMacroExpansion(
-    SourceLocation Loc,
-    DiagnosticsEngine::Level Level,
-    ArrayRef<CharSourceRange> Ranges,
-    const SourceManager &SM) {
+    UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level,
+    ArrayRef<CharSourceRange> Ranges) {
   // Find the spelling location for the macro definition. We must use the
   // spelling location here to avoid emitting a macro backtrace for the note.
-  SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
+  UnifiedSourceLoc SpellingLoc = Loc.getSpellingLoc();
 
   // Map the ranges into the FileID of the diagnostic location.
   SmallVector<CharSourceRange, 4> SpellingRanges;
-  mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
+  mapDiagnosticRanges(Loc, Ranges, SpellingRanges);
 
   SmallString<100> MessageStorage;
   llvm::raw_svector_ostream Message(MessageStorage);
-  StringRef MacroName =
-      Lexer::getImmediateMacroNameForDiagnostics(Loc, SM, LangOpts);
+  StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
+      Loc, Loc.getManager(), LangOpts);
   if (MacroName.empty())
     Message << "expanded from here";
   else
     Message << "expanded from macro '" << MacroName << "'";
 
   emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(),
-                 SpellingRanges, None, &SM);
+                 SpellingRanges, None);
 }
 
 /// Check that the macro argument location of Loc starts with ArgumentLoc.
@@ -473,13 +465,12 @@
 
 /// A helper function to check if the current ranges are all inside the same
 /// macro argument expansion as Loc.
-static bool checkRangesForMacroArgExpansion(SourceLocation Loc,
-                                            ArrayRef<CharSourceRange> Ranges,
-                                            const SourceManager &SM) {
+static bool checkRangesForMacroArgExpansion(UnifiedSourceLoc Loc,
+                                            ArrayRef<CharSourceRange> Ranges) {
   assert(Loc.isMacroID() && "Must be a macro expansion!");
 
   SmallVector<CharSourceRange, 4> SpellingRanges;
-  mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
+  mapDiagnosticRanges(Loc, Ranges, SpellingRanges);
 
   /// Count all valid ranges.
   unsigned ValidCount = 0;
@@ -490,15 +481,15 @@
     return false;
 
   /// To store the source location of the argument location.
-  SourceLocation ArgumentLoc;
+  UnifiedSourceLoc ArgumentLoc;
 
   /// Set the ArgumentLoc to the beginning location of the expansion of Loc
   /// so to check if the ranges expands to the same beginning location.
-  if (!SM.isMacroArgExpansion(Loc,&ArgumentLoc))
+  if (!Loc.isMacroArgExpansion(&ArgumentLoc))
     return false;
 
   for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) {
-    if (!checkRangeForMacroArgExpansion(*I, SM, ArgumentLoc))
+    if (!checkRangeForMacroArgExpansion(*I, Loc.getManager(), ArgumentLoc))
       return false;
   }
 
@@ -516,34 +507,33 @@
 /// \param Level The diagnostic level currently being emitted.
 /// \param Ranges The underlined ranges for this code snippet.
 /// \param Hints The FixIt hints active for this diagnostic.
-void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
+void DiagnosticRenderer::emitMacroExpansions(UnifiedSourceLoc Loc,
                                              DiagnosticsEngine::Level Level,
                                              ArrayRef<CharSourceRange> Ranges,
-                                             ArrayRef<FixItHint> Hints,
-                                             const SourceManager &SM) {
+                                             ArrayRef<FixItHint> Hints) {
   assert(Loc.isValid() && "must have a valid source location here");
 
   // Produce a stack of macro backtraces.
-  SmallVector<SourceLocation, 8> LocationStack;
+  SmallVector<UnifiedSourceLoc, 8> LocationStack;
   unsigned IgnoredEnd = 0;
   while (Loc.isMacroID()) {
     // If this is the expansion of a macro argument, point the caret at the
     // use of the argument in the definition of the macro, not the expansion.
-    if (SM.isMacroArgExpansion(Loc))
-      LocationStack.push_back(SM.getImmediateExpansionRange(Loc).first);
+    if (Loc.isMacroArgExpansion())
+      LocationStack.push_back(Loc.getImmediateExpansionRange().first);
     else
       LocationStack.push_back(Loc);
 
-    if (checkRangesForMacroArgExpansion(Loc, Ranges, SM))
+    if (checkRangesForMacroArgExpansion(Loc, Ranges))
       IgnoredEnd = LocationStack.size();
 
-    Loc = SM.getImmediateMacroCallerLoc(Loc);
+    Loc = Loc.getImmediateMacroCallerLoc();
 
     // Once the location no longer points into a macro, try stepping through
     // the last found location.  This sometimes produces additional useful
     // backtraces.
     if (Loc.isFileID())
-      Loc = SM.getImmediateMacroCallerLoc(LocationStack.back());
+      Loc = LocationStack.back().getImmediateMacroCallerLoc();
     assert(Loc.isValid() && "must have a valid source location here");
   }
 
@@ -555,7 +545,7 @@
   if (MacroDepth <= MacroLimit || MacroLimit == 0) {
     for (auto I = LocationStack.rbegin(), E = LocationStack.rend();
          I != E; ++I)
-      emitSingleMacroExpansion(*I, Level, Ranges, SM);
+      emitSingleMacroExpansion(*I, Level, Ranges);
     return;
   }
 
@@ -565,7 +555,7 @@
   for (auto I = LocationStack.rbegin(),
             E = LocationStack.rbegin() + MacroStartMessages;
        I != E; ++I)
-    emitSingleMacroExpansion(*I, Level, Ranges, SM);
+    emitSingleMacroExpansion(*I, Level, Ranges);
 
   SmallString<200> MessageStorage;
   llvm::raw_svector_ostream Message(MessageStorage);
@@ -577,49 +567,45 @@
   for (auto I = LocationStack.rend() - MacroEndMessages,
             E = LocationStack.rend();
        I != E; ++I)
-    emitSingleMacroExpansion(*I, Level, Ranges, SM);
+    emitSingleMacroExpansion(*I, Level, Ranges);
 }
 
 DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}
 
-void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc,
-                                                 PresumedLoc PLoc,
-                                                 const SourceManager &SM) {
+void DiagnosticNoteRenderer::emitIncludeLocation(UnifiedSourceLoc Loc,
+                                                 UnifiedPLoc PLoc) {
   // Generate a note indicating the include location.
   SmallString<200> MessageStorage;
   llvm::raw_svector_ostream Message(MessageStorage);
   Message << "in file included from " << PLoc.getFilename() << ':'
           << PLoc.getLine() << ":";
-  emitNote(Loc, Message.str(), &SM);
+  emitNote(Loc, Message.str());
 }
 
-void DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc,
-                                                PresumedLoc PLoc,
-                                                StringRef ModuleName,
-                                                const SourceManager &SM) {
+void DiagnosticNoteRenderer::emitImportLocation(UnifiedSourceLoc Loc,
+                                                UnifiedPLoc PLoc,
+                                                StringRef ModuleName) {
   // Generate a note indicating the include location.
   SmallString<200> MessageStorage;
   llvm::raw_svector_ostream Message(MessageStorage);
   Message << "in module '" << ModuleName;
   if (PLoc.isValid())
     Message << "' imported from " << PLoc.getFilename() << ':'
             << PLoc.getLine();
   Message << ":";
-  emitNote(Loc, Message.str(), &SM);
+  emitNote(Loc, Message.str());
 }
 
-void
-DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc,
-                                                   PresumedLoc PLoc,
-                                                   StringRef ModuleName,
-                                                   const SourceManager &SM) {
+void DiagnosticNoteRenderer::emitBuildingModuleLocation(UnifiedSourceLoc Loc,
+                                                        UnifiedPLoc PLoc,
+                                                        StringRef ModuleName) {
   // Generate a note indicating the include location.
   SmallString<200> MessageStorage;
   llvm::raw_svector_ostream Message(MessageStorage);
   if (PLoc.isValid())
     Message << "while building module '" << ModuleName << "' imported from "
             << PLoc.getFilename() << ':' << PLoc.getLine() << ":";
   else
     Message << "while building module '" << ModuleName << "':";
-  emitNote(Loc, Message.str(), &SM);
+  emitNote(Loc, Message.str());
 }
Index: lib/Frontend/DiagnosticOptions.cpp
===================================================================
--- /dev/null
+++ lib/Frontend/DiagnosticOptions.cpp
@@ -0,0 +1,230 @@
+//===--- DiagnosticOptions.cpp - Diagnostic option handling ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Frontend/Utils.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/Process.h"
+
+using namespace clang::driver;
+using namespace llvm::opt;
+using namespace clang::driver;
+using namespace clang::driver::options;
+
+namespace {
+using namespace clang;
+
+static void addDiagnosticArgs(const ArgList &Args, OptSpecifier Group,
+                              OptSpecifier GroupWithValue,
+                              std::vector<std::string> &Diagnostics) {
+  for (Arg *A : Args.filtered(Group)) {
+    if (A->getOption().getKind() == Option::FlagClass) {
+      // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
+      // its name (minus the "W" or "R" at the beginning) to the warning list.
+      Diagnostics.push_back(A->getOption().getName().drop_front(1));
+    } else if (A->getOption().matches(GroupWithValue)) {
+      // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic
+      // group.
+      Diagnostics.push_back(A->getOption().getName().drop_front(1).rtrim("=-"));
+    } else {
+      // Otherwise, add its value (for OPT_W_Joined and similar).
+      for (const char *Arg : A->getValues())
+        Diagnostics.emplace_back(Arg);
+    }
+  }
+}
+
+static bool parseDiagnosticLevelMask(StringRef FlagName,
+                                     const std::vector<std::string> &Levels,
+                                     DiagnosticsEngine *Diags,
+                                     DiagnosticLevelMask &M) {
+  bool Success = true;
+  for (const auto &Level : Levels) {
+    DiagnosticLevelMask const PM =
+        llvm::StringSwitch<DiagnosticLevelMask>(Level)
+            .Case("note", DiagnosticLevelMask::Note)
+            .Case("remark", DiagnosticLevelMask::Remark)
+            .Case("warning", DiagnosticLevelMask::Warning)
+            .Case("error", DiagnosticLevelMask::Error)
+            .Default(DiagnosticLevelMask::None);
+    if (PM == DiagnosticLevelMask::None) {
+      Success = false;
+      if (Diags)
+        Diags->Report(diag::err_drv_invalid_value) << FlagName << Level;
+    }
+    M = M | PM;
+  }
+  return Success;
+}
+
+static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
+  // Color diagnostics default to auto ("on" if terminal supports) in the driver
+  // but default to off in cc1, needing an explicit OPT_fdiagnostics_color.
+  // Support both clang's -f[no-]color-diagnostics and gcc's
+  // -f[no-]diagnostics-colors[=never|always|auto].
+  enum {
+    Colors_On,
+    Colors_Off,
+    Colors_Auto
+  } ShowColors = DefaultColor ? Colors_Auto : Colors_Off;
+  for (Arg *A : Args) {
+    const Option &O = A->getOption();
+    if (O.matches(options::OPT_fcolor_diagnostics) ||
+        O.matches(options::OPT_fdiagnostics_color)) {
+      ShowColors = Colors_On;
+    } else if (O.matches(options::OPT_fno_color_diagnostics) ||
+               O.matches(options::OPT_fno_diagnostics_color)) {
+      ShowColors = Colors_Off;
+    } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
+      StringRef Value(A->getValue());
+      if (Value == "always")
+        ShowColors = Colors_On;
+      else if (Value == "never")
+        ShowColors = Colors_Off;
+      else if (Value == "auto")
+        ShowColors = Colors_Auto;
+    }
+  }
+  return ShowColors == Colors_On ||
+         (ShowColors == Colors_Auto &&
+          llvm::sys::Process::StandardErrHasColors());
+}
+}
+
+bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts,
+                                const llvm::opt::ArgList &Args,
+                                DiagnosticsEngine *Diags, bool DefaultDiagColor,
+                                bool DefaultShowOpt) {
+  using namespace options;
+  bool Success = true;
+
+  Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file);
+  if (Arg *A =
+          Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags))
+    Opts.DiagnosticSerializationFile = A->getValue();
+  Opts.IgnoreWarnings = Args.hasArg(OPT_w);
+  Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros);
+  Opts.Pedantic = Args.hasArg(OPT_pedantic);
+  Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors);
+  Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics);
+  Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);
+  Opts.ShowColumn = Args.hasFlag(OPT_fshow_column, OPT_fno_show_column,
+                                 /*Default=*/true);
+  Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info);
+  Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location);
+  Opts.AbsolutePath = Args.hasArg(OPT_fdiagnostics_absolute_paths);
+  Opts.ShowOptionNames =
+      Args.hasFlag(OPT_fdiagnostics_show_option,
+                   OPT_fno_diagnostics_show_option, DefaultShowOpt);
+
+  llvm::sys::Process::UseANSIEscapeCodes(Args.hasArg(OPT_fansi_escape_codes));
+
+  // Default behavior is to not to show note include stacks.
+  Opts.ShowNoteIncludeStack = false;
+  if (Arg *A = Args.getLastArg(OPT_fdiagnostics_show_note_include_stack,
+                               OPT_fno_diagnostics_show_note_include_stack))
+    if (A->getOption().matches(OPT_fdiagnostics_show_note_include_stack))
+      Opts.ShowNoteIncludeStack = true;
+
+  StringRef ShowOverloads = Args.getLastArgValue(OPT_fshow_overloads_EQ, "all");
+  if (ShowOverloads == "best")
+    Opts.setShowOverloads(Ovl_Best);
+  else if (ShowOverloads == "all")
+    Opts.setShowOverloads(Ovl_All);
+  else {
+    Success = false;
+    if (Diags)
+      Diags->Report(diag::err_drv_invalid_value)
+          << Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args)
+          << ShowOverloads;
+  }
+
+  StringRef ShowCategory =
+      Args.getLastArgValue(OPT_fdiagnostics_show_category, "none");
+  if (ShowCategory == "none")
+    Opts.ShowCategories = 0;
+  else if (ShowCategory == "id")
+    Opts.ShowCategories = 1;
+  else if (ShowCategory == "name")
+    Opts.ShowCategories = 2;
+  else {
+    Success = false;
+    if (Diags)
+      Diags->Report(diag::err_drv_invalid_value)
+          << Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args)
+          << ShowCategory;
+  }
+
+  StringRef Format = Args.getLastArgValue(OPT_fdiagnostics_format, "clang");
+  if (Format == "clang")
+    Opts.setFormat(DiagnosticOptions::Clang);
+  else if (Format == "msvc")
+    Opts.setFormat(DiagnosticOptions::MSVC);
+  else if (Format == "msvc-fallback") {
+    Opts.setFormat(DiagnosticOptions::MSVC);
+    Opts.CLFallbackMode = true;
+  } else if (Format == "vi")
+    Opts.setFormat(DiagnosticOptions::Vi);
+  else {
+    Success = false;
+    if (Diags)
+      Diags->Report(diag::err_drv_invalid_value)
+          << Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args)
+          << Format;
+  }
+
+  Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
+  Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
+  Opts.ShowPresumedLoc =
+      !Args.hasArg(OPT_fno_diagnostics_use_presumed_location);
+  Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
+  DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
+  Success &= parseDiagnosticLevelMask(
+      "-verify-ignore-unexpected=",
+      Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), Diags, DiagMask);
+  if (Args.hasArg(OPT_verify_ignore_unexpected))
+    DiagMask = DiagnosticLevelMask::All;
+  Opts.setVerifyIgnoreUnexpected(DiagMask);
+  Opts.ElideType = !Args.hasArg(OPT_fno_elide_type);
+  Opts.ShowTemplateTree = Args.hasArg(OPT_fdiagnostics_show_template_tree);
+  Opts.ErrorLimit = getLastArgIntValue(Args, OPT_ferror_limit, 0, Diags);
+  Opts.MacroBacktraceLimit =
+      getLastArgIntValue(Args, OPT_fmacro_backtrace_limit,
+                         DiagnosticOptions::DefaultMacroBacktraceLimit, Diags);
+  Opts.TemplateBacktraceLimit = getLastArgIntValue(
+      Args, OPT_ftemplate_backtrace_limit,
+      DiagnosticOptions::DefaultTemplateBacktraceLimit, Diags);
+  Opts.ConstexprBacktraceLimit = getLastArgIntValue(
+      Args, OPT_fconstexpr_backtrace_limit,
+      DiagnosticOptions::DefaultConstexprBacktraceLimit, Diags);
+  Opts.SpellCheckingLimit =
+      getLastArgIntValue(Args, OPT_fspell_checking_limit,
+                         DiagnosticOptions::DefaultSpellCheckingLimit, Diags);
+  Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop,
+                                    DiagnosticOptions::DefaultTabStop, Diags);
+  if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
+    Opts.TabStop = DiagnosticOptions::DefaultTabStop;
+    if (Diags)
+      Diags->Report(diag::warn_ignoring_ftabstop_value)
+          << Opts.TabStop << DiagnosticOptions::DefaultTabStop;
+  }
+  Opts.MessageLength = getLastArgIntValue(Args, OPT_fmessage_length, 0, Diags);
+  addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings);
+  addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks);
+
+  return Success;
+}
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -16,6 +16,7 @@
 #include "clang/Driver/DriverDiagnostic.h"
 #include "clang/Driver/Options.h"
 #include "clang/Driver/Util.h"
+#include "clang/Frontend/DiagnosticOptions.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/LangStandard.h"
 #include "clang/Frontend/Utils.h"
@@ -41,8 +42,8 @@
 #include "llvm/Support/Host.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
-#include "llvm/Target/TargetOptions.h"
 #include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Target/TargetOptions.h"
 #include <atomic>
 #include <memory>
 #include <sys/stat.h>
@@ -122,25 +123,6 @@
   return 0;
 }
 
-static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
-                              OptSpecifier GroupWithValue,
-                              std::vector<std::string> &Diagnostics) {
-  for (Arg *A : Args.filtered(Group)) {
-    if (A->getOption().getKind() == Option::FlagClass) {
-      // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
-      // its name (minus the "W" or "R" at the beginning) to the warning list.
-      Diagnostics.push_back(A->getOption().getName().drop_front(1));
-    } else if (A->getOption().matches(GroupWithValue)) {
-      // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic group.
-      Diagnostics.push_back(A->getOption().getName().drop_front(1).rtrim("=-"));
-    } else {
-      // Otherwise, add its value (for OPT_W_Joined and similar).
-      for (const char *Arg : A->getValues())
-        Diagnostics.emplace_back(Arg);
-    }
-  }
-}
-
 static void getAllNoBuiltinFuncValues(ArgList &Args,
                                       std::vector<std::string> &Funcs) {
   SmallVector<const char *, 8> Values;
@@ -357,28 +339,6 @@
   return Pattern;
 }
 
-static bool parseDiagnosticLevelMask(StringRef FlagName,
-                                     const std::vector<std::string> &Levels,
-                                     DiagnosticsEngine *Diags,
-                                     DiagnosticLevelMask &M) {
-  bool Success = true;
-  for (const auto &Level : Levels) {
-    DiagnosticLevelMask const PM =
-      llvm::StringSwitch<DiagnosticLevelMask>(Level)
-        .Case("note",    DiagnosticLevelMask::Note)
-        .Case("remark",  DiagnosticLevelMask::Remark)
-        .Case("warning", DiagnosticLevelMask::Warning)
-        .Case("error",   DiagnosticLevelMask::Error)
-        .Default(DiagnosticLevelMask::None);
-    if (PM == DiagnosticLevelMask::None) {
-      Success = false;
-      if (Diags)
-        Diags->Report(diag::err_drv_invalid_value) << FlagName << Level;
-    }
-    M = M | PM;
-  }
-  return Success;
-}
 
 static void parseSanitizerKinds(StringRef FlagName,
                                 const std::vector<std::string> &Sanitizers,
@@ -940,163 +900,6 @@
                         ModuleFiles.end());
 }
 
-static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
-  // Color diagnostics default to auto ("on" if terminal supports) in the driver
-  // but default to off in cc1, needing an explicit OPT_fdiagnostics_color.
-  // Support both clang's -f[no-]color-diagnostics and gcc's
-  // -f[no-]diagnostics-colors[=never|always|auto].
-  enum {
-    Colors_On,
-    Colors_Off,
-    Colors_Auto
-  } ShowColors = DefaultColor ? Colors_Auto : Colors_Off;
-  for (Arg *A : Args) {
-    const Option &O = A->getOption();
-    if (O.matches(options::OPT_fcolor_diagnostics) ||
-        O.matches(options::OPT_fdiagnostics_color)) {
-      ShowColors = Colors_On;
-    } else if (O.matches(options::OPT_fno_color_diagnostics) ||
-               O.matches(options::OPT_fno_diagnostics_color)) {
-      ShowColors = Colors_Off;
-    } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
-      StringRef Value(A->getValue());
-      if (Value == "always")
-        ShowColors = Colors_On;
-      else if (Value == "never")
-        ShowColors = Colors_Off;
-      else if (Value == "auto")
-        ShowColors = Colors_Auto;
-    }
-  }
-  return ShowColors == Colors_On ||
-         (ShowColors == Colors_Auto &&
-          llvm::sys::Process::StandardErrHasColors());
-}
-
-bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
-                                DiagnosticsEngine *Diags,
-                                bool DefaultDiagColor, bool DefaultShowOpt) {
-  using namespace options;
-  bool Success = true;
-
-  Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file);
-  if (Arg *A =
-          Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags))
-    Opts.DiagnosticSerializationFile = A->getValue();
-  Opts.IgnoreWarnings = Args.hasArg(OPT_w);
-  Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros);
-  Opts.Pedantic = Args.hasArg(OPT_pedantic);
-  Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors);
-  Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics);
-  Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);
-  Opts.ShowColumn = Args.hasFlag(OPT_fshow_column,
-                                 OPT_fno_show_column,
-                                 /*Default=*/true);
-  Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info);
-  Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location);
-  Opts.AbsolutePath = Args.hasArg(OPT_fdiagnostics_absolute_paths);
-  Opts.ShowOptionNames =
-      Args.hasFlag(OPT_fdiagnostics_show_option,
-                   OPT_fno_diagnostics_show_option, DefaultShowOpt);
-
-  llvm::sys::Process::UseANSIEscapeCodes(Args.hasArg(OPT_fansi_escape_codes));
-
-  // Default behavior is to not to show note include stacks.
-  Opts.ShowNoteIncludeStack = false;
-  if (Arg *A = Args.getLastArg(OPT_fdiagnostics_show_note_include_stack,
-                               OPT_fno_diagnostics_show_note_include_stack))
-    if (A->getOption().matches(OPT_fdiagnostics_show_note_include_stack))
-      Opts.ShowNoteIncludeStack = true;
-
-  StringRef ShowOverloads =
-    Args.getLastArgValue(OPT_fshow_overloads_EQ, "all");
-  if (ShowOverloads == "best")
-    Opts.setShowOverloads(Ovl_Best);
-  else if (ShowOverloads == "all")
-    Opts.setShowOverloads(Ovl_All);
-  else {
-    Success = false;
-    if (Diags)
-      Diags->Report(diag::err_drv_invalid_value)
-      << Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args)
-      << ShowOverloads;
-  }
-
-  StringRef ShowCategory =
-    Args.getLastArgValue(OPT_fdiagnostics_show_category, "none");
-  if (ShowCategory == "none")
-    Opts.ShowCategories = 0;
-  else if (ShowCategory == "id")
-    Opts.ShowCategories = 1;
-  else if (ShowCategory == "name")
-    Opts.ShowCategories = 2;
-  else {
-    Success = false;
-    if (Diags)
-      Diags->Report(diag::err_drv_invalid_value)
-      << Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args)
-      << ShowCategory;
-  }
-
-  StringRef Format =
-    Args.getLastArgValue(OPT_fdiagnostics_format, "clang");
-  if (Format == "clang")
-    Opts.setFormat(DiagnosticOptions::Clang);
-  else if (Format == "msvc")
-    Opts.setFormat(DiagnosticOptions::MSVC);
-  else if (Format == "msvc-fallback") {
-    Opts.setFormat(DiagnosticOptions::MSVC);
-    Opts.CLFallbackMode = true;
-  } else if (Format == "vi")
-    Opts.setFormat(DiagnosticOptions::Vi);
-  else {
-    Success = false;
-    if (Diags)
-      Diags->Report(diag::err_drv_invalid_value)
-      << Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args)
-      << Format;
-  }
-
-  Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
-  Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
-  Opts.ShowPresumedLoc = !Args.hasArg(OPT_fno_diagnostics_use_presumed_location);
-  Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
-  DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
-  Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=",
-    Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ),
-    Diags, DiagMask);
-  if (Args.hasArg(OPT_verify_ignore_unexpected))
-    DiagMask = DiagnosticLevelMask::All;
-  Opts.setVerifyIgnoreUnexpected(DiagMask);
-  Opts.ElideType = !Args.hasArg(OPT_fno_elide_type);
-  Opts.ShowTemplateTree = Args.hasArg(OPT_fdiagnostics_show_template_tree);
-  Opts.ErrorLimit = getLastArgIntValue(Args, OPT_ferror_limit, 0, Diags);
-  Opts.MacroBacktraceLimit =
-      getLastArgIntValue(Args, OPT_fmacro_backtrace_limit,
-                         DiagnosticOptions::DefaultMacroBacktraceLimit, Diags);
-  Opts.TemplateBacktraceLimit = getLastArgIntValue(
-      Args, OPT_ftemplate_backtrace_limit,
-      DiagnosticOptions::DefaultTemplateBacktraceLimit, Diags);
-  Opts.ConstexprBacktraceLimit = getLastArgIntValue(
-      Args, OPT_fconstexpr_backtrace_limit,
-      DiagnosticOptions::DefaultConstexprBacktraceLimit, Diags);
-  Opts.SpellCheckingLimit = getLastArgIntValue(
-      Args, OPT_fspell_checking_limit,
-      DiagnosticOptions::DefaultSpellCheckingLimit, Diags);
-  Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop,
-                                    DiagnosticOptions::DefaultTabStop, Diags);
-  if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
-    Opts.TabStop = DiagnosticOptions::DefaultTabStop;
-    if (Diags)
-      Diags->Report(diag::warn_ignoring_ftabstop_value)
-      << Opts.TabStop << DiagnosticOptions::DefaultTabStop;
-  }
-  Opts.MessageLength = getLastArgIntValue(Args, OPT_fmessage_length, 0, Diags);
-  addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings);
-  addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks);
-
-  return Success;
-}
 
 static void ParseFileSystemArgs(FileSystemOptions &Opts, ArgList &Args) {
   Opts.WorkingDir = Args.getLastArgValue(OPT_working_directory);
Index: lib/Frontend/CMakeLists.txt
===================================================================
--- lib/Frontend/CMakeLists.txt
+++ lib/Frontend/CMakeLists.txt
@@ -26,6 +26,7 @@
   DependencyFile.cpp
   DependencyGraph.cpp
   DiagnosticRenderer.cpp
+  DiagnosticOptions.cpp
   FrontendAction.cpp
   FrontendActions.cpp
   FrontendOptions.cpp
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -28,6 +28,7 @@
 #include "clang/Driver/Options.h"
 #include "clang/Driver/SanitizerArgs.h"
 #include "clang/Driver/XRayArgs.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/CodeGen.h"
@@ -1684,6 +1685,33 @@
   CDB << ", \"" << escape(Buf) << "\"]},\n";
 }
 
+static void CollectArgsForColorDiagnostics(const ArgList &Args,
+                                           ArgStringList &CmdArgs,
+                                           const Driver &D) {
+  // Color diagnostics are parsed by the driver directly from argv
+  // and later re-parsed to construct this job; claim any possible
+  // color diagnostic here to avoid warn_drv_unused_argument and
+  // diagnose bad OPT_fdiagnostics_color_EQ values.
+  for (Arg *A : Args) {
+    const Option &O = A->getOption();
+    if (!O.matches(options::OPT_fcolor_diagnostics) &&
+        !O.matches(options::OPT_fdiagnostics_color) &&
+        !O.matches(options::OPT_fno_color_diagnostics) &&
+        !O.matches(options::OPT_fno_diagnostics_color) &&
+        !O.matches(options::OPT_fdiagnostics_color_EQ))
+      continue;
+    if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
+      StringRef Value(A->getValue());
+      if (Value != "always" && Value != "never" && Value != "auto")
+        D.Diag(diag::err_drv_clang_unsupported)
+            << ("-fdiagnostics-color=" + Value).str();
+    }
+    A->claim();
+  }
+  if (D.getDiags().getDiagnosticOptions().ShowColors)
+    CmdArgs.push_back("-fcolor-diagnostics");
+}
+
 static void CollectArgsForIntegratedAssembler(Compilation &C,
                                               const ArgList &Args,
                                               ArgStringList &CmdArgs,
@@ -4005,28 +4033,7 @@
       CmdArgs.push_back("-fno-diagnostics-show-note-include-stack");
   }
 
-  // Color diagnostics are parsed by the driver directly from argv
-  // and later re-parsed to construct this job; claim any possible
-  // color diagnostic here to avoid warn_drv_unused_argument and
-  // diagnose bad OPT_fdiagnostics_color_EQ values.
-  for (Arg *A : Args) {
-    const Option &O = A->getOption();
-    if (!O.matches(options::OPT_fcolor_diagnostics) &&
-        !O.matches(options::OPT_fdiagnostics_color) &&
-        !O.matches(options::OPT_fno_color_diagnostics) &&
-        !O.matches(options::OPT_fno_diagnostics_color) &&
-        !O.matches(options::OPT_fdiagnostics_color_EQ))
-      continue;
-    if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
-      StringRef Value(A->getValue());
-      if (Value != "always" && Value != "never" && Value != "auto")
-        getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
-              << ("-fdiagnostics-color=" + Value).str();
-    }
-    A->claim();
-  }
-  if (D.getDiags().getDiagnosticOptions().ShowColors)
-    CmdArgs.push_back("-fcolor-diagnostics");
+  CollectArgsForColorDiagnostics(Args, CmdArgs, getToolChain().getDriver());
 
   if (Args.hasArg(options::OPT_fansi_escape_codes))
     CmdArgs.push_back("-fansi-escape-codes");
@@ -4857,9 +4864,7 @@
   const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
   const std::string &TripleStr = Triple.getTriple();
 
-  // Don't warn about "clang -w -c foo.s"
-  Args.ClaimAllArgs(options::OPT_w);
-  // and "clang -emit-llvm -c foo.s"
+  // Don't warn about "clang -emit-llvm -c foo.s"
   Args.ClaimAllArgs(options::OPT_emit_llvm);
 
   claimNoWarnArgs(Args);
@@ -4998,12 +5003,11 @@
     break;
   }
 
-  // Consume all the warning flags. Usually this would be handled more
-  // gracefully by -cc1 (warning about unknown warning flags, etc) but -cc1as
-  // doesn't handle that so rather than warning about unused flags that are
-  // actually used, we'll lie by omission instead.
-  // FIXME: Stop lying and consume only the appropriate driver flags
-  Args.ClaimAllArgs(options::OPT_W_Group);
+  // Pass all warning flags to -cc1as.
+  Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
+  Args.AddLastArg(CmdArgs, options::OPT_w);
+
+  CollectArgsForColorDiagnostics(Args, CmdArgs, getToolChain().getDriver());
 
   CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
                                     getToolChain().getDriver());
Index: lib/Driver/DriverOptions.cpp
===================================================================
--- lib/Driver/DriverOptions.cpp
+++ lib/Driver/DriverOptions.cpp
@@ -7,10 +7,17 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Driver/DriverDiagnostic.h"
 #include "clang/Driver/Options.h"
+#include "clang/Frontend/Utils.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/ArgList.h"
 #include "llvm/Option/OptTable.h"
 #include "llvm/Option/Option.h"
+#include "llvm/Support/Process.h"
 
 using namespace clang::driver;
 using namespace clang::driver::options;
Index: lib/Basic/SourceLocation.cpp
===================================================================
--- lib/Basic/SourceLocation.cpp
+++ lib/Basic/SourceLocation.cpp
@@ -22,6 +22,7 @@
 // PrettyStackTraceLoc
 //===----------------------------------------------------------------------===//
 
+namespace clang {
 void PrettyStackTraceLoc::print(raw_ostream &OS) const {
   if (Loc.isValid()) {
     Loc.print(OS, SM);
@@ -92,6 +93,73 @@
   return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr);
 }
 
+FullSourceLoc FullSourceLoc::getFileLoc() const {
+  assert(isValid());
+  return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr);
+}
+
+std::pair<FullSourceLoc, FullSourceLoc>
+FullSourceLoc::getImmediateExpansionRange() const {
+  assert(isValid());
+  auto Range = SrcMgr->getImmediateExpansionRange(*this);
+  return std::make_pair(FullSourceLoc(Range.first, *SrcMgr),
+                        FullSourceLoc(Range.second, *SrcMgr));
+}
+
+PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const {
+  if (!isValid())
+    return PresumedLoc();
+
+  return SrcMgr->getPresumedLoc(*this, UseLineDirectives);
+}
+
+bool FullSourceLoc::isMacroArgExpansion(FullSourceLoc *StartLoc) const {
+  assert(isValid());
+  return SrcMgr->isMacroArgExpansion(*this, StartLoc);
+}
+
+FullSourceLoc FullSourceLoc::getImmediateMacroCallerLoc() const {
+  assert(isValid());
+  return FullSourceLoc(SrcMgr->getImmediateMacroCallerLoc(*this), *SrcMgr);
+}
+
+std::pair<FullSourceLoc, StringRef> FullSourceLoc::getModuleImportLoc() const {
+  if (!isValid())
+    return std::make_pair(FullSourceLoc(), StringRef());
+
+  auto ImportLoc = SrcMgr->getModuleImportLoc(*this);
+  return std::make_pair(FullSourceLoc(ImportLoc.first, *SrcMgr),
+                        ImportLoc.second);
+}
+
+unsigned FullSourceLoc::getFileOffset() const {
+  assert(isValid());
+  return SrcMgr->getFileOffset(*this);
+}
+
+unsigned FullSourceLoc::getLineNumber(bool *Invalid) const {
+  assert(isValid());
+  return SrcMgr->getLineNumber(getFileID(), getFileOffset(), Invalid);
+}
+
+unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const {
+  assert(isValid());
+  return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid);
+}
+
+std::pair<FullSourceLoc, FullSourceLoc>
+FullSourceLoc::getExpansionRange() const {
+  assert(isValid());
+  auto Range = SrcMgr->getExpansionRange(*this);
+  return std::make_pair(FullSourceLoc(Range.first, *SrcMgr),
+                        FullSourceLoc(Range.second, *SrcMgr));
+}
+
+const FileEntry *FullSourceLoc::getFileEntry() const {
+  assert(isValid());
+  return SrcMgr->getFileEntryForID(getFileID());
+}
+
 unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const {
   assert(isValid());
   return SrcMgr->getExpansionLineNumber(*this, Invalid);
@@ -139,3 +207,101 @@
 std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const {
   return SrcMgr->getDecomposedLoc(*this);
 }
+
+bool UnifiedSourceLoc::isValid() const {
+  if (!SrcMgr)
+    return FullSourceLoc::isValid();
+
+  return Loc.isValid();
+}
+
+UnifiedSourceLoc UnifiedSourceLoc::getFileLoc() const {
+  if (!SrcMgr)
+    return FullSourceLoc::getFileLoc();
+
+  // Just return the current location.
+  return *this;
+}
+
+UnifiedPLoc UnifiedSourceLoc::getPresumedLoc(bool UseLineDirectives) const {
+  if (!SrcMgr)
+    return FullSourceLoc::getPresumedLoc(UseLineDirectives);
+
+  // Return the current location as a PresumedLoc.
+  return UnifiedPLoc(Loc, *SrcMgr);
+}
+
+bool UnifiedSourceLoc::isLLVMLocation() const { return !!SrcMgr; }
+
+std::pair<FileID, unsigned> UnifiedSourceLoc::getDecomposedLoc() const {
+  if (!SrcMgr)
+    return FullSourceLoc::getDecomposedLoc();
+
+  unsigned Offset = Loc.getPointer() - getBufferData().data();
+  return std::make_pair(FileID(), Offset);
+}
+
+StringRef UnifiedSourceLoc::getBufferData(bool *Invalid) const {
+  if (!SrcMgr)
+    return FullSourceLoc::getBufferData(Invalid);
+
+  unsigned BufID = SrcMgr->FindBufferContainingLoc(Loc);
+  return SrcMgr->getMemoryBuffer(BufID)->getBuffer();
+}
+
+unsigned UnifiedSourceLoc::getLineNumber() const {
+  if (!SrcMgr)
+    return FullSourceLoc::getLineNumber();
+
+  return SrcMgr->getLineAndColumn(Loc).first;
+}
+
+unsigned UnifiedSourceLoc::getColumnNumber() const {
+  if (!SrcMgr)
+    return FullSourceLoc::getColumnNumber();
+
+  return SrcMgr->getLineAndColumn(Loc).second;
+}
+
+bool UnifiedPLoc::isValid() const {
+  if (!SrcMgr)
+    return PresumedLoc::isValid();
+
+  return Loc.isValid();
+}
+
+bool UnifiedPLoc::isInvalid() const { return !isValid(); }
+
+unsigned UnifiedPLoc::getLine() const {
+  if (!SrcMgr)
+    return PresumedLoc::getLine();
+
+  return SrcMgr->getLineAndColumn(Loc).first;
+}
+
+unsigned UnifiedPLoc::getColumn() const {
+  if (!SrcMgr)
+    return PresumedLoc::getColumn();
+
+  return SrcMgr->getLineAndColumn(Loc).second;
+}
+
+StringRef UnifiedPLoc::getFilename() const {
+  if (!SrcMgr)
+    return PresumedLoc::getFilename();
+
+  unsigned CurBuf = SrcMgr->FindBufferContainingLoc(Loc);
+  assert(CurBuf && "Invalid or unspecified location!");
+
+  const llvm::MemoryBuffer *CurMB = SrcMgr->getMemoryBuffer(CurBuf);
+  return CurMB->getBufferIdentifier();
+}
+
+SourceLocation UnifiedPLoc::getIncludeLoc() const {
+  if (!SrcMgr)
+    return PresumedLoc::getIncludeLoc();
+
+  return SourceLocation();
+}
+
+} // end namespace clang
Index: include/clang/Frontend/TextDiagnostic.h
===================================================================
--- include/clang/Frontend/TextDiagnostic.h
+++ include/clang/Frontend/TextDiagnostic.h
@@ -75,44 +75,35 @@
                                      unsigned Columns, bool ShowColors);
 
 protected:
-  void emitDiagnosticMessage(SourceLocation Loc,PresumedLoc PLoc,
-                             DiagnosticsEngine::Level Level,
-                             StringRef Message,
+  void emitDiagnosticMessage(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
+                             DiagnosticsEngine::Level Level, StringRef Message,
                              ArrayRef<CharSourceRange> Ranges,
-                             const SourceManager *SM,
                              DiagOrStoredDiag D) override;
 
-  void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
+  void emitDiagnosticLoc(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
                          DiagnosticsEngine::Level Level,
-                         ArrayRef<CharSourceRange> Ranges,
-                         const SourceManager &SM) override;
-
-  void emitCodeContext(SourceLocation Loc,
-                       DiagnosticsEngine::Level Level,
-                       SmallVectorImpl<CharSourceRange>& Ranges,
-                       ArrayRef<FixItHint> Hints,
-                       const SourceManager &SM) override {
-    emitSnippetAndCaret(Loc, Level, Ranges, Hints, SM);
+                         ArrayRef<CharSourceRange> Ranges) override;
+
+  void emitCodeContext(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level,
+                       SmallVectorImpl<CharSourceRange> &Ranges,
+                       ArrayRef<FixItHint> Hints) override {
+    emitSnippetAndCaret(Loc, Level, Ranges, Hints);
   }
 
-  void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
-                           const SourceManager &SM) override;
+  void emitIncludeLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc) override;
 
-  void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
-                          StringRef ModuleName,
-                          const SourceManager &SM) override;
+  void emitImportLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
+                          StringRef ModuleName) override;
 
-  void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
-                                  StringRef ModuleName,
-                                  const SourceManager &SM) override;
+  void emitBuildingModuleLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
+                                  StringRef ModuleName) override;
 
 private:
-  void emitFilename(StringRef Filename, const SourceManager &SM);
+  void emitFilename(StringRef Filename, const SourceManager *SM);
 
-  void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
-                           SmallVectorImpl<CharSourceRange>& Ranges,
-                           ArrayRef<FixItHint> Hints,
-                           const SourceManager &SM);
+  void emitSnippetAndCaret(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level,
+                           SmallVectorImpl<CharSourceRange> &Ranges,
+                           ArrayRef<FixItHint> Hints);
 
   void emitSnippet(StringRef SourceLine);
 
Index: include/clang/Frontend/DiagnosticRenderer.h
===================================================================
--- include/clang/Frontend/DiagnosticRenderer.h
+++ include/clang/Frontend/DiagnosticRenderer.h
@@ -52,8 +52,8 @@
   /// This will be invalid in cases where there is no (known) previous
   /// diagnostic location, or that location itself is invalid or comes from
   /// a different source manager than SM.
-  SourceLocation LastLoc;
-  
+  UnifiedSourceLoc LastLoc;
+
   /// \brief The location of the last include whose stack was printed if known.
   ///
   /// Same restriction as LastLoc essentially, but tracking include stack
@@ -70,33 +70,28 @@
                      DiagnosticOptions *DiagOpts);
   
   virtual ~DiagnosticRenderer();
-  
-  virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
+
+  virtual void emitDiagnosticMessage(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
                                      DiagnosticsEngine::Level Level,
                                      StringRef Message,
                                      ArrayRef<CharSourceRange> Ranges,
-                                     const SourceManager *SM,
                                      DiagOrStoredDiag Info) = 0;
-  
-  virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
+
+  virtual void emitDiagnosticLoc(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
                                  DiagnosticsEngine::Level Level,
-                                 ArrayRef<CharSourceRange> Ranges,
-                                 const SourceManager &SM) = 0;
+                                 ArrayRef<CharSourceRange> Ranges) = 0;
 
-  virtual void emitCodeContext(SourceLocation Loc,
+  virtual void emitCodeContext(UnifiedSourceLoc Loc,
                                DiagnosticsEngine::Level Level,
-                               SmallVectorImpl<CharSourceRange>& Ranges,
-                               ArrayRef<FixItHint> Hints,
-                               const SourceManager &SM) = 0;
-  
-  virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
-                                   const SourceManager &SM) = 0;
-  virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
-                                  StringRef ModuleName,
-                                  const SourceManager &SM) = 0;
-  virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
-                                          StringRef ModuleName,
-                                          const SourceManager &SM) = 0;
+                               SmallVectorImpl<CharSourceRange> &Ranges,
+                               ArrayRef<FixItHint> Hints) = 0;
+
+  virtual void emitIncludeLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc) = 0;
+  virtual void emitImportLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
+                                  StringRef ModuleName) = 0;
+  virtual void emitBuildingModuleLocation(UnifiedSourceLoc Loc,
+                                          UnifiedPLoc PLoc,
+                                          StringRef ModuleName) = 0;
 
   virtual void beginDiagnostic(DiagOrStoredDiag D,
                                DiagnosticsEngine::Level Level) {}
@@ -106,25 +101,21 @@
   
 private:
   void emitBasicNote(StringRef Message);
-  void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc,
-                        DiagnosticsEngine::Level Level, const SourceManager &SM);
-  void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
-  void emitImportStack(SourceLocation Loc, const SourceManager &SM);
-  void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName,
-                                  const SourceManager &SM);
+  void emitIncludeStack(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
+                        DiagnosticsEngine::Level Level);
+  void emitIncludeStackRecursively(UnifiedSourceLoc Loc);
+  void emitImportStack(UnifiedSourceLoc Loc);
+  void emitImportStackRecursively(UnifiedSourceLoc Loc, StringRef ModuleName);
   void emitModuleBuildStack(const SourceManager &SM);
-  void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
-                 ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints,
-                 const SourceManager &SM);
-  void emitSingleMacroExpansion(SourceLocation Loc,
+  void emitCaret(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level,
+                 ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints);
+  void emitSingleMacroExpansion(UnifiedSourceLoc Loc,
                                 DiagnosticsEngine::Level Level,
-                                ArrayRef<CharSourceRange> Ranges,
-                                const SourceManager &SM);
-  void emitMacroExpansions(SourceLocation Loc,
-                           DiagnosticsEngine::Level Level,
+                                ArrayRef<CharSourceRange> Ranges);
+  void emitMacroExpansions(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level,
                            ArrayRef<CharSourceRange> Ranges,
-                           ArrayRef<FixItHint> Hints,
-                           const SourceManager &SM);
+                           ArrayRef<FixItHint> Hints);
+
 public:
   /// \brief Emit a diagnostic.
   ///
@@ -140,10 +131,9 @@
   /// \param FixItHints The FixIt hints active for this diagnostic.
   /// \param SM The SourceManager; will be null if the diagnostic came from the
   ///        frontend, thus \p Loc will be invalid.
-  void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
+  void emitDiagnostic(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level,
                       StringRef Message, ArrayRef<CharSourceRange> Ranges,
                       ArrayRef<FixItHint> FixItHints,
-                      const SourceManager *SM,
                       DiagOrStoredDiag D = (Diagnostic *)nullptr);
 
   void emitStoredDiagnostic(StoredDiagnostic &Diag);
@@ -159,19 +149,15 @@
 
   ~DiagnosticNoteRenderer() override;
 
-  void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
-                           const SourceManager &SM) override;
+  void emitIncludeLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc) override;
 
-  void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
-                          StringRef ModuleName,
-                          const SourceManager &SM) override;
+  void emitImportLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
+                          StringRef ModuleName) override;
 
-  void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
-                                  StringRef ModuleName,
-                                  const SourceManager &SM) override;
+  void emitBuildingModuleLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc,
+                                  StringRef ModuleName) override;
 
-  virtual void emitNote(SourceLocation Loc, StringRef Message,
-                        const SourceManager *SM) = 0;
+  virtual void emitNote(UnifiedSourceLoc Loc, StringRef Message) = 0;
 };
 } // end clang namespace
 #endif
Index: include/clang/Frontend/DiagnosticOptions.h
===================================================================
--- /dev/null
+++ include/clang/Frontend/DiagnosticOptions.h
@@ -0,0 +1,39 @@
+//===--- DiagnosticOptions.h - Handling of diagnostic options ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
+#define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
+
+namespace llvm {
+namespace opt {
+
+class ArgList;
+}
+}
+
+namespace clang {
+
+class DiagnosticOptions;
+class DiagnosticsEngine;
+
+/// \brief Fill out Opts based on the options given in Args.
+///
+/// Args must have been created from the OptTable returned by
+/// createCC1OptTable().
+///
+/// When errors are encountered, return false and, if Diags is non-null,
+/// report the error(s).
+bool ParseDiagnosticArgs(DiagnosticOptions &Opts,
+                         const llvm::opt::ArgList &Args,
+                         DiagnosticsEngine *Diags = nullptr,
+                         bool DefaultDiagColor = true,
+                         bool DefaultShowOpt = true);
+}
+
+#endif
\ No newline at end of file
Index: include/clang/Frontend/CompilerInvocation.h
===================================================================
--- include/clang/Frontend/CompilerInvocation.h
+++ include/clang/Frontend/CompilerInvocation.h
@@ -39,18 +39,6 @@
 class CompilerInvocation;
 class DiagnosticsEngine;
 
-/// \brief Fill out Opts based on the options given in Args.
-///
-/// Args must have been created from the OptTable returned by
-/// createCC1OptTable().
-///
-/// When errors are encountered, return false and, if Diags is non-null,
-/// report the error(s).
-bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args,
-                         DiagnosticsEngine *Diags = nullptr,
-                         bool DefaultDiagColor = true,
-                         bool DefaultShowOpt = true);
-
 class CompilerInvocationBase {
   void operator=(const CompilerInvocationBase &) = delete;
 
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -433,7 +433,7 @@
   MetaVarName<"<arg>">, Group<Preprocessor_Group>;
 def Wwrite_strings : Flag<["-"], "Wwrite-strings">, Group<W_Group>, Flags<[CC1Option, HelpHidden]>;
 def Wno_write_strings : Flag<["-"], "Wno-write-strings">, Group<W_Group>, Flags<[CC1Option, HelpHidden]>;
-def W_Joined : Joined<["-"], "W">, Group<W_Group>, Flags<[CC1Option, CoreOption]>,
+def W_Joined : Joined<["-"], "W">, Group<W_Group>, Flags<[CC1Option, CC1AsOption, CoreOption]>,
   MetaVarName<"<warning>">, HelpText<"Enable the specified warning">;
 def Xanalyzer : Separate<["-"], "Xanalyzer">,
   HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">,
@@ -685,7 +685,7 @@
 def fcaret_diagnostics : Flag<["-"], "fcaret-diagnostics">, Group<f_Group>;
 def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group<f_Group>;
 def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<f_Group>,
-  Flags<[CoreOption, CC1Option]>, HelpText<"Use colors in diagnostics">;
+  Flags<[CoreOption, CC1Option, CC1AsOption]>, HelpText<"Use colors in diagnostics">;
 def fdiagnostics_color : Flag<["-"], "fdiagnostics-color">, Group<f_Group>,
   Flags<[CoreOption, DriverOption]>;
 def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group<f_Group>;
@@ -2208,7 +2208,7 @@
 def weak__reference__mismatches : Separate<["-"], "weak_reference_mismatches">;
 def whatsloaded : Flag<["-"], "whatsloaded">;
 def whyload : Flag<["-"], "whyload">;
-def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">, Flags<[CC1Option]>;
+def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">, Flags<[CC1Option,CC1AsOption]>;
 def x : JoinedOrSeparate<["-"], "x">, Flags<[DriverOption,CC1Option]>,
   HelpText<"Treat subsequent input files as having type <language>">,
   MetaVarName<"<language>">;
Index: include/clang/Driver/Options.h
===================================================================
--- include/clang/Driver/Options.h
+++ include/clang/Driver/Options.h
@@ -15,10 +15,13 @@
 namespace llvm {
 namespace opt {
 class OptTable;
+class ArgList;
 }
 }
 
 namespace clang {
+class DiagnosticOptions;
+class DiagnosticsEngine;
 namespace driver {
 
 namespace options {
Index: include/clang/Basic/SourceLocation.h
===================================================================
--- include/clang/Basic/SourceLocation.h
+++ include/clang/Basic/SourceLocation.h
@@ -18,13 +18,15 @@
 #include "clang/Basic/LLVM.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm/Support/SMLoc.h"
 #include <cassert>
 #include <functional>
 #include <string>
 #include <utility>
 
 namespace llvm {
   class MemoryBuffer;
+  class SourceMgr;
   template <typename T> struct DenseMapInfo;
   template <typename T> struct isPodLike;
 }
@@ -262,6 +264,65 @@
   bool isInvalid() const { return !isValid(); }
 };
 
+/// \brief Represents an unpacked "presumed" location which can be presented
+/// to the user.
+///
+/// A 'presumed' location can be modified by \#line and GNU line marker
+/// directives and is always the expansion point of a normal location.
+///
+/// You can get a PresumedLoc from a SourceLocation with SourceManager.
+class PresumedLoc {
+  const char *Filename;
+  unsigned Line, Col;
+  SourceLocation IncludeLoc;
+
+public:
+  PresumedLoc() : Filename(nullptr) {}
+  PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL)
+      : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {}
+
+  /// \brief Return true if this object is invalid or uninitialized.
+  ///
+  /// This occurs when created with invalid source locations or when walking
+  /// off the top of a \#include stack.
+  bool isInvalid() const { return Filename == nullptr; }
+  bool isValid() const { return Filename != nullptr; }
+
+  /// \brief Return the presumed filename of this location.
+  ///
+  /// This can be affected by \#line etc.
+  const char *getFilename() const {
+    assert(isValid());
+    return Filename;
+  }
+
+  /// \brief Return the presumed line number of this location.
+  ///
+  /// This can be affected by \#line etc.
+  unsigned getLine() const {
+    assert(isValid());
+    return Line;
+  }
+
+  /// \brief Return the presumed column number of this location.
+  ///
+  /// This cannot be affected by \#line, but is packaged here for convenience.
+  unsigned getColumn() const {
+    assert(isValid());
+    return Col;
+  }
+
+  /// \brief Return the presumed include location of this location.
+  ///
+  /// This can be affected by GNU linemarker directives.
+  SourceLocation getIncludeLoc() const {
+    assert(isValid());
+    return IncludeLoc;
+  }
+};
+
+class FileEntry;
+
 /// \brief A SourceLocation and its associated SourceManager.
 ///
 /// This is useful for argument passing to functions that expect both objects.
@@ -274,6 +335,7 @@
   explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
     : SourceLocation(Loc), SrcMgr(&SM) {}
 
+  bool hasManager() const { return SrcMgr != nullptr; }
   /// \pre This FullSourceLoc has an associated SourceManager.
   const SourceManager &getManager() const {
     assert(SrcMgr && "SourceManager is NULL.");
@@ -284,6 +346,13 @@
 
   FullSourceLoc getExpansionLoc() const;
   FullSourceLoc getSpellingLoc() const;
+  FullSourceLoc getFileLoc() const;
+  std::pair<FullSourceLoc, FullSourceLoc> getImmediateExpansionRange() const;
+  PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const;
+  bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const;
+  FullSourceLoc getImmediateMacroCallerLoc() const;
+  std::pair<FullSourceLoc, StringRef> getModuleImportLoc() const;
+  unsigned getFileOffset() const;
 
   unsigned getExpansionLineNumber(bool *Invalid = nullptr) const;
   unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const;
@@ -293,6 +362,12 @@
 
   const char *getCharacterData(bool *Invalid = nullptr) const;
 
+  unsigned getLineNumber(bool *Invalid = nullptr) const;
+  unsigned getColumnNumber(bool *Invalid = nullptr) const;
+
+  std::pair<FullSourceLoc, FullSourceLoc> getExpansionRange() const;
+
+  const FileEntry *getFileEntry() const;
 
   /// \brief Return a StringRef to the source buffer data for the
   /// specified FileID.
@@ -345,52 +420,60 @@
 
 };
 
-/// \brief Represents an unpacked "presumed" location which can be presented
-/// to the user.
-///
-/// A 'presumed' location can be modified by \#line and GNU line marker
-/// directives and is always the expansion point of a normal location.
-///
-/// You can get a PresumedLoc from a SourceLocation with SourceManager.
-class PresumedLoc {
-  const char *Filename;
-  unsigned Line, Col;
-  SourceLocation IncludeLoc;
+class UnifiedPLoc : public PresumedLoc {
+  const llvm::SourceMgr *SrcMgr = nullptr;
+  llvm::SMLoc Loc = llvm::SMLoc();
+
 public:
-  PresumedLoc() : Filename(nullptr) {}
-  PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL)
-    : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {
-  }
+  UnifiedPLoc() : PresumedLoc() {}
+  UnifiedPLoc(PresumedLoc Loc) : PresumedLoc(Loc) {}
+  explicit UnifiedPLoc(llvm::SMLoc Loc, const llvm::SourceMgr &SM)
+      : PresumedLoc(), SrcMgr(&SM), Loc(Loc) {}
+
+  bool isValid() const;
+  bool isInvalid() const;
+  unsigned getLine() const;
+  unsigned getColumn() const;
+  StringRef getFilename() const;
+
+  SourceLocation getIncludeLoc() const;
+};
 
-  /// \brief Return true if this object is invalid or uninitialized.
-  ///
-  /// This occurs when created with invalid source locations or when walking
-  /// off the top of a \#include stack.
-  bool isInvalid() const { return Filename == nullptr; }
-  bool isValid() const { return Filename != nullptr; }
+class UnifiedSourceLoc : public FullSourceLoc {
+  const llvm::SourceMgr *SrcMgr = nullptr;
+  llvm::SMLoc Loc = llvm::SMLoc();
 
-  /// \brief Return the presumed filename of this location.
-  ///
-  /// This can be affected by \#line etc.
-  const char *getFilename() const { assert(isValid()); return Filename; }
+public:
+  UnifiedSourceLoc() : FullSourceLoc() {}
+  UnifiedSourceLoc(FullSourceLoc Loc) : FullSourceLoc(Loc) {}
+  UnifiedSourceLoc(SourceLocation Loc, const SourceManager &SM)
+      : FullSourceLoc(Loc, SM) {}
+  explicit UnifiedSourceLoc(llvm::SMLoc Loc, const llvm::SourceMgr &SM)
+      : FullSourceLoc(), SrcMgr(&SM), Loc(Loc) {}
+
+  bool isValid() const;
+  UnifiedSourceLoc getFileLoc() const;
+  UnifiedPLoc getPresumedLoc(bool UseLineDirectives = true) const;
+  bool isLLVMLocation() const;
+  std::pair<FileID, unsigned> getDecomposedLoc() const;
+  StringRef getBufferData(bool *Invalid = nullptr) const;
+  unsigned getLineNumber() const;
+  unsigned getColumnNumber() const;
 
-  /// \brief Return the presumed line number of this location.
-  ///
-  /// This can be affected by \#line etc.
-  unsigned getLine() const { assert(isValid()); return Line; }
+  friend inline bool operator==(const UnifiedSourceLoc &LHS,
+                                const UnifiedSourceLoc &RHS) {
+    if (!LHS.SrcMgr && !RHS.SrcMgr)
+      return static_cast<FullSourceLoc>(LHS) == static_cast<FullSourceLoc>(RHS);
 
-  /// \brief Return the presumed column number of this location.
-  ///
-  /// This cannot be affected by \#line, but is packaged here for convenience.
-  unsigned getColumn() const { assert(isValid()); return Col; }
+    return LHS.Loc == RHS.Loc && LHS.SrcMgr == RHS.SrcMgr;
+  }
 
-  /// \brief Return the presumed include location of this location.
-  ///
-  /// This can be affected by GNU linemarker directives.
-  SourceLocation getIncludeLoc() const { assert(isValid()); return IncludeLoc; }
+  friend inline bool operator!=(const UnifiedSourceLoc &LHS,
+                                const UnifiedSourceLoc &RHS) {
+    return !(LHS == RHS);
+  }
 };
 
-
 }  // end namespace clang
 
 namespace llvm {
Index: include/clang/Basic/Diagnostic.h
===================================================================
--- include/clang/Basic/Diagnostic.h
+++ include/clang/Basic/Diagnostic.h
@@ -22,9 +22,10 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/iterator_range.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/SMLoc.h"
 #include <algorithm>
 #include <cassert>
 #include <cstdint>
@@ -36,6 +37,11 @@
 #include <utility>
 #include <vector>
 
+namespace llvm {
+
+class SourceMgr;
+}
+
 namespace clang {
 
 class DeclContext;
@@ -733,6 +739,8 @@
   /// which can be an invalid location if no position information is available.
   inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID);
   inline DiagnosticBuilder Report(unsigned DiagID);
+  inline DiagnosticBuilder Report(const llvm::SourceMgr *SM, llvm::SMLoc Loc,
+                                  unsigned DiagID);
 
   void Report(const StoredDiagnostic &storedDiag);
 
@@ -786,7 +794,7 @@
   friend class DiagnosticErrorTrap;
   
   /// \brief The location of the current diagnostic that is in flight.
-  SourceLocation CurDiagLoc;
+  UnifiedSourceLoc CurDiagLoc;
 
   /// \brief The ID of the current diagnostic that is in flight.
   ///
@@ -1180,7 +1188,12 @@
 inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
                                                    unsigned DiagID) {
   assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
-  CurDiagLoc = Loc;
+
+  if (!Loc.isValid() || !hasSourceManager())
+    CurDiagLoc = UnifiedSourceLoc();
+  else
+    CurDiagLoc = UnifiedSourceLoc(Loc, getSourceManager());
+
   CurDiagID = DiagID;
   FlagValue.clear();
   return DiagnosticBuilder(this);
@@ -1190,6 +1203,19 @@
   return Report(SourceLocation(), DiagID);
 }
 
+inline DiagnosticBuilder DiagnosticsEngine::Report(const llvm::SourceMgr *SM,
+                                                   llvm::SMLoc Loc,
+                                                   unsigned DiagID) {
+  auto DB = Report(DiagID);
+
+  if (!Loc.isValid() || !SM)
+    CurDiagLoc = UnifiedSourceLoc();
+  else
+    CurDiagLoc = UnifiedSourceLoc(Loc, *SM);
+
+  return DB;
+}
+
 //===----------------------------------------------------------------------===//
 // Diagnostic
 //===----------------------------------------------------------------------===//
@@ -1208,7 +1234,7 @@
 
   const DiagnosticsEngine *getDiags() const { return DiagObj; }
   unsigned getID() const { return DiagObj->CurDiagID; }
-  const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; }
+  const UnifiedSourceLoc &getLocation() const { return DiagObj->CurDiagLoc; }
   bool hasSourceManager() const { return DiagObj->hasSourceManager(); }
   SourceManager &getSourceManager() const { return DiagObj->getSourceManager();}
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to