dexonsmith created this revision.
dexonsmith added reviewers: arphaman, Bigcheese, rsmith.
Herald added subscribers: llvm-commits, ributzka, kadircet, jkorous, hiraditya.
Herald added a reviewer: martong.
Herald added a reviewer: shafik.
Herald added a project: LLVM.

Change the APIs in SourceManager returning `const MemoryBuffer*` to
return `Optional<MemoryBufferRef>` instead, and remove the `bool
*Invalid` flag from same.  This removes the need to create dummy
invalid buffers in SrcMgr::ContentCache and clarifies buffer ownership.

A few APIs changed, and a few were added.

- SrcMgr::ContentCache::getBuffer returns Optional<MemoryBufferRef>.
- SrcMgr::ContentCache::getBufferIdentifier returns Optional<StringRef>.
- SrcMgr::ContentCache::getBufferSize returns Optional<unsigned>.
- SourceManager::getMemoryBufferForFile returns Optional<MemoryBufferRef>.
- SourceManager::getBuffer returns Optional<MemoryBufferRef>.
- SourceManager::getBufferOrFake returns MemoryBufferRef, replacing None with 
fake data.
- SourceManager::getBufferIdentifier returns Optional<StringRef>.
- SourceManager::getBufferIdentifierOrEmpty returns StringRef, replacing None 
with `""`.
- SourceManager::getBufferDataOrNone returns Optional<StringRef>

SourceManager::getBufferData did not change to return
Optional<StringRef> because its usage is too pervasive.  A possible
follow-up would be to add SourceManager::getBufferDataOrFake (to match
the other APIs) and move components over but I'm not sure it's urgent.

Threading MemoryBufferRef (instead of `const MemoryBuffer*`) through had
a few small side effects:

- FrontendInputFile now stores a MemoryBufferRef.
- SourceManager::createFileID now takes a MemoryBufferRef.
- llvm::line_iterator now uses an Optional<StringRef>.
- MemoryBufferRef::operator== now exists and compares pointer identity for 
comparing Optional<MemoryBufferRef>.


https://reviews.llvm.org/D66782

Files:
  clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
  clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp
  clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
  clang-tools-extra/clangd/ClangdUnit.cpp
  clang-tools-extra/clangd/Format.cpp
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/modularize/PreprocessorTracker.cpp
  clang/include/clang/Basic/SourceManager.h
  clang/include/clang/Frontend/FrontendAction.h
  clang/include/clang/Frontend/FrontendOptions.h
  clang/include/clang/Frontend/PrecompiledPreamble.h
  clang/include/clang/Lex/Lexer.h
  clang/lib/ARCMigrate/Transforms.cpp
  clang/lib/AST/ASTImporter.cpp
  clang/lib/Basic/Diagnostic.cpp
  clang/lib/Basic/SourceLocation.cpp
  clang/lib/Basic/SourceManager.cpp
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/lib/CodeGen/CodeGenAction.cpp
  clang/lib/Format/FormatTokenLexer.cpp
  clang/lib/Frontend/ASTUnit.cpp
  clang/lib/Frontend/CompilerInstance.cpp
  clang/lib/Frontend/FrontendAction.cpp
  clang/lib/Frontend/FrontendActions.cpp
  clang/lib/Frontend/PrecompiledPreamble.cpp
  clang/lib/Frontend/Rewrite/HTMLPrint.cpp
  clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
  clang/lib/Frontend/Rewrite/RewriteMacros.cpp
  clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
  clang/lib/Frontend/Rewrite/RewriteObjC.cpp
  clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
  clang/lib/Lex/Lexer.cpp
  clang/lib/Lex/ModuleMap.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Preprocessor.cpp
  clang/lib/Rewrite/HTMLRewrite.cpp
  clang/lib/Rewrite/TokenRewriter.cpp
  clang/lib/Serialization/ASTWriter.cpp
  clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
  clang/lib/StaticAnalyzer/Core/BugReporter.cpp
  clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
  clang/lib/StaticAnalyzer/Core/IssueHash.cpp
  clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
  clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/lib/Tooling/Syntax/Tokens.cpp
  clang/tools/clang-diff/ClangDiff.cpp
  clang/tools/clang-import-test/clang-import-test.cpp
  clang/tools/libclang/CIndex.cpp
  llvm/include/llvm/Support/LineIterator.h
  llvm/include/llvm/Support/MemoryBuffer.h
  llvm/lib/Support/LineIterator.cpp

Index: llvm/lib/Support/LineIterator.cpp
===================================================================
--- llvm/lib/Support/LineIterator.cpp
+++ llvm/lib/Support/LineIterator.cpp
@@ -31,27 +31,37 @@
   return false;
 }
 
+line_iterator::line_iterator(const MemoryBufferRef &Buffer, bool SkipBlanks,
+                             char CommentMarker)
+    : line_iterator(StringRef(Buffer.getBufferStart(), Buffer.getBufferSize()),
+                    SkipBlanks, CommentMarker) {}
+
 line_iterator::line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks,
                              char CommentMarker)
-    : Buffer(Buffer.getBufferSize() ? &Buffer : nullptr),
+    : line_iterator(StringRef(Buffer.getBufferStart(), Buffer.getBufferSize()),
+                    SkipBlanks, CommentMarker) {}
+
+line_iterator::line_iterator(StringRef Buffer, bool SkipBlanks,
+                             char CommentMarker)
+    : Buffer(Buffer.empty() ? Optional<StringRef>(None) : Buffer),
       CommentMarker(CommentMarker), SkipBlanks(SkipBlanks), LineNumber(1),
-      CurrentLine(Buffer.getBufferSize() ? Buffer.getBufferStart() : nullptr,
-                  0) {
+      CurrentLine(Buffer.empty() ? nullptr : Buffer.begin(), 0) {
   // Ensure that if we are constructed on a non-empty memory buffer that it is
   // a null terminated buffer.
-  if (Buffer.getBufferSize()) {
-    assert(Buffer.getBufferEnd()[0] == '\0');
-    // Make sure we don't skip a leading newline if we're keeping blanks
-    if (SkipBlanks || !isAtLineEnd(Buffer.getBufferStart()))
-      advance();
-  }
+  if (Buffer.empty())
+    return;
+
+  assert(Buffer.end()[0] == '\0');
+  // Make sure we don't skip a leading newline if we're keeping blanks
+  if (SkipBlanks || !isAtLineEnd(Buffer.begin()))
+    advance();
 }
 
 void line_iterator::advance() {
   assert(Buffer && "Cannot advance past the end!");
 
   const char *Pos = CurrentLine.end();
-  assert(Pos == Buffer->getBufferStart() || isAtLineEnd(Pos) || *Pos == '\0');
+  assert(Pos == Buffer->begin() || isAtLineEnd(Pos) || *Pos == '\0');
 
   if (skipIfAtLineEnd(Pos))
     ++LineNumber;
@@ -78,7 +88,7 @@
 
   if (*Pos == '\0') {
     // We've hit the end of the buffer, reset ourselves to the end state.
-    Buffer = nullptr;
+    Buffer = None;
     CurrentLine = StringRef();
     return;
   }
Index: llvm/include/llvm/Support/MemoryBuffer.h
===================================================================
--- llvm/include/llvm/Support/MemoryBuffer.h
+++ llvm/include/llvm/Support/MemoryBuffer.h
@@ -276,6 +276,15 @@
   const char *getBufferStart() const { return Buffer.begin(); }
   const char *getBufferEnd() const { return Buffer.end(); }
   size_t getBufferSize() const { return Buffer.size(); }
+
+  /// Check if two memory buffer refs have the same pointer identity.
+  friend bool operator==(const MemoryBufferRef &LHS,
+                         const MemoryBufferRef &RHS) {
+    return LHS.Buffer.begin() == RHS.Buffer.begin() &&
+           LHS.Buffer.end() == RHS.Buffer.end() &&
+           LHS.Identifier.begin() == RHS.Identifier.begin() &&
+           LHS.Identifier.end() == RHS.Identifier.end();
+  }
 };
 
 // Create wrappers for C Binding types (see CBindingWrapping.h).
Index: llvm/include/llvm/Support/LineIterator.h
===================================================================
--- llvm/include/llvm/Support/LineIterator.h
+++ llvm/include/llvm/Support/LineIterator.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_SUPPORT_LINEITERATOR_H
 #define LLVM_SUPPORT_LINEITERATOR_H
 
+#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/DataTypes.h"
 #include <iterator>
@@ -16,6 +17,7 @@
 namespace llvm {
 
 class MemoryBuffer;
+class MemoryBufferRef;
 
 /// A forward iterator which reads text lines from a buffer.
 ///
@@ -30,16 +32,22 @@
 /// Note that this iterator requires the buffer to be nul terminated.
 class line_iterator
     : public std::iterator<std::forward_iterator_tag, StringRef> {
-  const MemoryBuffer *Buffer;
+  Optional<StringRef> Buffer;
   char CommentMarker;
   bool SkipBlanks;
 
   unsigned LineNumber;
   StringRef CurrentLine;
 
+  explicit line_iterator(StringRef Buffer, bool SkipBlanks, char CommentMarker);
+
 public:
   /// Default construct an "end" iterator.
-  line_iterator() : Buffer(nullptr) {}
+  line_iterator() = default;
+
+  /// Construct a new iterator around an unowned memory buffer.
+  explicit line_iterator(const MemoryBufferRef &Buffer, bool SkipBlanks = true,
+                         char CommentMarker = '\0');
 
   /// Construct a new iterator around some memory buffer.
   explicit line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks = true,
@@ -70,8 +78,14 @@
   const StringRef *operator->() const { return &CurrentLine; }
 
   friend bool operator==(const line_iterator &LHS, const line_iterator &RHS) {
-    return LHS.Buffer == RHS.Buffer &&
-           LHS.CurrentLine.begin() == RHS.CurrentLine.begin();
+    if (LHS.Buffer && RHS.Buffer) {
+      // Use pointer identity to compare Buffer.
+      if (LHS.Buffer->begin() != RHS.Buffer->begin())
+        return false;
+    } else if (LHS.Buffer || RHS.Buffer) {
+      return false;
+    }
+    return LHS.CurrentLine.begin() == RHS.CurrentLine.begin();
   }
 
   friend bool operator!=(const line_iterator &LHS, const line_iterator &RHS) {
Index: clang/tools/libclang/CIndex.cpp
===================================================================
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -4250,9 +4250,8 @@
 
   const SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager();
   FileID fid = SM.translateFile(static_cast<FileEntry *>(file));
-  bool Invalid = true;
-  const llvm::MemoryBuffer *buf = SM.getBuffer(fid, &Invalid);
-  if (Invalid) {
+  llvm::Optional<llvm::MemoryBufferRef> buf = SM.getBuffer(fid);
+  if (!buf) {
     if (size)
       *size = 0;
     return nullptr;
Index: clang/tools/clang-import-test/clang-import-test.cpp
===================================================================
--- clang/tools/clang-import-test/clang-import-test.cpp
+++ clang/tools/clang-import-test/clang-import-test.cpp
@@ -102,20 +102,19 @@
     unsigned LocColumn =
         SM.getSpellingColumnNumber(Loc, /*Invalid=*/nullptr) - 1;
     FileID FID = SM.getFileID(Loc);
-    const llvm::MemoryBuffer *Buffer =
-        SM.getBuffer(FID, Loc, /*Invalid=*/nullptr);
+    llvm::MemoryBufferRef Buffer = SM.getBufferOrFake(FID, Loc);
 
-    assert(LocData >= Buffer->getBufferStart() &&
-           LocData < Buffer->getBufferEnd());
+    assert(LocData >= Buffer.getBufferStart() &&
+           LocData < Buffer.getBufferEnd());
 
     const char *LineBegin = LocData - LocColumn;
 
-    assert(LineBegin >= Buffer->getBufferStart());
+    assert(LineBegin >= Buffer.getBufferStart());
 
     const char *LineEnd = nullptr;
 
     for (LineEnd = LineBegin; *LineEnd != '\n' && *LineEnd != '\r' &&
-                              LineEnd < Buffer->getBufferEnd();
+                              LineEnd < Buffer.getBufferEnd();
          ++LineEnd)
       ;
 
Index: clang/tools/clang-diff/ClangDiff.cpp
===================================================================
--- clang/tools/clang-diff/ClangDiff.cpp
+++ clang/tools/clang-diff/ClangDiff.cpp
@@ -284,7 +284,7 @@
   unsigned Begin, End;
   std::tie(Begin, End) = Tree.getSourceRangeOffsets(Node);
   const SourceManager &SrcMgr = Tree.getASTContext().getSourceManager();
-  auto Code = SrcMgr.getBuffer(SrcMgr.getMainFileID())->getBuffer();
+  auto Code = SrcMgr.getBufferOrFake(SrcMgr.getMainFileID()).getBuffer();
   for (; Offset < Begin; ++Offset)
     printHtml(OS, Code[Offset]);
   OS << "<span id='" << MyTag << Id << "' "
Index: clang/lib/Tooling/Syntax/Tokens.cpp
===================================================================
--- clang/lib/Tooling/Syntax/Tokens.cpp
+++ clang/lib/Tooling/Syntax/Tokens.cpp
@@ -262,7 +262,7 @@
     Tokens.push_back(syntax::Token(T));
   };
 
-  Lexer L(FID, SM.getBuffer(FID), SM, LO);
+  Lexer L(FID, SM.getBufferOrFake(FID), SM, LO);
 
   clang::Token T;
   while (!L.LexFromRawLexer(T))
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===================================================================
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -41,7 +41,7 @@
         GetOffsetAfterSequence) {
   SourceManagerForFile VirtualSM(FileName, Code);
   SourceManager &SM = VirtualSM.get();
-  Lexer Lex(SM.getMainFileID(), SM.getBuffer(SM.getMainFileID()), SM,
+  Lexer Lex(SM.getMainFileID(), SM.getBufferOrFake(SM.getMainFileID()), SM,
             createLangOpts());
   Token Tok;
   // Get the first token.
Index: clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -569,7 +569,7 @@
 static bool isBisonFile(ASTContext &C) {
   const SourceManager &SM = C.getSourceManager();
   FileID FID = SM.getMainFileID();
-  StringRef Buffer = SM.getBuffer(FID)->getBuffer();
+  StringRef Buffer = SM.getBufferOrFake(FID).getBuffer();
   if (Buffer.startswith("/* A Bison parser, made by"))
     return true;
   return false;
Index: clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -1011,11 +1011,11 @@
   // First, we create a Lexer to lex *at the expansion location* the tokens
   // referring to the macro's name and its arguments.
   std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(ExpanLoc);
-  const llvm::MemoryBuffer *MB = SM.getBuffer(LocInfo.first);
-  const char *MacroNameTokenPos = MB->getBufferStart() + LocInfo.second;
+  llvm::MemoryBufferRef MB = SM.getBufferOrFake(LocInfo.first);
+  const char *MacroNameTokenPos = MB.getBufferStart() + LocInfo.second;
 
   Lexer RawLexer(SM.getLocForStartOfFile(LocInfo.first), LangOpts,
-                 MB->getBufferStart(), MacroNameTokenPos, MB->getBufferEnd());
+                 MB.getBufferStart(), MacroNameTokenPos, MB.getBufferEnd());
 
   // Acquire the macro's name.
   Token TheTok;
Index: clang/lib/StaticAnalyzer/Core/IssueHash.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/IssueHash.cpp
+++ clang/lib/StaticAnalyzer/Core/IssueHash.cpp
@@ -120,7 +120,8 @@
   return "";
 }
 
-static StringRef GetNthLineOfFile(const llvm::MemoryBuffer *Buffer, int Line) {
+static StringRef GetNthLineOfFile(llvm::Optional<llvm::MemoryBufferRef> Buffer,
+                                  int Line) {
   if (!Buffer)
     return "";
 
@@ -135,7 +136,7 @@
                                  const LangOptions &LangOpts) {
   static StringRef Whitespaces = " \t\n";
 
-  StringRef Str = GetNthLineOfFile(SM.getBuffer(L.getFileID(), L),
+  StringRef Str = GetNthLineOfFile(SM.getBufferOrFake(L.getFileID(), L),
                                    L.getExpansionLineNumber());
   StringRef::size_type col = Str.find_first_not_of(Whitespaces);
   if (col == StringRef::npos)
@@ -144,7 +145,7 @@
     col++;
   SourceLocation StartOfLine =
       SM.translateLineCol(SM.getFileID(L), L.getExpansionLineNumber(), col);
-  const llvm::MemoryBuffer *Buffer =
+  llvm::Optional<llvm::MemoryBufferRef> Buffer =
       SM.getBuffer(SM.getFileID(StartOfLine), StartOfLine);
   if (!Buffer)
     return {};
Index: clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -749,8 +749,8 @@
   if (LPosInfo.first != BugFileID)
     return;
 
-  const llvm::MemoryBuffer *Buf = SM.getBuffer(LPosInfo.first);
-  const char* FileStart = Buf->getBufferStart();
+  llvm::MemoryBufferRef Buf = SM.getBufferOrFake(LPosInfo.first);
+  const char *FileStart = Buf.getBufferStart();
 
   // Compute the column number.  Rewind from the current position to the start
   // of the line.
@@ -760,7 +760,7 @@
 
   // Compute LineEnd.
   const char *LineEnd = TokInstantiationPtr;
-  const char* FileEnd = Buf->getBufferEnd();
+  const char *FileEnd = Buf.getBufferEnd();
   while (*LineEnd != '\n' && LineEnd != FileEnd)
     ++LineEnd;
 
Index: clang/lib/StaticAnalyzer/Core/BugReporter.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1511,9 +1511,8 @@
   if (FID != SM.getFileID(ExpansionRange.getEnd()))
     return None;
 
-  bool Invalid;
-  const llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, &Invalid);
-  if (Invalid)
+  llvm::Optional<llvm::MemoryBufferRef> Buffer = SM.getBuffer(FID);
+  if (!Buffer)
     return None;
 
   unsigned BeginOffset = SM.getFileOffset(ExpansionRange.getBegin());
Index: clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
@@ -1138,10 +1138,9 @@
     SE = Mgr.getSourceManager().getSLocEntry(SLInfo.first);
   }
 
-  bool Invalid = false;
-  const llvm::MemoryBuffer *BF =
-      Mgr.getSourceManager().getBuffer(SLInfo.first, SL, &Invalid);
-  if (Invalid)
+  llvm::Optional<llvm::MemoryBufferRef> BF =
+      Mgr.getSourceManager().getBuffer(SLInfo.first, SL);
+  if (!BF)
     return;
 
   Lexer TheLexer(SL, LangOptions(), BF->getBufferStart(),
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -2315,9 +2315,9 @@
         // We add one to the size so that we capture the trailing NULL
         // that is required by llvm::MemoryBuffer::getMemBuffer (on
         // the reader side).
-        const llvm::MemoryBuffer *Buffer =
+        llvm::Optional<llvm::MemoryBufferRef> Buffer =
             Content->getBuffer(PP.getDiagnostics(), PP.getFileManager());
-        StringRef Name = Buffer->getBufferIdentifier();
+        StringRef Name = Buffer ? Buffer->getBufferIdentifier() : "";
         Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,
                                   StringRef(Name.data(), Name.size() + 1));
         EmitBlob = true;
@@ -2329,8 +2329,10 @@
       if (EmitBlob) {
         // Include the implicit terminating null character in the on-disk buffer
         // if we're writing it uncompressed.
-        const llvm::MemoryBuffer *Buffer =
+        llvm::Optional<llvm::MemoryBufferRef> Buffer =
             Content->getBuffer(PP.getDiagnostics(), PP.getFileManager());
+        if (!Buffer)
+          Buffer = llvm::MemoryBufferRef("<<<INVALID BUFFER>>>", "");
         StringRef Blob(Buffer->getBufferStart(), Buffer->getBufferSize() + 1);
         emitBlob(Stream, Blob, SLocBufferBlobCompressedAbbrv,
                  SLocBufferBlobAbbrv);
Index: clang/lib/Rewrite/TokenRewriter.cpp
===================================================================
--- clang/lib/Rewrite/TokenRewriter.cpp
+++ clang/lib/Rewrite/TokenRewriter.cpp
@@ -28,7 +28,7 @@
   ScratchBuf.reset(new ScratchBuffer(SM));
 
   // Create a lexer to lex all the tokens of the main file in raw mode.
-  const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
+  llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(FID);
   Lexer RawLex(FID, FromFile, SM, LangOpts);
 
   // Return all comments and whitespace as tokens.
Index: clang/lib/Rewrite/HTMLRewrite.cpp
===================================================================
--- clang/lib/Rewrite/HTMLRewrite.cpp
+++ clang/lib/Rewrite/HTMLRewrite.cpp
@@ -107,9 +107,9 @@
 void html::EscapeText(Rewriter &R, FileID FID,
                       bool EscapeSpaces, bool ReplaceTabs) {
 
-  const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
-  const char* C = Buf->getBufferStart();
-  const char* FileEnd = Buf->getBufferEnd();
+  llvm::MemoryBufferRef Buf = R.getSourceMgr().getBufferOrFake(FID);
+  const char *C = Buf.getBufferStart();
+  const char *FileEnd = Buf.getBufferEnd();
 
   assert (C <= FileEnd);
 
@@ -226,9 +226,9 @@
 
 void html::AddLineNumbers(Rewriter& R, FileID FID) {
 
-  const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
-  const char* FileBeg = Buf->getBufferStart();
-  const char* FileEnd = Buf->getBufferEnd();
+  llvm::MemoryBufferRef Buf = R.getSourceMgr().getBufferOrFake(FID);
+  const char *FileBeg = Buf.getBufferStart();
+  const char *FileEnd = Buf.getBufferEnd();
   const char* C = FileBeg;
   RewriteBuffer &RB = R.getEditBuffer(FID);
 
@@ -274,9 +274,9 @@
 void html::AddHeaderFooterInternalBuiltinCSS(Rewriter &R, FileID FID,
                                              StringRef title) {
 
-  const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
-  const char* FileStart = Buf->getBufferStart();
-  const char* FileEnd = Buf->getBufferEnd();
+  llvm::MemoryBufferRef Buf = R.getSourceMgr().getBufferOrFake(FID);
+  const char *FileStart = Buf.getBufferStart();
+  const char *FileEnd = Buf.getBufferEnd();
 
   SourceLocation StartLoc = R.getSourceMgr().getLocForStartOfFile(FID);
   SourceLocation EndLoc = StartLoc.getLocWithOffset(FileEnd-FileStart);
@@ -445,7 +445,7 @@
   RewriteBuffer &RB = R.getEditBuffer(FID);
 
   const SourceManager &SM = PP.getSourceManager();
-  const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
+  llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(FID);
   Lexer L(FID, FromFile, SM, PP.getLangOpts());
   const char *BufferStart = L.getBuffer().data();
 
@@ -536,7 +536,7 @@
   const SourceManager &SM = PP.getSourceManager();
   std::vector<Token> TokenStream;
 
-  const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
+  llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(FID);
   Lexer L(FID, FromFile, SM, PP.getLangOpts());
 
   // Lex all the tokens in raw mode, to avoid entering #includes or expanding
Index: clang/lib/Lex/Preprocessor.cpp
===================================================================
--- clang/lib/Lex/Preprocessor.cpp
+++ clang/lib/Lex/Preprocessor.cpp
@@ -388,9 +388,9 @@
   using llvm::MemoryBuffer;
 
   // Load the actual file's contents.
-  bool Invalid = false;
-  const MemoryBuffer *Buffer = SourceMgr.getMemoryBufferForFile(File, &Invalid);
-  if (Invalid)
+  llvm::Optional<llvm::MemoryBufferRef> Buffer =
+      SourceMgr.getMemoryBufferForFile(File);
+  if (!Buffer)
     return true;
 
   // Find the byte position of the truncation point.
Index: clang/lib/Lex/PPLexerChange.cpp
===================================================================
--- clang/lib/Lex/PPLexerChange.cpp
+++ clang/lib/Lex/PPLexerChange.cpp
@@ -75,10 +75,9 @@
     MaxIncludeStackDepth = IncludeMacroStack.size();
 
   // Get the MemoryBuffer for this FID, if it fails, we fail.
-  bool Invalid = false;
-  const llvm::MemoryBuffer *InputFile =
-    getSourceManager().getBuffer(FID, Loc, &Invalid);
-  if (Invalid) {
+  llvm::Optional<llvm::MemoryBufferRef> InputFile =
+      getSourceManager().getBuffer(FID, Loc);
+  if (!InputFile) {
     SourceLocation FileStart = SourceMgr.getLocForStartOfFile(FID);
     Diag(Loc, diag::err_pp_error_opening_file)
       << std::string(SourceMgr.getBufferName(FileStart)) << "";
@@ -92,7 +91,7 @@
         CodeCompletionFileLoc.getLocWithOffset(CodeCompletionOffset);
   }
 
-  EnterSourceFileWithLexer(new Lexer(FID, InputFile, *this), CurDir);
+  EnterSourceFileWithLexer(new Lexer(FID, *InputFile, *this), CurDir);
   return false;
 }
 
Index: clang/lib/Lex/ModuleMap.cpp
===================================================================
--- clang/lib/Lex/ModuleMap.cpp
+++ clang/lib/Lex/ModuleMap.cpp
@@ -2979,7 +2979,7 @@
   }
 
   assert(Target && "Missing target information");
-  const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
+  llvm::Optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBuffer(ID);
   if (!Buffer)
     return ParsedModuleMap[File] = true;
   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
Index: clang/lib/Lex/Lexer.cpp
===================================================================
--- clang/lib/Lex/Lexer.cpp
+++ clang/lib/Lex/Lexer.cpp
@@ -130,12 +130,13 @@
 /// with the specified preprocessor managing the lexing process.  This lexer
 /// assumes that the associated file buffer and Preprocessor objects will
 /// outlive it, so it doesn't take ownership of either of them.
-Lexer::Lexer(FileID FID, const llvm::MemoryBuffer *InputFile, Preprocessor &PP)
+Lexer::Lexer(FileID FID, const llvm::MemoryBufferRef &InputFile,
+             Preprocessor &PP)
     : PreprocessorLexer(&PP, FID),
       FileLoc(PP.getSourceManager().getLocForStartOfFile(FID)),
       LangOpts(PP.getLangOpts()) {
-  InitLexer(InputFile->getBufferStart(), InputFile->getBufferStart(),
-            InputFile->getBufferEnd());
+  InitLexer(InputFile.getBufferStart(), InputFile.getBufferStart(),
+            InputFile.getBufferEnd());
 
   resetExtendedTokenMode();
 }
@@ -155,10 +156,10 @@
 /// Lexer constructor - Create a new raw lexer object.  This object is only
 /// suitable for calls to 'LexFromRawLexer'.  This lexer assumes that the text
 /// range will outlive it, so it doesn't take ownership of it.
-Lexer::Lexer(FileID FID, const llvm::MemoryBuffer *FromFile,
+Lexer::Lexer(FileID FID, const llvm::MemoryBufferRef &FromFile,
              const SourceManager &SM, const LangOptions &langOpts)
-    : Lexer(SM.getLocForStartOfFile(FID), langOpts, FromFile->getBufferStart(),
-            FromFile->getBufferStart(), FromFile->getBufferEnd()) {}
+    : Lexer(SM.getLocForStartOfFile(FID), langOpts, FromFile.getBufferStart(),
+            FromFile.getBufferStart(), FromFile.getBufferEnd()) {}
 
 void Lexer::resetExtendedTokenMode() {
   assert(PP && "Cannot reset token mode without a preprocessor");
@@ -191,7 +192,7 @@
 
   // Create the lexer as if we were going to lex the file normally.
   FileID SpellingFID = SM.getFileID(SpellingLoc);
-  const llvm::MemoryBuffer *InputFile = SM.getBuffer(SpellingFID);
+  llvm::MemoryBufferRef InputFile = SM.getBufferOrFake(SpellingFID);
   Lexer *L = new Lexer(SpellingFID, InputFile, PP);
 
   // Now that the lexer is created, change the start/end locations so that we
Index: clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
===================================================================
--- clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -809,7 +809,7 @@
     return false;
 
   // Create a lexer to lex all the tokens of the main file in raw mode.
-  const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
+  llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(FID);
   Lexer RawLex(FID, FromFile, SM, LangOpts);
 
   // Return comments as tokens, this is how we find expected diagnostics.
Index: clang/lib/Frontend/Rewrite/RewriteObjC.cpp
===================================================================
--- clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -630,9 +630,9 @@
 
   // Get the ID and start/end of the main file.
   MainFileID = SM->getMainFileID();
-  const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
-  MainFileStart = MainBuf->getBufferStart();
-  MainFileEnd = MainBuf->getBufferEnd();
+  llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID);
+  MainFileStart = MainBuf.getBufferStart();
+  MainFileEnd = MainBuf.getBufferEnd();
 
   Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
 }
Index: clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
===================================================================
--- clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -701,9 +701,9 @@
 
   // Get the ID and start/end of the main file.
   MainFileID = SM->getMainFileID();
-  const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
-  MainFileStart = MainBuf->getBufferStart();
-  MainFileEnd = MainBuf->getBufferEnd();
+  llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID);
+  MainFileStart = MainBuf.getBufferStart();
+  MainFileEnd = MainBuf.getBufferEnd();
 
   Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
 }
Index: clang/lib/Frontend/Rewrite/RewriteMacros.cpp
===================================================================
--- clang/lib/Frontend/Rewrite/RewriteMacros.cpp
+++ clang/lib/Frontend/Rewrite/RewriteMacros.cpp
@@ -64,7 +64,7 @@
 
   // Create a lexer to lex all the tokens of the main file in raw mode.  Even
   // though it is in raw mode, it will not return comments.
-  const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
+  llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(SM.getMainFileID());
   Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOpts());
 
   // Switch on comment lexing because we really do want them.
Index: clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
===================================================================
--- clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -40,7 +40,7 @@
   SourceManager &SM; ///< Used to read and manage source files.
   raw_ostream &OS; ///< The destination stream for rewritten contents.
   StringRef MainEOL; ///< The line ending marker to use.
-  const llvm::MemoryBuffer *PredefinesBuffer; ///< The preprocessor predefines.
+  Optional<MemoryBufferRef> PredefinesBuffer; ///< The preprocessor predefines.
   bool ShowLineMarkers; ///< Show #line markers.
   bool UseLineDirectives; ///< Use of line directives or line markers.
   /// Tracks where inclusions that change the file are found.
@@ -57,7 +57,7 @@
                     bool UseLineDirectives);
   void Process(FileID FileId, SrcMgr::CharacteristicKind FileType,
                const DirectoryLookup *DirLookup);
-  void setPredefinesBuffer(const llvm::MemoryBuffer *Buf) {
+  void setPredefinesBuffer(Optional<MemoryBufferRef> Buf) {
     PredefinesBuffer = Buf;
   }
   void detectMainFileEOL();
@@ -82,12 +82,11 @@
                      SrcMgr::CharacteristicKind FileType,
                      StringRef Extra = StringRef());
   void WriteImplicitModuleImport(const Module *Mod);
-  void OutputContentUpTo(const MemoryBuffer &FromFile,
-                         unsigned &WriteFrom, unsigned WriteTo,
-                         StringRef EOL, int &lines,
+  void OutputContentUpTo(MemoryBufferRef FromFile, unsigned &WriteFrom,
+                         unsigned WriteTo, StringRef EOL, int &lines,
                          bool EnsureNewline);
   void CommentOutDirective(Lexer &DirectivesLex, const Token &StartToken,
-                           const MemoryBuffer &FromFile, StringRef EOL,
+                           MemoryBufferRef FromFile, StringRef EOL,
                            unsigned &NextToWrite, int &Lines);
   bool HandleHasInclude(FileID FileId, Lexer &RawLex,
                         const DirectoryLookup *Lookup, Token &Tok,
@@ -105,8 +104,7 @@
                                      bool ShowLineMarkers,
                                      bool UseLineDirectives)
     : PP(PP), SM(PP.getSourceManager()), OS(OS), MainEOL("\n"),
-      PredefinesBuffer(nullptr), ShowLineMarkers(ShowLineMarkers),
-      UseLineDirectives(UseLineDirectives),
+      ShowLineMarkers(ShowLineMarkers), UseLineDirectives(UseLineDirectives),
       LastInclusionLocation(SourceLocation()) {}
 
 /// Write appropriate line information as either #line directives or GNU line
@@ -235,7 +233,7 @@
 
 /// Detect the likely line ending style of \p FromFile by examining the first
 /// newline found within it.
-static StringRef DetectEOL(const MemoryBuffer &FromFile) {
+static StringRef DetectEOL(MemoryBufferRef FromFile) {
   // Detect what line endings the file uses, so that added content does not mix
   // the style. We need to check for "\r\n" first because "\n\r" will match
   // "\r\n\r\n".
@@ -250,23 +248,21 @@
 }
 
 void InclusionRewriter::detectMainFileEOL() {
-  bool Invalid;
-  const MemoryBuffer &FromFile = *SM.getBuffer(SM.getMainFileID(), &Invalid);
-  assert(!Invalid);
-  if (Invalid)
+  Optional<MemoryBufferRef> FromFile = SM.getBuffer(SM.getMainFileID());
+  if (!FromFile)
     return; // Should never happen, but whatever.
-  MainEOL = DetectEOL(FromFile);
+  MainEOL = DetectEOL(*FromFile);
 }
 
 /// Writes out bytes from \p FromFile, starting at \p NextToWrite and ending at
 /// \p WriteTo - 1.
-void InclusionRewriter::OutputContentUpTo(const MemoryBuffer &FromFile,
+void InclusionRewriter::OutputContentUpTo(MemoryBufferRef FromFile,
                                           unsigned &WriteFrom, unsigned WriteTo,
                                           StringRef LocalEOL, int &Line,
                                           bool EnsureNewline) {
   if (WriteTo <= WriteFrom)
     return;
-  if (&FromFile == PredefinesBuffer) {
+  if (FromFile == PredefinesBuffer) {
     // Ignore the #defines of the predefines buffer.
     WriteFrom = WriteTo;
     return;
@@ -313,7 +309,7 @@
 /// through the \p FromFile buffer.
 void InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex,
                                             const Token &StartToken,
-                                            const MemoryBuffer &FromFile,
+                                            MemoryBufferRef FromFile,
                                             StringRef LocalEOL,
                                             unsigned &NextToWrite, int &Line) {
   OutputContentUpTo(FromFile, NextToWrite,
@@ -323,7 +319,7 @@
   do {
     DirectiveLex.LexFromRawLexer(DirectiveToken);
   } while (!DirectiveToken.is(tok::eod) && DirectiveToken.isNot(tok::eof));
-  if (&FromFile == PredefinesBuffer) {
+  if (FromFile == PredefinesBuffer) {
     // OutputContentUpTo() would not output anything anyway.
     return;
   }
@@ -425,11 +421,11 @@
 void InclusionRewriter::Process(FileID FileId,
                                 SrcMgr::CharacteristicKind FileType,
                                 const DirectoryLookup *DirLookup) {
-  bool Invalid;
-  const MemoryBuffer &FromFile = *SM.getBuffer(FileId, &Invalid);
-  assert(!Invalid && "Attempting to process invalid inclusion");
+  Optional<MemoryBufferRef> MaybeFromFile = SM.getBuffer(FileId);
+  assert(MaybeFromFile && "Attempting to process invalid inclusion");
+  auto FromFile = *MaybeFromFile;
   StringRef FileName = FromFile.getBufferIdentifier();
-  Lexer RawLex(FileId, &FromFile, PP.getSourceManager(), PP.getLangOpts());
+  Lexer RawLex(FileId, FromFile, PP.getSourceManager(), PP.getLangOpts());
   RawLex.SetCommentRetentionState(false);
 
   StringRef LocalEOL = DetectEOL(FromFile);
Index: clang/lib/Frontend/Rewrite/HTMLPrint.cpp
===================================================================
--- clang/lib/Frontend/Rewrite/HTMLPrint.cpp
+++ clang/lib/Frontend/Rewrite/HTMLPrint.cpp
@@ -70,7 +70,7 @@
   if (Entry)
     Name = Entry->getName();
   else
-    Name = R.getSourceMgr().getBuffer(FID)->getBufferIdentifier();
+    Name = R.getSourceMgr().getBufferOrFake(FID).getBufferIdentifier();
 
   html::AddLineNumbers(R, FID);
   html::AddHeaderFooterInternalBuiltinCSS(R, FID, Name);
Index: clang/lib/Frontend/PrecompiledPreamble.cpp
===================================================================
--- clang/lib/Frontend/PrecompiledPreamble.cpp
+++ clang/lib/Frontend/PrecompiledPreamble.cpp
@@ -379,7 +379,8 @@
           PrecompiledPreamble::PreambleFileHash::createForFile(File->getSize(),
                                                                ModTime);
     } else {
-      const llvm::MemoryBuffer *Buffer = SourceMgr.getMemoryBufferForFile(File);
+      llvm::Optional<llvm::MemoryBufferRef> Buffer =
+          SourceMgr.getMemoryBufferForFile(File);
       FilesInPreamble[File->getName()] =
           PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(Buffer);
     }
@@ -460,7 +461,9 @@
   llvm::StringMap<PreambleFileHash> OverridenFileBuffers;
   for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {
     const PrecompiledPreamble::PreambleFileHash PreambleHash =
-        PreambleFileHash::createForMemoryBuffer(RB.second);
+        PreambleFileHash::createForMemoryBuffer(
+            RB.second ? RB.second->getMemBufferRef()
+                      : llvm::Optional<llvm::MemoryBufferRef>(None));
     llvm::vfs::Status Status;
     if (moveOnNoError(VFS->status(RB.first), Status))
       OverriddenFiles[Status.getUniqueID()] = PreambleHash;
@@ -688,13 +691,13 @@
 
 PrecompiledPreamble::PreambleFileHash
 PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(
-    const llvm::MemoryBuffer *Buffer) {
+    llvm::Optional<llvm::MemoryBufferRef> Buffer) {
   PreambleFileHash Result;
-  Result.Size = Buffer->getBufferSize();
+  Result.Size = Buffer ? Buffer->getBufferSize() : 0;
   Result.ModTime = 0;
 
   llvm::MD5 MD5Ctx;
-  MD5Ctx.update(Buffer->getBuffer().data());
+  MD5Ctx.update(Buffer ? Buffer->getBuffer().data() : nullptr);
   MD5Ctx.final(Result.MD5);
 
   return Result;
Index: clang/lib/Frontend/FrontendActions.cpp
===================================================================
--- clang/lib/Frontend/FrontendActions.cpp
+++ clang/lib/Frontend/FrontendActions.cpp
@@ -259,7 +259,7 @@
     if (FIF.getKind().getFormat() != InputKind::Source || !FIF.isFile()) {
       CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
           << (FIF.isFile() ? FIF.getFile()
-                           : FIF.getBuffer()->getBufferIdentifier());
+                           : FIF.getBuffer().getBufferIdentifier());
       return true;
     }
 
@@ -273,7 +273,8 @@
 
   // Set that buffer up as our "real" input.
   Inputs.clear();
-  Inputs.push_back(FrontendInputFile(Buffer.get(), Kind, /*IsSystem*/false));
+  Inputs.push_back(
+      FrontendInputFile(Buffer->getMemBufferRef(), Kind, /*IsSystem*/ false));
 
   return GenerateModuleAction::PrepareToExecuteAction(CI);
 }
@@ -727,8 +728,8 @@
   SourceManager &SM = PP.getSourceManager();
 
   // Start lexing the specified input file.
-  const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
-  Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOpts());
+  Lexer RawLex(SM.getMainFileID(), SM.getBufferOrFake(SM.getMainFileID()), SM,
+               PP.getLangOpts());
   RawLex.SetKeepWhitespaceMode(true);
 
   Token RawTok;
@@ -782,11 +783,9 @@
   // concern, so if we scan for too long, we'll just assume the file should
   // be opened in binary mode.
   bool BinaryMode = true;
-  bool InvalidFile = false;
   const SourceManager& SM = CI.getSourceManager();
-  const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getMainFileID(),
-                                                     &InvalidFile);
-  if (!InvalidFile) {
+  if (llvm::Optional<llvm::MemoryBufferRef> Buffer =
+          SM.getBuffer(SM.getMainFileID())) {
     const char *cur = Buffer->getBufferStart();
     const char *end = Buffer->getBufferEnd();
     const char *next = (cur != end) ? cur + 1 : end;
@@ -914,12 +913,12 @@
 void PrintDependencyDirectivesSourceMinimizerAction::ExecuteAction() {
   CompilerInstance &CI = getCompilerInstance();
   SourceManager &SM = CI.getPreprocessor().getSourceManager();
-  const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
+  llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(SM.getMainFileID());
 
   llvm::SmallString<1024> Output;
   llvm::SmallVector<minimize_source_to_dependency_directives::Token, 32> Toks;
   if (minimizeSourceToDependencyDirectives(
-          FromFile->getBuffer(), Output, Toks, &CI.getDiagnostics(),
+          FromFile.getBuffer(), Output, Toks, &CI.getDiagnostics(),
           SM.getLocForStartOfFile(SM.getMainFileID()))) {
     assert(CI.getDiagnostics().hasErrorOccurred() &&
            "no errors reported for failure");
Index: clang/lib/Frontend/FrontendAction.cpp
===================================================================
--- clang/lib/Frontend/FrontendAction.cpp
+++ clang/lib/Frontend/FrontendAction.cpp
@@ -234,13 +234,13 @@
   auto &SourceMgr = CI.getSourceManager();
   auto MainFileID = SourceMgr.getMainFileID();
 
-  bool Invalid = false;
-  const auto *MainFileBuf = SourceMgr.getBuffer(MainFileID, &Invalid);
-  if (Invalid)
+  llvm::Optional<llvm::MemoryBufferRef> MainFileBuf =
+      SourceMgr.getBuffer(MainFileID);
+  if (!MainFileBuf)
     return SourceLocation();
 
   std::unique_ptr<Lexer> RawLexer(
-      new Lexer(MainFileID, MainFileBuf, SourceMgr, CI.getLangOpts()));
+      new Lexer(MainFileID, *MainFileBuf, SourceMgr, CI.getLangOpts()));
 
   // If the first line has the syntax of
   //
@@ -438,7 +438,7 @@
                            PresumedModuleMapFile))
     return true;
 
-  if (SrcMgr.getBuffer(ModuleMapID)->getBufferSize() == Offset)
+  if (SrcMgr.getBufferOrFake(ModuleMapID).getBufferSize() == Offset)
     Offset = 0;
 
   return false;
@@ -611,7 +611,7 @@
       if (auto *File = OldSM.getFileEntryForID(ID))
         Input = FrontendInputFile(File->getName(), Kind);
       else
-        Input = FrontendInputFile(OldSM.getBuffer(ID), Kind);
+        Input = FrontendInputFile(OldSM.getBufferOrFake(ID), Kind);
     }
     setCurrentInput(Input, std::move(AST));
   }
Index: clang/lib/Frontend/CompilerInstance.cpp
===================================================================
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -820,8 +820,7 @@
           : Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;
 
   if (Input.isBuffer()) {
-    SourceMgr.setMainFileID(SourceMgr.createFileID(SourceManager::Unowned,
-                                                   Input.getBuffer(), Kind));
+    SourceMgr.setMainFileID(SourceMgr.createFileID(Input.getBuffer(), Kind));
     assert(SourceMgr.getMainFileID().isValid() &&
            "Couldn't establish MainFileID!");
     return true;
Index: clang/lib/Frontend/ASTUnit.cpp
===================================================================
--- clang/lib/Frontend/ASTUnit.cpp
+++ clang/lib/Frontend/ASTUnit.cpp
@@ -1466,7 +1466,7 @@
     if (Input.isFile())
       return Input.getFile();
     else
-      return Input.getBuffer()->getBufferIdentifier();
+      return Input.getBuffer().getBufferIdentifier();
   }
 
   if (SourceMgr) {
Index: clang/lib/Format/FormatTokenLexer.cpp
===================================================================
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -31,7 +31,7 @@
       Keywords(IdentTable), Encoding(Encoding), FirstInLineIndex(0),
       FormattingDisabled(false), MacroBlockBeginRegex(Style.MacroBlockBegin),
       MacroBlockEndRegex(Style.MacroBlockEnd) {
-  Lex.reset(new Lexer(ID, SourceMgr.getBuffer(ID), SourceMgr,
+  Lex.reset(new Lexer(ID, SourceMgr.getBufferOrFake(ID), SourceMgr,
                       getFormattingLangOpts(Style)));
   Lex->SetKeepWhitespaceMode(true);
 
@@ -541,7 +541,7 @@
   unsigned FirstInLineOffset;
   std::tie(ID, FirstInLineOffset) = SourceMgr.getDecomposedLoc(
       Tokens[FirstInLineIndex]->getStartOfNonWhitespace());
-  StringRef Buffer = SourceMgr.getBuffer(ID)->getBuffer();
+  StringRef Buffer = SourceMgr.getBufferOrFake(ID).getBuffer();
   // Calculate the offset of the start of the current line.
   auto LineOffset = Buffer.rfind('\n', FirstInLineOffset);
   if (LineOffset == StringRef::npos) {
Index: clang/lib/CodeGen/CodeGenAction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenAction.cpp
+++ clang/lib/CodeGen/CodeGenAction.cpp
@@ -1025,11 +1025,10 @@
     if (BA != Backend_EmitNothing && !OS)
       return;
 
-    bool Invalid;
     SourceManager &SM = CI.getSourceManager();
     FileID FID = SM.getMainFileID();
-    const llvm::MemoryBuffer *MainFile = SM.getBuffer(FID, &Invalid);
-    if (Invalid)
+    llvm::Optional<llvm::MemoryBufferRef> MainFile = SM.getBuffer(FID);
+    if (!MainFile)
       return;
 
     TheModule = loadModule(*MainFile);
@@ -1044,8 +1043,7 @@
       TheModule->setTargetTriple(TargetOpts.Triple);
     }
 
-    EmbedBitcode(TheModule.get(), CI.getCodeGenOpts(),
-                 MainFile->getMemBufferRef());
+    EmbedBitcode(TheModule.get(), CI.getCodeGenOpts(), *MainFile);
 
     LLVMContext &Ctx = TheModule->getContext();
     Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler,
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -372,9 +372,8 @@
     return None;
 
   SourceManager &SM = CGM.getContext().getSourceManager();
-  bool Invalid;
-  const llvm::MemoryBuffer *MemBuffer = SM.getBuffer(FID, &Invalid);
-  if (Invalid)
+  llvm::Optional<llvm::MemoryBufferRef> MemBuffer = SM.getBuffer(FID);
+  if (!MemBuffer)
     return None;
 
   llvm::MD5 Hash;
@@ -392,13 +391,7 @@
   if (!CGM.getCodeGenOpts().EmbedSource)
     return None;
 
-  bool SourceInvalid = false;
-  StringRef Source = SM.getBufferData(FID, &SourceInvalid);
-
-  if (SourceInvalid)
-    return None;
-
-  return Source;
+  return SM.getBufferData(FID);
 }
 
 llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
Index: clang/lib/Basic/SourceManager.cpp
===================================================================
--- clang/lib/Basic/SourceManager.cpp
+++ clang/lib/Basic/SourceManager.cpp
@@ -83,6 +83,8 @@
 }
 
 void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree) {
+  IsBufferInvalid = false;
+
   if (B && B == Buffer.getPointer()) {
     assert(0 && "Replacing with the same buffer");
     Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
@@ -95,18 +97,17 @@
   Buffer.setInt((B && DoNotFree) ? DoNotFreeFlag : 0);
 }
 
-const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
-                                                  FileManager &FM,
-                                                  SourceLocation Loc,
-                                                  bool *Invalid) const {
+llvm::Optional<llvm::MemoryBufferRef>
+ContentCache::getBuffer(DiagnosticsEngine &Diag, FileManager &FM,
+                        SourceLocation Loc) const {
   // Lazily create the Buffer for ContentCaches that wrap files.  If we already
   // computed it, just return what we have.
-  if (Buffer.getPointer() || !ContentsEntry) {
-    if (Invalid)
-      *Invalid = isBufferInvalid();
-
-    return Buffer.getPointer();
-  }
+  if (isBufferInvalid())
+    return None;
+  if (auto *B = Buffer.getPointer())
+    return B->getMemBufferRef();
+  if (!ContentsEntry)
+    return None;
 
   // Check that the file's size fits in an 'unsigned' (with room for a
   // past-the-end value). This is deeply regrettable, but various parts of
@@ -115,13 +116,6 @@
   // miserably on large source files.
   if ((uint64_t)ContentsEntry->getSize() >=
       std::numeric_limits<unsigned>::max()) {
-    // We can't make a memory buffer of the required size, so just make a small
-    // one. We should never hit a situation where we've already parsed to a
-    // later offset of the file, so it shouldn't matter that the buffer is
-    // smaller than the file.
-    Buffer.setPointer(
-        llvm::MemoryBuffer::getMemBuffer("", ContentsEntry->getName())
-            .release());
     if (Diag.isDiagnosticInFlight())
       Diag.SetDelayedDiagnostic(diag::err_file_too_large,
                                 ContentsEntry->getName());
@@ -129,9 +123,8 @@
       Diag.Report(Loc, diag::err_file_too_large)
         << ContentsEntry->getName();
 
-    Buffer.setInt(Buffer.getInt() | InvalidFlag);
-    if (Invalid) *Invalid = true;
-    return Buffer.getPointer();
+    IsBufferInvalid = true;
+    return None;
   }
 
   auto BufferOrError = FM.getBufferForFile(ContentsEntry, IsFileVolatile);
@@ -141,20 +134,7 @@
   // exists. Most likely, we were using a stat cache with an invalid entry but
   // the file could also have been removed during processing. Since we can't
   // really deal with this situation, just create an empty buffer.
-  //
-  // FIXME: This is definitely not ideal, but our immediate clients can't
-  // currently handle returning a null entry here. Ideally we should detect
-  // that we are in an inconsistent situation and error out as quickly as
-  // possible.
   if (!BufferOrError) {
-    StringRef FillStr("<<<MISSING SOURCE FILE>>>\n");
-    auto BackupBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
-        ContentsEntry->getSize(), "<invalid>");
-    char *Ptr = BackupBuffer->getBufferStart();
-    for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i)
-      Ptr[i] = FillStr[i % FillStr.size()];
-    Buffer.setPointer(BackupBuffer.release());
-
     if (Diag.isDiagnosticInFlight())
       Diag.SetDelayedDiagnostic(diag::err_cannot_open_file,
                                 ContentsEntry->getName(),
@@ -163,10 +143,8 @@
       Diag.Report(Loc, diag::err_cannot_open_file)
           << ContentsEntry->getName() << BufferOrError.getError().message();
 
-    Buffer.setInt(Buffer.getInt() | InvalidFlag);
-
-    if (Invalid) *Invalid = true;
-    return Buffer.getPointer();
+    IsBufferInvalid = true;
+    return None;
   }
 
   Buffer.setPointer(BufferOrError->release());
@@ -181,9 +159,8 @@
       Diag.Report(Loc, diag::err_file_modified)
         << ContentsEntry->getName();
 
-    Buffer.setInt(Buffer.getInt() | InvalidFlag);
-    if (Invalid) *Invalid = true;
-    return Buffer.getPointer();
+    IsBufferInvalid = true;
+    return None;
   }
 
   // If the buffer is valid, check to see if it has a UTF Byte Order Mark
@@ -208,13 +185,11 @@
   if (InvalidBOM) {
     Diag.Report(Loc, diag::err_unsupported_bom)
       << InvalidBOM << ContentsEntry->getName();
-    Buffer.setInt(Buffer.getInt() | InvalidFlag);
+    IsBufferInvalid = true;
+    return None;
   }
 
-  if (Invalid)
-    *Invalid = isBufferInvalid();
-
-  return Buffer.getPointer();
+  return Buffer.getPointer()->getMemBufferRef();
 }
 
 unsigned LineTableInfo::getLineTableFilenameID(StringRef Name) {
@@ -487,25 +462,12 @@
   return std::make_pair(-ID - 1, CurrentLoadedOffset);
 }
 
-/// As part of recovering from missing or changed content, produce a
-/// fake, non-empty buffer.
-llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const {
-  if (!FakeBufferForRecovery)
-    FakeBufferForRecovery =
-        llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>");
-
-  return FakeBufferForRecovery.get();
-}
-
 /// As part of recovering from missing or changed content, produce a
 /// fake content cache.
 const SrcMgr::ContentCache *
 SourceManager::getFakeContentCacheForRecovery() const {
-  if (!FakeContentCacheForRecovery) {
+  if (!FakeContentCacheForRecovery)
     FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
-    FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(),
-                                               /*DoNotFree=*/true);
-  }
   return FakeContentCacheForRecovery.get();
 }
 
@@ -639,11 +601,11 @@
   return SourceLocation::getMacroLoc(NextLocalOffset - (TokLength + 1));
 }
 
-const llvm::MemoryBuffer *
-SourceManager::getMemoryBufferForFile(const FileEntry *File, bool *Invalid) {
+llvm::Optional<llvm::MemoryBufferRef>
+SourceManager::getMemoryBufferForFile(const FileEntry *File) {
   const SrcMgr::ContentCache *IR = getOrCreateContentCache(File);
   assert(IR && "getOrCreateContentCache() cannot return NULL");
-  return IR->getBuffer(Diag, getFileManager(), SourceLocation(), Invalid);
+  return IR->getBuffer(Diag, getFileManager());
 }
 
 void SourceManager::overrideFileContents(const FileEntry *SourceFile,
@@ -687,24 +649,16 @@
   const_cast<SrcMgr::ContentCache *>(CC)->IsTransient = true;
 }
 
-StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
+llvm::Optional<StringRef> SourceManager::getBufferDataOrNone(FileID FID) const {
   bool MyInvalid = false;
   const SLocEntry &SLoc = getSLocEntry(FID, &MyInvalid);
-  if (!SLoc.isFile() || MyInvalid) {
-    if (Invalid)
-      *Invalid = true;
-    return "<<<<<INVALID SOURCE LOCATION>>>>>";
-  }
-
-  const llvm::MemoryBuffer *Buf = SLoc.getFile().getContentCache()->getBuffer(
-      Diag, getFileManager(), SourceLocation(), &MyInvalid);
-  if (Invalid)
-    *Invalid = MyInvalid;
+  if (!SLoc.isFile() || MyInvalid)
+    return None;
 
-  if (MyInvalid)
-    return "<<<<<INVALID SOURCE LOCATION>>>>>";
-
-  return Buf->getBuffer();
+  if (llvm::Optional<llvm::MemoryBufferRef> Buf =
+          SLoc.getFile().getContentCache()->getBuffer(Diag, getFileManager()))
+    return Buf->getBuffer();
+  return None;
 }
 
 //===----------------------------------------------------------------------===//
@@ -1126,24 +1080,22 @@
 
     return "<<<<INVALID BUFFER>>>>";
   }
-  const llvm::MemoryBuffer *Buffer =
-      Entry.getFile().getContentCache()->getBuffer(
-          Diag, getFileManager(), SourceLocation(), &CharDataInvalid);
+  llvm::Optional<llvm::MemoryBufferRef> Buffer =
+      Entry.getFile().getContentCache()->getBuffer(Diag, getFileManager());
   if (Invalid)
-    *Invalid = CharDataInvalid;
-  return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second);
+    *Invalid = !Buffer;
+  return Buffer ? Buffer->getBufferStart() + LocInfo.second : nullptr;
 }
 
 /// getColumnNumber - Return the column # for the specified file position.
 /// this is significantly cheaper to compute than the line number.
 unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
                                         bool *Invalid) const {
-  bool MyInvalid = false;
-  const llvm::MemoryBuffer *MemBuf = getBuffer(FID, &MyInvalid);
+  llvm::Optional<llvm::MemoryBufferRef> MemBuf = getBuffer(FID);
   if (Invalid)
-    *Invalid = MyInvalid;
+    *Invalid = !MemBuf;
 
-  if (MyInvalid)
+  if (!MemBuf)
     return 1;
 
   // It is okay to request a position just past the end of the buffer.
@@ -1224,9 +1176,9 @@
                                llvm::BumpPtrAllocator &Alloc,
                                const SourceManager &SM, bool &Invalid) {
   // Note that calling 'getBuffer()' may lazily page in the file.
-  const MemoryBuffer *Buffer =
-      FI->getBuffer(Diag, SM.getFileManager(), SourceLocation(), &Invalid);
-  if (Invalid)
+  llvm::Optional<llvm::MemoryBufferRef> Buffer =
+      FI->getBuffer(Diag, SM.getFileManager());
+  if (!Buffer)
     return;
 
   // Find the file offsets of all of the *physical* source lines.  This does
@@ -1423,7 +1375,9 @@
                                        bool *Invalid) const {
   if (isInvalid(Loc, Invalid)) return "<invalid loc>";
 
-  return getBuffer(getFileID(Loc), Invalid)->getBufferIdentifier();
+  if (auto Buffer = getBuffer(getFileID(Loc)))
+    return Buffer->getBufferIdentifier();
+  return "";
 }
 
 /// getPresumedLoc - This method returns the "presumed" location of a
@@ -1455,8 +1409,8 @@
   StringRef Filename;
   if (C->OrigEntry)
     Filename = C->OrigEntry->getName();
-  else
-    Filename = C->getBuffer(Diag, getFileManager())->getBufferIdentifier();
+  else if (auto Name = C->getBufferIdentifier(Diag, getFileManager()))
+    Filename = *Name;
 
   unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
   if (Invalid)
@@ -1656,13 +1610,16 @@
   }
 
   if (Line > Content->NumLines) {
-    unsigned Size = Content->getBuffer(Diag, getFileManager())->getBufferSize();
-    if (Size > 0)
-      --Size;
+    unsigned Size = 0;
+    if (llvm::Optional<unsigned> RawSize =
+            Content->getBufferSize(Diag, getFileManager()))
+      if (*RawSize > 0)
+        Size = *RawSize - 1;
     return FileLoc.getLocWithOffset(Size);
   }
 
-  const llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, getFileManager());
+  llvm::Optional<llvm::MemoryBufferRef> Buffer =
+      Content->getBuffer(Diag, getFileManager());
   unsigned FilePos = Content->SourceLineCache[Line - 1];
   const char *Buf = Buffer->getBufferStart() + FilePos;
   unsigned BufLength = Buffer->getBufferSize() - FilePos;
@@ -1947,11 +1904,10 @@
 
   // If we arrived here, the location is either in a built-ins buffer or
   // associated with global inline asm. PR5662 and PR22576 are examples.
-
-  StringRef LB = getBuffer(LOffs.first)->getBufferIdentifier();
-  StringRef RB = getBuffer(ROffs.first)->getBufferIdentifier();
-  bool LIsBuiltins = LB == "<built-in>";
-  bool RIsBuiltins = RB == "<built-in>";
+  llvm::Optional<StringRef> LB = getBufferIdentifier(LOffs.first);
+  llvm::Optional<StringRef> RB = getBufferIdentifier(ROffs.first);
+  bool LIsBuiltins = LB == StringRef("<built-in>");
+  bool RIsBuiltins = RB == StringRef("<built-in>");
   // Sort built-in before non-built-in.
   if (LIsBuiltins || RIsBuiltins) {
     if (LIsBuiltins != RIsBuiltins)
@@ -1960,8 +1916,8 @@
     // lower IDs come first.
     return LOffs.first < ROffs.first;
   }
-  bool LIsAsm = LB == "<inline asm>";
-  bool RIsAsm = RB == "<inline asm>";
+  bool LIsAsm = LB == StringRef("<inline asm>");
+  bool RIsAsm = RB == StringRef("<inline asm>");
   // Sort assembler after built-ins, but before the rest.
   if (LIsAsm || RIsAsm) {
     if (LIsAsm != RIsAsm)
@@ -1969,8 +1925,8 @@
     assert(LOffs.first == ROffs.first);
     return false;
   }
-  bool LIsScratch = LB == "<scratch space>";
-  bool RIsScratch = RB == "<scratch space>";
+  bool LIsScratch = LB == StringRef("<scratch space>");
+  bool RIsScratch = RB == StringRef("<scratch space>");
   // Sort scratch after inline asm, but before the rest.
   if (LIsScratch || RIsScratch) {
     if (LIsScratch != RIsScratch)
Index: clang/lib/Basic/SourceLocation.cpp
===================================================================
--- clang/lib/Basic/SourceLocation.cpp
+++ clang/lib/Basic/SourceLocation.cpp
@@ -245,7 +245,13 @@
 
 StringRef FullSourceLoc::getBufferData(bool *Invalid) const {
   assert(isValid());
-  return SrcMgr->getBuffer(SrcMgr->getFileID(*this), Invalid)->getBuffer();
+  auto Buffer = SrcMgr->getBuffer(SrcMgr->getFileID(*this));
+  if (Invalid)
+    *Invalid = !Buffer;
+
+  if (Buffer)
+    return Buffer->getBuffer();
+  return "";
 }
 
 std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const {
Index: clang/lib/Basic/Diagnostic.cpp
===================================================================
--- clang/lib/Basic/Diagnostic.cpp
+++ clang/lib/Basic/Diagnostic.cpp
@@ -258,7 +258,7 @@
       PrintedOuterHeading = true;
 
       llvm::errs() << "File " << &File << " <FileID " << ID.getHashValue()
-                   << ">: " << SrcMgr.getBuffer(ID)->getBufferIdentifier();
+                   << ">: " << SrcMgr.getBufferOrFake(ID).getBufferIdentifier();
       if (F.second.Parent) {
         std::pair<FileID, unsigned> Decomp =
             SrcMgr.getDecomposedIncludedLoc(ID);
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -8502,11 +8502,9 @@
 
     if (ToID.isInvalid() || IsBuiltin) {
       // FIXME: We want to re-use the existing MemoryBuffer!
-      bool Invalid = true;
-      const llvm::MemoryBuffer *FromBuf =
-          Cache->getBuffer(FromContext.getDiagnostics(),
-                           FromSM.getFileManager(), SourceLocation{}, &Invalid);
-      if (!FromBuf || Invalid)
+      llvm::Optional<llvm::MemoryBufferRef> FromBuf = Cache->getBuffer(
+          FromContext.getDiagnostics(), FromSM.getFileManager());
+      if (!FromBuf)
         // FIXME: Use a new error kind?
         return llvm::make_error<ImportError>(ImportError::Unknown);
 
Index: clang/lib/ARCMigrate/Transforms.cpp
===================================================================
--- clang/lib/ARCMigrate/Transforms.cpp
+++ clang/lib/ARCMigrate/Transforms.cpp
@@ -140,10 +140,10 @@
   std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
 
   // Try to load the file buffer.
-  bool invalidTemp = false;
-  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
-  if (invalidTemp)
+  llvm::Optional<StringRef> maybeFile = SM.getBufferData(locInfo.first);
+  if (!maybeFile)
     return SourceLocation();
+  StringRef file = *maybeFile;
 
   const char *tokenBegin = file.data() + locInfo.second;
 
@@ -388,10 +388,10 @@
   std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
 
   // Try to load the file buffer.
-  bool invalidTemp = false;
-  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
-  if (invalidTemp)
+  llvm::Optional<StringRef> maybeFile = SM.getBufferData(locInfo.first);
+  if (!maybeFile)
     return false;
+  StringRef file = *maybeFile;
 
   const char *tokenBegin = file.data() + locInfo.second;
 
@@ -469,10 +469,10 @@
   std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
 
   // Try to load the file buffer.
-  bool invalidTemp = false;
-  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
-  if (invalidTemp)
+  llvm::Optional<StringRef> maybeFile = SM.getBufferData(locInfo.first);
+  if (!maybeFile)
     return false;
+  StringRef file = *maybeFile;
 
   const char *tokenBegin = file.data() + locInfo.second;
 
Index: clang/include/clang/Lex/Lexer.h
===================================================================
--- clang/include/clang/Lex/Lexer.h
+++ clang/include/clang/Lex/Lexer.h
@@ -28,6 +28,7 @@
 namespace llvm {
 
 class MemoryBuffer;
+class MemoryBufferRef;
 
 } // namespace llvm
 
@@ -138,7 +139,7 @@
   /// with the specified preprocessor managing the lexing process.  This lexer
   /// assumes that the associated file buffer and Preprocessor objects will
   /// outlive it, so it doesn't take ownership of either of them.
-  Lexer(FileID FID, const llvm::MemoryBuffer *InputFile, Preprocessor &PP);
+  Lexer(FileID FID, const llvm::MemoryBufferRef &InputFile, Preprocessor &PP);
 
   /// Lexer constructor - Create a new raw lexer object.  This object is only
   /// suitable for calls to 'LexFromRawLexer'.  This lexer assumes that the
@@ -149,7 +150,7 @@
   /// Lexer constructor - Create a new raw lexer object.  This object is only
   /// suitable for calls to 'LexFromRawLexer'.  This lexer assumes that the
   /// text range will outlive it, so it doesn't take ownership of it.
-  Lexer(FileID FID, const llvm::MemoryBuffer *FromFile,
+  Lexer(FileID FID, const llvm::MemoryBufferRef &FromFile,
         const SourceManager &SM, const LangOptions &LangOpts);
 
   Lexer(const Lexer &) = delete;
Index: clang/include/clang/Frontend/PrecompiledPreamble.h
===================================================================
--- clang/include/clang/Frontend/PrecompiledPreamble.h
+++ clang/include/clang/Frontend/PrecompiledPreamble.h
@@ -216,7 +216,7 @@
 
     static PreambleFileHash createForFile(off_t Size, time_t ModTime);
     static PreambleFileHash
-    createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
+    createForMemoryBuffer(llvm::Optional<llvm::MemoryBufferRef> Buffer);
 
     friend bool operator==(const PreambleFileHash &LHS,
                            const PreambleFileHash &RHS) {
Index: clang/include/clang/Frontend/FrontendOptions.h
===================================================================
--- clang/include/clang/Frontend/FrontendOptions.h
+++ clang/include/clang/Frontend/FrontendOptions.h
@@ -15,18 +15,13 @@
 #include "clang/Sema/CodeCompleteOptions.h"
 #include "clang/Serialization/ModuleFileExtension.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include <cassert>
 #include <memory>
 #include <string>
 #include <unordered_map>
 #include <vector>
 
-namespace llvm {
-
-class MemoryBuffer;
-
-} // namespace llvm
-
 namespace clang {
 
 namespace frontend {
@@ -188,7 +183,7 @@
   /// The input, if it comes from a buffer rather than a file. This object
   /// does not own the buffer, and the caller is responsible for ensuring
   /// that it outlives any users.
-  const llvm::MemoryBuffer *Buffer = nullptr;
+  llvm::Optional<llvm::MemoryBufferRef> Buffer;
 
   /// The kind of input, e.g., C source, AST file, LLVM IR.
   InputKind Kind;
@@ -200,16 +195,16 @@
   FrontendInputFile() = default;
   FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false)
       : File(File.str()), Kind(Kind), IsSystem(IsSystem) {}
-  FrontendInputFile(const llvm::MemoryBuffer *Buffer, InputKind Kind,
+  FrontendInputFile(llvm::MemoryBufferRef Buffer, InputKind Kind,
                     bool IsSystem = false)
       : Buffer(Buffer), Kind(Kind), IsSystem(IsSystem) {}
 
   InputKind getKind() const { return Kind; }
   bool isSystem() const { return IsSystem; }
 
-  bool isEmpty() const { return File.empty() && Buffer == nullptr; }
-  bool isFile() const { return !isBuffer(); }
-  bool isBuffer() const { return Buffer != nullptr; }
+  bool isEmpty() const { return File.empty() && !Buffer; }
+  bool isFile() const { return !Buffer; }
+  bool isBuffer() const { return !isFile(); }
   bool isPreprocessed() const { return Kind.isPreprocessed(); }
 
   StringRef getFile() const {
@@ -217,9 +212,9 @@
     return File;
   }
 
-  const llvm::MemoryBuffer *getBuffer() const {
-    assert(isBuffer());
-    return Buffer;
+  llvm::MemoryBufferRef getBuffer() const {
+    assert(Buffer);
+    return *Buffer;
   }
 };
 
Index: clang/include/clang/Frontend/FrontendAction.h
===================================================================
--- clang/include/clang/Frontend/FrontendAction.h
+++ clang/include/clang/Frontend/FrontendAction.h
@@ -145,7 +145,7 @@
     assert(!CurrentInput.isEmpty() && "No current file!");
     return CurrentInput.isFile()
                ? CurrentInput.getFile()
-               : CurrentInput.getBuffer()->getBufferIdentifier();
+               : CurrentInput.getBuffer().getBufferIdentifier();
   }
 
   InputKind getCurrentFileKind() const {
Index: clang/include/clang/Basic/SourceManager.h
===================================================================
--- clang/include/clang/Basic/SourceManager.h
+++ clang/include/clang/Basic/SourceManager.h
@@ -93,9 +93,6 @@
   /// This object owns the MemoryBuffer object.
   class alignas(8) ContentCache {
     enum CCFlags {
-      /// Whether the buffer is invalid.
-      InvalidFlag = 0x01,
-
       /// Whether the buffer should not be freed on destruction.
       DoNotFreeFlag = 0x02
     };
@@ -149,21 +146,21 @@
     /// after serialization and deserialization.
     unsigned IsTransient : 1;
 
+    /// Cache whether the content is known to be invalid.
+    mutable unsigned IsBufferInvalid : 1;
+
     ContentCache(const FileEntry *Ent = nullptr) : ContentCache(Ent, Ent) {}
 
     ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
         : Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
-          BufferOverridden(false), IsFileVolatile(false), IsTransient(false) {}
+          BufferOverridden(false), IsFileVolatile(false), IsTransient(false),
+          IsBufferInvalid(false) {}
 
     /// The copy ctor does not allow copies where source object has either
     /// a non-NULL Buffer or SourceLineCache.  Ownership of allocated memory
     /// is not transferred, so this is a logical error.
     ContentCache(const ContentCache &RHS)
-        : Buffer(nullptr, false), BufferOverridden(false),
-          IsFileVolatile(false), IsTransient(false) {
-      OrigEntry = RHS.OrigEntry;
-      ContentsEntry = RHS.ContentsEntry;
-
+        : ContentCache(RHS.OrigEntry, RHS.ContentsEntry) {
       assert(RHS.Buffer.getPointer() == nullptr &&
              RHS.SourceLineCache == nullptr &&
              "Passed ContentCache object cannot own a buffer.");
@@ -184,10 +181,26 @@
     ///   will be emitted at.
     ///
     /// \param Invalid If non-NULL, will be set \c true if an error occurred.
-    const llvm::MemoryBuffer *getBuffer(DiagnosticsEngine &Diag,
-                                        FileManager &FM,
-                                        SourceLocation Loc = SourceLocation(),
-                                        bool *Invalid = nullptr) const;
+    llvm::Optional<llvm::MemoryBufferRef>
+    getBuffer(DiagnosticsEngine &Diag, FileManager &FM,
+              SourceLocation Loc = SourceLocation()) const;
+
+    llvm::Optional<llvm::StringRef>
+    getBufferIdentifier(DiagnosticsEngine &Diag, FileManager &FM,
+                        SourceLocation Loc = SourceLocation()) const {
+      if (auto Buffer = getBuffer(Diag, FM, Loc))
+        return Buffer->getBufferIdentifier();
+      return None;
+    }
+
+    /// Get the buffer size, giving 0 if the buffer is invalid.
+    llvm::Optional<unsigned>
+    getBufferSize(DiagnosticsEngine &Diag, FileManager &FM,
+                  SourceLocation Loc = SourceLocation()) const {
+      if (auto Buffer = getBuffer(Diag, FM, Loc))
+        return Buffer->getBufferSize();
+      return None;
+    }
 
     /// Returns the size of the content encapsulated by this
     /// ContentCache.
@@ -218,9 +231,7 @@
     void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree = false);
 
     /// Determine whether the buffer itself is invalid.
-    bool isBufferInvalid() const {
-      return Buffer.getInt() & InvalidFlag;
-    }
+    bool isBufferInvalid() const { return IsBufferInvalid; }
 
     /// Determine whether the buffer should be freed.
     bool shouldFreeBuffer() const {
@@ -283,6 +294,11 @@
       return X;
     }
 
+    static FileInfo getForRecovery() {
+      FileInfo X = get(SourceLocation(), nullptr, SrcMgr::C_User, "");
+      return X;
+    }
+
     SourceLocation getIncludeLoc() const {
       return SourceLocation::getFromRawEncoding(IncludeLoc);
     }
@@ -858,19 +874,16 @@
         Name, IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
   }
 
-  enum UnownedTag { Unowned };
-
   /// Create a new FileID that represents the specified memory buffer.
   ///
-  /// This does not take ownership of the MemoryBuffer. The memory buffer must
-  /// outlive the SourceManager.
-  FileID createFileID(UnownedTag, const llvm::MemoryBuffer *Buffer,
+  /// This does not take ownership of the MemoryBufferRef. The memory buffer
+  /// must outlive the SourceManager.
+  FileID createFileID(llvm::MemoryBufferRef Buffer,
                       SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User,
                       int LoadedID = 0, unsigned LoadedOffset = 0,
                       SourceLocation IncludeLoc = SourceLocation()) {
-    return createFileID(createMemBufferContentCache(Buffer, /*DoNotFree*/ true),
-                        Buffer->getBufferIdentifier(), IncludeLoc,
-                        FileCharacter, LoadedID, LoadedOffset);
+    return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
+                        LoadedID, LoadedOffset, IncludeLoc);
   }
 
   /// Get the FileID for \p SourceFile if it exists. Otherwise, create a
@@ -911,8 +924,8 @@
   ///
   /// \param Invalid If non-NULL, will be set \c true if an error
   /// occurs while retrieving the memory buffer.
-  const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File,
-                                                   bool *Invalid = nullptr);
+  llvm::Optional<llvm::MemoryBufferRef>
+  getMemoryBufferForFile(const FileEntry *File);
 
   /// Override the contents of the given source file by providing an
   /// already-allocated buffer.
@@ -976,34 +989,37 @@
   ///
   /// If there is an error opening this buffer the first time, this
   /// manufactures a temporary buffer and returns a non-empty error string.
-  const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc,
-                                      bool *Invalid = nullptr) const {
+  llvm::Optional<llvm::MemoryBufferRef>
+  getBuffer(FileID FID, SourceLocation Loc = SourceLocation()) const {
     bool MyInvalid = false;
     const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
-    if (MyInvalid || !Entry.isFile()) {
-      if (Invalid)
-        *Invalid = true;
-
-      return getFakeBufferForRecovery();
-    }
+    if (MyInvalid || !Entry.isFile())
+      return None;
 
     return Entry.getFile().getContentCache()->getBuffer(Diag, getFileManager(),
-                                                        Loc, Invalid);
+                                                        Loc);
   }
 
-  const llvm::MemoryBuffer *getBuffer(FileID FID,
-                                      bool *Invalid = nullptr) const {
-    bool MyInvalid = false;
-    const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
-    if (MyInvalid || !Entry.isFile()) {
-      if (Invalid)
-        *Invalid = true;
+  llvm::MemoryBufferRef
+  getBufferOrFake(FileID FID, SourceLocation Loc = SourceLocation()) const {
+    if (auto Buffer = getBuffer(FID, Loc))
+      return *Buffer;
+    return llvm::MemoryBufferRef("<<<INVALID BUFFER>>>", "");
+  }
 
-      return getFakeBufferForRecovery();
-    }
+  llvm::Optional<llvm::StringRef>
+  getBufferIdentifier(FileID FID, SourceLocation Loc = SourceLocation()) const {
+    if (auto Buffer = getBuffer(FID, Loc))
+      return Buffer->getBufferIdentifier();
+    return None;
+  }
 
-    return Entry.getFile().getContentCache()->getBuffer(
-        Diag, getFileManager(), SourceLocation(), Invalid);
+  llvm::StringRef
+  getBufferIdentifierOrEmpty(FileID FID,
+                             SourceLocation Loc = SourceLocation()) const {
+    if (auto Identifier = getBufferIdentifier(FID, Loc))
+      return *Identifier;
+    return "";
   }
 
   /// Returns the FileEntry record for the provided FileID.
@@ -1041,12 +1057,29 @@
     return Content->OrigEntry;
   }
 
+  /// Return a StringRef to the source buffer data for the
+  /// specified FileID, or None if it's invalid.
+  ///
+  /// \param FID The file ID whose contents will be returned.
+  llvm::Optional<StringRef> getBufferDataOrNone(FileID FID) const;
+
   /// Return a StringRef to the source buffer data for the
   /// specified FileID.
   ///
   /// \param FID The file ID whose contents will be returned.
   /// \param Invalid If non-NULL, will be set true if an error occurred.
-  StringRef getBufferData(FileID FID, bool *Invalid = nullptr) const;
+  StringRef getBufferData(FileID FID, bool *Invalid) const {
+    auto Data = getBufferDataOrNone(FID);
+    if (Invalid)
+      *Invalid = !Data;
+    return Data ? *Data : "";
+  }
+
+  StringRef getBufferData(FileID FID) const {
+    if (auto Data = getBufferDataOrNone(FID))
+      return *Data;
+    return "";
+  }
 
   /// Get the number of FileIDs (files and macros) that were created
   /// during preprocessing of \p FID, including it.
@@ -1761,7 +1794,6 @@
   friend class ASTReader;
   friend class ASTWriter;
 
-  llvm::MemoryBuffer *getFakeBufferForRecovery() const;
   const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const;
 
   const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const;
Index: clang-tools-extra/modularize/PreprocessorTracker.cpp
===================================================================
--- clang-tools-extra/modularize/PreprocessorTracker.cpp
+++ clang-tools-extra/modularize/PreprocessorTracker.cpp
@@ -312,8 +312,8 @@
 // Retrieve source line from file image given a location.
 static std::string getSourceLine(clang::Preprocessor &PP,
                                  clang::SourceLocation Loc) {
-  const llvm::MemoryBuffer *MemBuffer =
-      PP.getSourceManager().getBuffer(PP.getSourceManager().getFileID(Loc));
+  llvm::MemoryBufferRef MemBuffer = PP.getSourceManager().getBufferOrFake(
+      PP.getSourceManager().getFileID(Loc));
   const char *Buffer = MemBuffer->getBufferStart();
   const char *BufferEnd = MemBuffer->getBufferEnd();
   const char *BeginPtr = PP.getSourceManager().getCharacterData(Loc);
@@ -338,7 +338,8 @@
 // Retrieve source line from file image given a file ID and line number.
 static std::string getSourceLine(clang::Preprocessor &PP, clang::FileID FileID,
                                  int Line) {
-  const llvm::MemoryBuffer *MemBuffer = PP.getSourceManager().getBuffer(FileID);
+  llvm::MemoryBufferRef MemBuffer =
+      PP.getSourceManager().getBufferOrFake(FileID);
   const char *Buffer = MemBuffer->getBufferStart();
   const char *BufferEnd = MemBuffer->getBufferEnd();
   const char *BeginPtr = Buffer;
Index: clang-tools-extra/clangd/SourceCode.cpp
===================================================================
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -414,9 +414,9 @@
 
 llvm::StringRef toSourceCode(const SourceManager &SM, SourceRange R) {
   assert(isValidFileRange(SM, R));
-  bool Invalid = false;
-  auto *Buf = SM.getBuffer(SM.getFileID(R.getBegin()), &Invalid);
-  assert(!Invalid);
+  llvm::Optional<llvm::MemoryBufferRef> Buf =
+      SM.getBuffer(SM.getFileID(R.getBegin()));
+  assert(Buf);
 
   size_t BeginOffset = SM.getFileOffset(R.getBegin());
   size_t EndOffset = SM.getFileOffset(R.getEnd());
@@ -425,7 +425,7 @@
 
 llvm::Expected<SourceLocation> sourceLocationInMainFile(const SourceManager &SM,
                                                         Position P) {
-  llvm::StringRef Code = SM.getBuffer(SM.getMainFileID())->getBuffer();
+  llvm::StringRef Code = SM.getBufferOrFake(SM.getMainFileID())->getBuffer();
   auto Offset =
       positionToOffset(Code, P, /*AllowColumnBeyondLineLength=*/false);
   if (!Offset)
@@ -575,7 +575,8 @@
   SourceManagerForFile FileSM("dummy.cpp", NullTerminatedCode);
   auto &SM = FileSM.get();
   auto FID = SM.getMainFileID();
-  Lexer Lex(FID, SM.getBuffer(FID), SM, format::getFormattingLangOpts(Style));
+  Lexer Lex(FID, SM.getBufferOrFake(FID), SM,
+            format::getFormattingLangOpts(Style));
   Token Tok;
 
   while (!Lex.LexFromRawLexer(Tok))
Index: clang-tools-extra/clangd/Format.cpp
===================================================================
--- clang-tools-extra/clangd/Format.cpp
+++ clang-tools-extra/clangd/Format.cpp
@@ -25,7 +25,8 @@
   SourceManagerForFile FileSM("dummy.cpp", Code);
   auto &SM = FileSM.get();
   FileID FID = SM.getMainFileID();
-  Lexer Lex(FID, SM.getBuffer(FID), SM, format::getFormattingLangOpts(Style));
+  Lexer Lex(FID, SM.getBufferOrFake(FID), SM,
+            format::getFormattingLangOpts(Style));
   Token Tok;
   std::vector<char> Brackets;
   while (!Lex.LexFromRawLexer(Tok)) {
Index: clang-tools-extra/clangd/ClangdUnit.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdUnit.cpp
+++ clang-tools-extra/clangd/ClangdUnit.cpp
@@ -233,7 +233,7 @@
                    SrcMgr::CharacteristicKind Kind, FileID PrevFID) override {
     // It'd be nice if there was a better way to identify built-in headers...
     if (Reason == FileChangeReason::ExitFile &&
-        SM.getBuffer(PrevFID)->getBufferIdentifier() == "<built-in>")
+        SM.getBufferOrFake(PrevFID)->getBufferIdentifier() == "<built-in>")
       replay();
   }
 
Index: clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
@@ -159,10 +159,7 @@
   if (FileOffset.first.isInvalid())
     return false;
 
-  const StringRef BufferIdentifier =
-      SourceManager->getBuffer(FileOffset.first)->getBufferIdentifier();
-
-  return BufferIdentifier.empty();
+  return SourceManager->getBufferIdentifierOrEmpty(FileOffset.first).empty();
 }
 
 } // namespace readability
Index: clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp
+++ clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp
@@ -145,7 +145,8 @@
   const LangOptions &Opts = ASTCtx->getLangOpts();
   const SourceManager &SM = ASTCtx->getSourceManager();
 
-  const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getFileID(AssertLoc));
+  llvm::Optional<llvm::MemoryBufferRef> Buffer =
+      SM.getBuffer(SM.getFileID(AssertLoc));
   if (!Buffer)
     return SourceLocation();
 
Index: clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
@@ -53,10 +53,10 @@
 
   SourceLocation LocEnd = Semicolon->getEndLoc();
   FileID FID = SM.getFileID(LocEnd);
-  const llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, LocEnd);
+  llvm::MemoryBufferRef Buffer = SM.getBufferOrFake(FID, LocEnd);
   Lexer Lexer(SM.getLocForStartOfFile(FID), Ctxt.getLangOpts(),
-              Buffer->getBufferStart(), SM.getCharacterData(LocEnd) + 1,
-              Buffer->getBufferEnd());
+              Buffer.getBufferStart(), SM.getCharacterData(LocEnd) + 1,
+              Buffer.getBufferEnd());
   if (Lexer.LexFromRawLexer(Token))
     return;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to