Merge pull request #23840 from drodriguez/build-script-remove-unused-method

[utils] Remove unused method.
diff --git a/include/swift/AST/DiagnosticConsumer.h b/include/swift/AST/DiagnosticConsumer.h
index 49dc645..d619fa0 100644
--- a/include/swift/AST/DiagnosticConsumer.h
+++ b/include/swift/AST/DiagnosticConsumer.h
@@ -79,7 +79,7 @@
 
 public:
   virtual ~DiagnosticConsumer();
-  
+
   /// Invoked whenever the frontend emits a diagnostic.
   ///
   /// \param SM The source manager associated with the source locations in
@@ -94,11 +94,20 @@
   /// \param FormatArgs The diagnostic format string arguments.
   ///
   /// \param Info Extra information associated with the diagnostic.
-  virtual void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                                DiagnosticKind Kind,
-                                StringRef FormatString,
-                                ArrayRef<DiagnosticArgument> FormatArgs,
-                                const DiagnosticInfo &Info) = 0;
+  ///
+  /// \param bufferIndirectlyCausingDiagnostic Only used when directing
+  /// diagnostics to different outputs.
+  /// In batch mode a diagnostic may be
+  /// located in a non-primary file, but there will be no .dia file for a
+  /// non-primary. If valid, this argument contains a location within a buffer
+  /// that corresponds to a primary input. The .dia file for that primary can be
+  /// used for the diagnostic, as if it had occurred at this location.
+  virtual void
+  handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+                   StringRef FormatString,
+                   ArrayRef<DiagnosticArgument> FormatArgs,
+                   const DiagnosticInfo &Info,
+                   SourceLoc bufferIndirectlyCausingDiagnostic) = 0;
 
   /// \returns true if an error occurred while finishing-up.
   virtual bool finishProcessing() { return false; }
@@ -116,11 +125,11 @@
 /// DiagnosticConsumer that discards all diagnostics.
 class NullDiagnosticConsumer : public DiagnosticConsumer {
 public:
-  void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                        DiagnosticKind Kind,
+  void handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
                         StringRef FormatString,
                         ArrayRef<DiagnosticArgument> FormatArgs,
-                        const DiagnosticInfo &Info) override;
+                        const DiagnosticInfo &Info,
+                        SourceLoc bufferIndirectlyCausingDiagnostic) override;
 };
 
 /// DiagnosticConsumer that forwards diagnostics to the consumers of
@@ -129,11 +138,11 @@
   DiagnosticEngine &TargetEngine;
 public:
   ForwardingDiagnosticConsumer(DiagnosticEngine &Target);
-  void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                        DiagnosticKind Kind,
+  void handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
                         StringRef FormatString,
                         ArrayRef<DiagnosticArgument> FormatArgs,
-                        const DiagnosticInfo &Info) override;
+                        const DiagnosticInfo &Info,
+                        SourceLoc bufferIndirectlyCausingDiagnostic) override;
 };
 
 /// DiagnosticConsumer that funnels diagnostics in certain files to
@@ -175,8 +184,12 @@
     std::string inputFileName;
 
     /// The consumer (if any) for diagnostics associated with the inputFileName.
-    /// A null pointer for the DiagnosticConsumer means that diagnostics for
-    /// this file should not be emitted.
+    /// A null pointer for the DiagnosticConsumer means that this file is a
+    /// non-primary one in batch mode and we have no .dia file for it.
+    /// If there is a responsible primary when the diagnostic is handled
+    /// it will be shunted to that primary's .dia file.
+    /// Otherwise it will be suppressed, assuming that the diagnostic will
+    /// surface in another frontend job that compiles that file as a primary.
     std::unique_ptr<DiagnosticConsumer> consumer;
 
     // Has this subconsumer ever handled a diagnostic that is an error?
@@ -191,16 +204,16 @@
                 std::unique_ptr<DiagnosticConsumer> consumer)
         : inputFileName(inputFileName), consumer(std::move(consumer)) {}
 
-    void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                          DiagnosticKind Kind,
+    void handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
                           StringRef FormatString,
                           ArrayRef<DiagnosticArgument> FormatArgs,
-                          const DiagnosticInfo &Info) {
+                          const DiagnosticInfo &Info,
+                          const SourceLoc bufferIndirectlyCausingDiagnostic) {
       if (!getConsumer())
         return;
       hasAnErrorBeenConsumed |= Kind == DiagnosticKind::Error;
       getConsumer()->handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs,
-                                      Info);
+                                      Info, bufferIndirectlyCausingDiagnostic);
     }
     
     void informDriverOfIncompleteBatchModeCompilation() {
@@ -287,11 +300,11 @@
       SmallVectorImpl<Subconsumer> &consumers);
 
 public:
-  void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                        DiagnosticKind Kind,
+  void handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
                         StringRef FormatString,
                         ArrayRef<DiagnosticArgument> FormatArgs,
-                        const DiagnosticInfo &Info) override;
+                        const DiagnosticInfo &Info,
+                        SourceLoc bufferIndirectlyCausingDiagnostic) override;
 
   bool finishProcessing() override;
 
@@ -309,6 +322,14 @@
   /// a particular consumer if diagnostic goes there.
   Optional<FileSpecificDiagnosticConsumer::Subconsumer *>
   subconsumerForLocation(SourceManager &SM, SourceLoc loc);
+
+  Optional<FileSpecificDiagnosticConsumer::Subconsumer *>
+  findSubconsumer(SourceManager &SM, SourceLoc loc, DiagnosticKind Kind,
+                  SourceLoc bufferIndirectlyCausingDiagnostic);
+
+  Optional<FileSpecificDiagnosticConsumer::Subconsumer *>
+  findSubconsumerForNonNote(SourceManager &SM, SourceLoc loc,
+                            SourceLoc bufferIndirectlyCausingDiagnostic);
 };
   
 } // end namespace swift
diff --git a/include/swift/AST/DiagnosticEngine.h b/include/swift/AST/DiagnosticEngine.h
index c0c2739..06b2868 100644
--- a/include/swift/AST/DiagnosticEngine.h
+++ b/include/swift/AST/DiagnosticEngine.h
@@ -28,7 +28,8 @@
   class DiagnosticEngine;
   class SourceManager;
   class ValueDecl;
-  
+  class SourceFile;
+
   enum class PatternKind : uint8_t;
   enum class SelfAccessKind : uint8_t;
   enum class ReferenceOwnership : uint8_t;
@@ -561,6 +562,12 @@
     /// emitted once all transactions have closed.
     unsigned TransactionCount = 0;
 
+    /// For batch mode, use this to know where to output a diagnostic from a
+    /// non-primary file. It's any location in the buffer of the current primary
+    /// input being compiled.
+    /// May be invalid.
+    SourceLoc bufferIndirectlyCausingDiagnostic;
+
     friend class InFlightDiagnostic;
     friend class DiagnosticTransaction;
     
@@ -799,6 +806,27 @@
 
   public:
     static const char *diagnosticStringFor(const DiagID id);
+
+    /// If there is no clear .dia file for a diagnostic, put it in the one
+    /// corresponding to the SourceLoc given here.
+    /// In particular, in batch mode when a diagnostic is located in
+    /// a non-primary file, use this affordance to place it in the .dia
+    /// file for the primary that is currently being worked on.
+    void setBufferIndirectlyCausingDiagnosticToInput(SourceLoc);
+    void resetBufferIndirectlyCausingDiagnostic();
+    SourceLoc getDefaultDiagnosticLoc() const {
+      return bufferIndirectlyCausingDiagnostic;
+    }
+  };
+
+  class BufferIndirectlyCausingDiagnosticRAII {
+  private:
+    DiagnosticEngine &Diags;
+  public:
+    BufferIndirectlyCausingDiagnosticRAII(const SourceFile &SF);
+    ~BufferIndirectlyCausingDiagnosticRAII() {
+      Diags.resetBufferIndirectlyCausingDiagnostic();
+    }
   };
 
   /// Represents a diagnostic transaction. While a transaction is
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 89315e0..bb34f25 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -4099,6 +4099,11 @@
         "should not be referenced from " FRAGILE_FUNC_KIND "3",
         (DescriptiveDeclKind, DeclName, AccessLevel, unsigned, bool))
 
+ERROR(inlinable_decl_ref_implementation_only,
+      none, "%0 %1 cannot be used in an inlinable "
+      "function because its module was imported implementation-only",
+      (DescriptiveDeclKind, DeclName))
+
 #undef FRAGILE_FUNC_KIND
 
 NOTE(resilience_decl_declared_here_public,
diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h
index 35a96b8..1a79036 100644
--- a/include/swift/AST/Module.h
+++ b/include/swift/AST/Module.h
@@ -959,6 +959,10 @@
   /// May be -1, to indicate no association with a buffer.
   int BufferID;
 
+  /// Does this source file have any implementation-only imports?
+  /// If not, we can fast-path module checks.
+  bool HasImplementationOnlyImports = false;
+
   /// The list of protocol conformances that were "used" within this
   /// source file.
   llvm::SetVector<NormalProtocolConformance *> UsedConformances;
@@ -1047,6 +1051,12 @@
   hasTestableOrPrivateImport(AccessLevel accessLevel, const ValueDecl *ofDecl,
                              ImportQueryKind kind = TestableAndPrivate) const;
 
+  bool hasImplementationOnlyImports() const {
+    return HasImplementationOnlyImports;
+  }
+
+  bool isImportedImplementationOnly(const ModuleDecl *module) const;
+
   void clearLookupCache();
 
   void cacheVisibleDecls(SmallVectorImpl<ValueDecl *> &&globals) const;
diff --git a/include/swift/Frontend/PrintingDiagnosticConsumer.h b/include/swift/Frontend/PrintingDiagnosticConsumer.h
index 1b1f1d0..22a7696 100644
--- a/include/swift/Frontend/PrintingDiagnosticConsumer.h
+++ b/include/swift/Frontend/PrintingDiagnosticConsumer.h
@@ -35,11 +35,12 @@
   PrintingDiagnosticConsumer(llvm::raw_ostream &stream = llvm::errs()) :
     Stream(stream) { }
 
-  virtual void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                                DiagnosticKind Kind,
-                                StringRef FormatString,
-                                ArrayRef<DiagnosticArgument> FormatArgs,
-                                const DiagnosticInfo &Info) override;
+  virtual void
+  handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+                   StringRef FormatString,
+                   ArrayRef<DiagnosticArgument> FormatArgs,
+                   const DiagnosticInfo &Info,
+                   SourceLoc bufferIndirectlyCausingDiagnostic) override;
 
   void forceColors() {
     ForceColors = true;
diff --git a/include/swift/Migrator/FixitApplyDiagnosticConsumer.h b/include/swift/Migrator/FixitApplyDiagnosticConsumer.h
index 17c76d8..112cd15 100644
--- a/include/swift/Migrator/FixitApplyDiagnosticConsumer.h
+++ b/include/swift/Migrator/FixitApplyDiagnosticConsumer.h
@@ -62,11 +62,11 @@
   /// output stream.
   void printResult(llvm::raw_ostream &OS) const;
 
-  void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                        DiagnosticKind Kind,
+  void handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
                         StringRef FormatString,
                         ArrayRef<DiagnosticArgument> FormatArgs,
-                        const DiagnosticInfo &Info) override;
+                        const DiagnosticInfo &Info,
+                        SourceLoc bufferIndirectlyCausingDiagnostic) override;
 
   unsigned getNumFixitsApplied() const {
     return NumFixitsApplied;
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index 6a5c740..bcb6eaf 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -1819,7 +1819,7 @@
       
       // The base of a member reference cannot be an existential type.
       if (E->getBase()->getType()->getWithoutSpecifierType()
-            ->isAnyExistentialType()) {
+            ->isExistentialType()) {
         Out << "Member reference into an unopened existential type\n";
         E->dump(Out);
         Out << "\n";
diff --git a/lib/AST/DiagnosticConsumer.cpp b/lib/AST/DiagnosticConsumer.cpp
index bf1982e..ff68b01 100644
--- a/lib/AST/DiagnosticConsumer.cpp
+++ b/lib/AST/DiagnosticConsumer.cpp
@@ -118,6 +118,12 @@
   if (loc.isInvalid())
     return None;
 
+  // What if a there's a FileSpecificDiagnosticConsumer but there are no
+  // subconsumers in it? (This situation occurs for the fix-its
+  // FileSpecificDiagnosticConsumer.) In such a case, bail out now.
+  if (Subconsumers.empty())
+    return None;
+
   // This map is generated on first use and cached, to allow the
   // FileSpecificDiagnosticConsumer to be set up before the source files are
   // actually loaded.
@@ -165,29 +171,62 @@
 void FileSpecificDiagnosticConsumer::handleDiagnostic(
     SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
     StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
-    const DiagnosticInfo &Info) {
+    const DiagnosticInfo &Info,
+    const SourceLoc bufferIndirectlyCausingDiagnostic) {
 
   HasAnErrorBeenConsumed |= Kind == DiagnosticKind::Error;
 
-  Optional<FileSpecificDiagnosticConsumer::Subconsumer *> subconsumer;
+  auto subconsumer =
+      findSubconsumer(SM, Loc, Kind, bufferIndirectlyCausingDiagnostic);
+  if (subconsumer) {
+    subconsumer.getValue()->handleDiagnostic(SM, Loc, Kind, FormatString,
+                                             FormatArgs, Info,
+                                             bufferIndirectlyCausingDiagnostic);
+    return;
+  }
+  // Last resort: spray it everywhere
+  for (auto &subconsumer : Subconsumers)
+    subconsumer.handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs, Info,
+                                 bufferIndirectlyCausingDiagnostic);
+}
+
+Optional<FileSpecificDiagnosticConsumer::Subconsumer *>
+FileSpecificDiagnosticConsumer::findSubconsumer(
+    SourceManager &SM, SourceLoc loc, DiagnosticKind Kind,
+    SourceLoc bufferIndirectlyCausingDiagnostic) {
+  // Ensure that a note goes to the same place as the preceeding non-note.
   switch (Kind) {
   case DiagnosticKind::Error:
   case DiagnosticKind::Warning:
-  case DiagnosticKind::Remark:
-    subconsumer = subconsumerForLocation(SM, Loc);
+  case DiagnosticKind::Remark: {
+    auto subconsumer =
+        findSubconsumerForNonNote(SM, loc, bufferIndirectlyCausingDiagnostic);
     SubconsumerForSubsequentNotes = subconsumer;
-    break;
+    return subconsumer;
+  }
   case DiagnosticKind::Note:
-    subconsumer = SubconsumerForSubsequentNotes;
-    break;
+    return SubconsumerForSubsequentNotes;
   }
-  if (subconsumer.hasValue()) {
-    subconsumer.getValue()->handleDiagnostic(SM, Loc, Kind, FormatString,
-                                             FormatArgs, Info);
-    return;
-  }
-  for (auto &subconsumer : Subconsumers)
-    subconsumer.handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs, Info);
+}
+
+Optional<FileSpecificDiagnosticConsumer::Subconsumer *>
+FileSpecificDiagnosticConsumer::findSubconsumerForNonNote(
+    SourceManager &SM, const SourceLoc loc,
+    const SourceLoc bufferIndirectlyCausingDiagnostic) {
+  const auto subconsumer = subconsumerForLocation(SM, loc);
+  if (!subconsumer)
+    return None; // No place to put it; might be in an imported module
+  if ((*subconsumer)->getConsumer())
+    return subconsumer; // A primary file with a .dia file
+  // Try to put it in the responsible primary input
+  if (bufferIndirectlyCausingDiagnostic.isInvalid())
+    return None;
+  const auto currentPrimarySubconsumer =
+      subconsumerForLocation(SM, bufferIndirectlyCausingDiagnostic);
+  assert(!currentPrimarySubconsumer ||
+         (*currentPrimarySubconsumer)->getConsumer() &&
+             "current primary must have a .dia file");
+  return currentPrimarySubconsumer;
 }
 
 bool FileSpecificDiagnosticConsumer::finishProcessing() {
@@ -214,7 +253,7 @@
 void NullDiagnosticConsumer::handleDiagnostic(
     SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
     StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
-    const DiagnosticInfo &Info) {
+    const DiagnosticInfo &Info, const SourceLoc) {
   LLVM_DEBUG({
     llvm::dbgs() << "NullDiagnosticConsumer received diagnostic: ";
     DiagnosticEngine::formatDiagnosticText(llvm::dbgs(), FormatString,
@@ -229,7 +268,8 @@
 void ForwardingDiagnosticConsumer::handleDiagnostic(
     SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
     StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
-    const DiagnosticInfo &Info) {
+    const DiagnosticInfo &Info,
+    const SourceLoc bufferIndirectlyCausingDiagnostic) {
   LLVM_DEBUG({
     llvm::dbgs() << "ForwardingDiagnosticConsumer received diagnostic: ";
     DiagnosticEngine::formatDiagnosticText(llvm::dbgs(), FormatString,
@@ -237,6 +277,7 @@
     llvm::dbgs() << "\n";
   });
   for (auto *C : TargetEngine.getConsumers()) {
-    C->handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs, Info);
+    C->handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs, Info,
+                        bufferIndirectlyCausingDiagnostic);
   }
 }
diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp
index c3d2861..af76934 100644
--- a/lib/AST/DiagnosticEngine.cpp
+++ b/lib/AST/DiagnosticEngine.cpp
@@ -838,7 +838,8 @@
   for (auto &Consumer : Consumers) {
     Consumer->handleDiagnostic(SourceMgr, loc, toDiagnosticKind(behavior),
                                diagnosticStringFor(Info.ID),
-                               diagnostic.getArgs(), Info);
+                               diagnostic.getArgs(), Info,
+                               getDefaultDiagnosticLoc());
   }
 }
 
@@ -846,6 +847,22 @@
   return diagnosticStrings[(unsigned)id];
 }
 
+void DiagnosticEngine::setBufferIndirectlyCausingDiagnosticToInput(
+    SourceLoc loc) {
+  // If in the future, nested BufferIndirectlyCausingDiagnosticRAII need be
+  // supported, the compiler will need a stack for
+  // bufferIndirectlyCausingDiagnostic.
+  assert(bufferIndirectlyCausingDiagnostic.isInvalid() &&
+         "Buffer should not already be set.");
+  bufferIndirectlyCausingDiagnostic = loc;
+  assert(bufferIndirectlyCausingDiagnostic.isValid() &&
+         "Buffer must be valid for previous assertion to work.");
+}
+
+void DiagnosticEngine::resetBufferIndirectlyCausingDiagnostic() {
+  bufferIndirectlyCausingDiagnostic = SourceLoc();
+}
+
 DiagnosticSuppression::DiagnosticSuppression(DiagnosticEngine &diags)
   : diags(diags)
 {
@@ -856,3 +873,14 @@
   for (auto consumer : consumers)
     diags.addConsumer(*consumer);
 }
+
+BufferIndirectlyCausingDiagnosticRAII::BufferIndirectlyCausingDiagnosticRAII(
+    const SourceFile &SF)
+    : Diags(SF.getASTContext().Diags) {
+  auto id = SF.getBufferID();
+  if (!id)
+    return;
+  auto loc = SF.getASTContext().SourceMgr.getLocForBufferStart(*id);
+  if (loc.isValid())
+    Diags.setBufferIndirectlyCausingDiagnosticToInput(loc);
+}
diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp
index 2012e41..7b4d782 100644
--- a/lib/AST/Module.cpp
+++ b/lib/AST/Module.cpp
@@ -1421,6 +1421,14 @@
   assert(iter == newBuf.end());
 
   Imports = newBuf;
+
+  // Update the HasImplementationOnlyImports flag.
+  if (!HasImplementationOnlyImports) {
+    for (auto &desc : IM) {
+      if (desc.importOptions.contains(ImportFlags::ImplementationOnly))
+        HasImplementationOnlyImports = true;
+    }
+  }
 }
 
 bool SourceFile::hasTestableOrPrivateImport(
@@ -1485,6 +1493,43 @@
                      });
 }
 
+bool SourceFile::isImportedImplementationOnly(const ModuleDecl *module) const {
+  // Implementation-only imports are (currently) always source-file-specific,
+  // so if we don't have any, we know the search is complete.
+  if (!hasImplementationOnlyImports())
+    return false;
+
+  auto isImportedBy = [](const ModuleDecl *dest, const ModuleDecl *src) {
+    // Fast path.
+    if (dest == src) return true;
+
+    // Walk the transitive imports, respecting visibility.
+    // This return true if the search *didn't* short-circuit, and it short
+    // circuits if we found `dest`, so we need to invert the sense before
+    // returning.
+    return !const_cast<ModuleDecl*>(src)
+              ->forAllVisibleModules({}, [dest](ModuleDecl::ImportedModule im) {
+      // Continue searching as long as we haven't found `dest` yet.
+      return im.second != dest;
+    });
+  };
+
+  // Look at the imports of this source file.
+  for (auto &desc : Imports) {
+    // Ignore implementation-only imports.
+    if (desc.importOptions.contains(ImportFlags::ImplementationOnly))
+      continue;
+
+    // If the module is imported this way, it's not imported
+    // implementation-only.
+    if (isImportedBy(module, desc.module.second))
+      return false;
+  }
+
+  // Now check this file's enclosing module in case there are re-exports.
+  return !isImportedBy(module, getParentModule());
+}
+
 void SourceFile::clearLookupCache() {
   if (!Cache)
     return;
diff --git a/lib/Frontend/PrintingDiagnosticConsumer.cpp b/lib/Frontend/PrintingDiagnosticConsumer.cpp
index e391154..1cfdfc6 100644
--- a/lib/Frontend/PrintingDiagnosticConsumer.cpp
+++ b/lib/Frontend/PrintingDiagnosticConsumer.cpp
@@ -66,7 +66,8 @@
 void PrintingDiagnosticConsumer::handleDiagnostic(
     SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
     StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
-    const DiagnosticInfo &Info) {
+    const DiagnosticInfo &Info,
+    const SourceLoc bufferIndirectlyCausingDiagnostic) {
   // Determine what kind of diagnostic we're emitting.
   llvm::SourceMgr::DiagKind SMKind;
   switch (Kind) {
diff --git a/lib/Frontend/SerializedDiagnosticConsumer.cpp b/lib/Frontend/SerializedDiagnosticConsumer.cpp
index 12478fe..e46bada 100644
--- a/lib/Frontend/SerializedDiagnosticConsumer.cpp
+++ b/lib/Frontend/SerializedDiagnosticConsumer.cpp
@@ -191,11 +191,11 @@
     CompilationWasComplete = false;
   }
 
-  void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                                DiagnosticKind Kind,
-                                StringRef FormatString,
-                                ArrayRef<DiagnosticArgument> FormatArgs,
-                                const DiagnosticInfo &Info) override;
+  void handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+                        StringRef FormatString,
+                        ArrayRef<DiagnosticArgument> FormatArgs,
+                        const DiagnosticInfo &Info,
+                        SourceLoc bufferIndirectlyCausingDiagnostic) override;
 
   /// The version of the diagnostics file.
   enum { Version = 1 };
@@ -545,7 +545,8 @@
 void SerializedDiagnosticConsumer::handleDiagnostic(
     SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
     StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
-    const DiagnosticInfo &Info) {
+    const DiagnosticInfo &Info,
+    const SourceLoc bufferIndirectlyCausingDiagnostic) {
 
   // Enter the block for a non-note diagnostic immediately, rather
   // than waiting for beginDiagnostic, in case associated notes
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index b4929a7..3cd4b07 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -406,11 +406,12 @@
       FixitAll(DiagOpts.FixitCodeForAllDiagnostics) {}
 
 private:
-  void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                        DiagnosticKind Kind,
-                        StringRef FormatString,
-                        ArrayRef<DiagnosticArgument> FormatArgs,
-                        const DiagnosticInfo &Info) override {
+  void
+  handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+                   StringRef FormatString,
+                   ArrayRef<DiagnosticArgument> FormatArgs,
+                   const DiagnosticInfo &Info,
+                   const SourceLoc bufferIndirectlyCausingDiagnostic) override {
     if (!(FixitAll || shouldTakeFixit(Kind, Info)))
       return;
     for (const auto &Fix : Info.FixIts) {
@@ -1219,6 +1220,10 @@
   SILOptions &SILOpts = Invocation.getSILOptions();
   IRGenOptions &IRGenOpts = Invocation.getIRGenOptions();
 
+  Optional<BufferIndirectlyCausingDiagnosticRAII> ricd;
+  if (auto *SF = MSF.dyn_cast<SourceFile *>())
+    ricd.emplace(*SF);
+
   if (Stats)
     countStatsPostSILGen(*Stats, *SM);
 
@@ -1541,13 +1546,18 @@
           subconsumers.emplace_back(input.file(), std::move(consumer));
         return false;
       });
-  // For batch mode, the compiler must swallow diagnostics pertaining to
-  // non-primary files in order to avoid Xcode showing the same diagnostic
+  // For batch mode, the compiler must sometimes swallow diagnostics pertaining
+  // to non-primary files in order to avoid Xcode showing the same diagnostic
   // multiple times. So, create a diagnostic "eater" for those non-primary
   // files.
+  //
+  // This routine gets called in cases where no primary subconsumers are created.
+  // Don't bother to create non-primary subconsumers if there aren't any primary
+  // ones.
+  //
   // To avoid introducing bugs into WMO or single-file modes, test for multiple
   // primaries.
-  if (inputsAndOutputs.hasMultiplePrimaryInputs()) {
+  if (!subconsumers.empty() && inputsAndOutputs.hasMultiplePrimaryInputs()) {
     inputsAndOutputs.forEachNonPrimaryInput(
         [&](const InputFile &input) -> bool {
           subconsumers.emplace_back(input.file(), nullptr);
@@ -1628,11 +1638,11 @@
 
     PDC.handleDiagnostic(dummyMgr, SourceLoc(), DiagnosticKind::Error,
                          "fatal error encountered during compilation; please "
-                           "file a bug report with your project and the crash "
-                           "log", {},
-                         DiagnosticInfo());
+                         "file a bug report with your project and the crash "
+                         "log",
+                         {}, DiagnosticInfo(), SourceLoc());
     PDC.handleDiagnostic(dummyMgr, SourceLoc(), DiagnosticKind::Note, reason,
-                         {}, DiagnosticInfo());
+                         {}, DiagnosticInfo(), SourceLoc());
     if (shouldCrash)
       abort();
   };
diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp
index 0c6e77b..de75273 100644
--- a/lib/IDE/CodeCompletion.cpp
+++ b/lib/IDE/CodeCompletion.cpp
@@ -1641,6 +1641,7 @@
 
   void setExpectedTypes(ArrayRef<Type> Types, bool isSingleExpressionBody) {
     expectedTypeContext.isSingleExpressionBody = isSingleExpressionBody;
+    expectedTypeContext.possibleTypes.clear();
     expectedTypeContext.possibleTypes.reserve(Types.size());
     for (auto T : Types)
       if (T)
@@ -2242,22 +2243,56 @@
     Builder.addRightParen();
   }
 
+  SemanticContextKind getSemanticContextKind(const AbstractFunctionDecl *AFD) {
+    // FIXME: to get the corect semantic context we need to know how lookup
+    // would have found the declaration AFD. For now, just infer a reasonable
+    // semantics.
+
+    if (!AFD)
+      return SemanticContextKind::CurrentModule;
+
+    DeclContext *calleeDC = AFD->getDeclContext();
+    
+    if (calleeDC->isTypeContext())
+      // FIXME: We should distinguish CurrentNominal and Super. We need to
+      // propagate the base type to do that.
+      return SemanticContextKind::CurrentNominal;
+
+    if (calleeDC->isLocalContext())
+      return SemanticContextKind::Local;
+    if (calleeDC->getParentModule() == CurrDeclContext->getParentModule())
+      return SemanticContextKind::CurrentModule;
+
+    return SemanticContextKind::OtherModule;
+  }
+
   void addFunctionCallPattern(const AnyFunctionType *AFT,
                               const AbstractFunctionDecl *AFD = nullptr) {
+    if (AFD) {
+      auto genericSig =
+          AFD->getInnermostDeclContext()->getGenericSignatureOfContext();
+      AFT = eraseArchetypes(CurrDeclContext->getParentModule(),
+                            const_cast<AnyFunctionType *>(AFT), genericSig)
+                ->castTo<AnyFunctionType>();
+    }
 
     // Add the pattern, possibly including any default arguments.
     auto addPattern = [&](ArrayRef<const ParamDecl *> declParams = {},
                           bool includeDefaultArgs = true) {
-      // FIXME: to get the corect semantic context we need to know how lookup
-      // would have found the declaration AFD. For now, just choose a reasonable
-      // default, it's most likely to be CurrentModule or CurrentNominal.
+      CommandWordsPairs Pairs;
       CodeCompletionResultBuilder Builder(
-          Sink, CodeCompletionResult::ResultKind::Pattern,
-          SemanticContextKind::CurrentModule, expectedTypeContext);
+          Sink,
+          AFD ? CodeCompletionResult::ResultKind::Declaration
+              : CodeCompletionResult::ResultKind::Pattern,
+          getSemanticContextKind(AFD), expectedTypeContext);
       if (!HaveLParen)
         Builder.addLeftParen();
       else
         Builder.addAnnotatedLeftParen();
+      if (AFD) {
+        Builder.setAssociatedDecl(AFD);
+        setClangDeclKeywords(AFD, Pairs, Builder);
+      }
 
       addCallArgumentPatterns(Builder, AFT->getParams(), declParams,
                               includeDefaultArgs);
@@ -5066,14 +5101,17 @@
     Lookup.setHaveLParen(true);
 
     ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);
-    Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
-                            ContextInfo.isSingleExpressionBody());
+
     if (ShouldCompleteCallPatternAfterParen) {
-      if (ExprType) {
+      ExprContextInfo ParentContextInfo(CurDeclContext, ParsedExpr);
+      Lookup.setExpectedTypes(ParentContextInfo.getPossibleTypes(),
+                              ParentContextInfo.isSingleExpressionBody());
+      if (ExprType && ((*ExprType)->is<AnyFunctionType>() ||
+                       (*ExprType)->is<AnyMetatypeType>())) {
         Lookup.getValueExprCompletions(*ExprType, ReferencedDecl.getDecl());
       } else {
         for (auto &typeAndDecl : ContextInfo.getPossibleCallees())
-          Lookup.getValueExprCompletions(typeAndDecl.first, typeAndDecl.second);
+          Lookup.tryFunctionCallCompletions(typeAndDecl.first, typeAndDecl.second);
       }
     } else {
       // Add argument labels, then fallthrough to get values.
@@ -5083,6 +5121,8 @@
     if (!Lookup.FoundFunctionCalls ||
         (Lookup.FoundFunctionCalls &&
          Lookup.FoundFunctionsWithoutFirstKeyword)) {
+      Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
+                              ContextInfo.isSingleExpressionBody());
       Lookup.setHaveLParen(false);
       DoPostfixExprBeginning();
     }
diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp
index 2e7776a..c0352d3 100644
--- a/lib/IDE/ExprContextAnalysis.cpp
+++ b/lib/IDE/ExprContextAnalysis.cpp
@@ -16,6 +16,7 @@
 #include "swift/AST/Decl.h"
 #include "swift/AST/DeclContext.h"
 #include "swift/AST/Expr.h"
+#include "swift/AST/GenericSignature.h"
 #include "swift/AST/Initializer.h"
 #include "swift/AST/LazyResolver.h"
 #include "swift/AST/Module.h"
@@ -194,7 +195,7 @@
 class ExprParentFinder : public ASTWalker {
   friend class ExprContextAnalyzer;
   Expr *ChildExpr;
-  llvm::function_ref<bool(ParentTy, ParentTy)> Predicate;
+  std::function<bool(ParentTy, ParentTy)> Predicate;
 
   bool arePositionsSame(Expr *E1, Expr *E2) {
     return E1->getSourceRange().Start == E2->getSourceRange().Start &&
@@ -204,7 +205,7 @@
 public:
   llvm::SmallVector<ParentTy, 5> Ancestors;
   ExprParentFinder(Expr *ChildExpr,
-                   llvm::function_ref<bool(ParentTy, ParentTy)> Predicate)
+                   std::function<bool(ParentTy, ParentTy)> Predicate)
       : ChildExpr(ChildExpr), Predicate(Predicate) {}
 
   std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
@@ -271,7 +272,8 @@
   SmallVector<ValueDecl *, 2> decls;
   auto resolver = DC.getASTContext().getLazyResolver();
   if (!DC.lookupQualified(baseTy->getMetatypeInstanceType(), name,
-                          NL_QualifiedDefault, resolver, decls))
+                          NL_QualifiedDefault | NL_ProtocolMembers, resolver,
+                          decls))
     return;
 
   for (auto *VD : decls) {
@@ -303,8 +305,19 @@
 
     if (!fnType)
       continue;
-    if (auto *AFT = fnType->getAs<AnyFunctionType>()) {
-      candidates.emplace_back(AFT, VD);
+
+    if (fnType->is<AnyFunctionType>()) {
+      auto baseInstanceTy = baseTy->getMetatypeInstanceType();
+      // If we are calling to typealias type, 
+      if (isa<SugarType>(baseInstanceTy.getPointer())) {
+        auto canBaseTy = baseInstanceTy->getCanonicalType();
+        fnType = fnType.transform([&](Type t) -> Type {
+          if (t->getCanonicalType()->isEqual(canBaseTy))
+            return baseInstanceTy;
+          return t;
+        });
+      }
+      candidates.emplace_back(fnType->castTo<AnyFunctionType>(), VD);
     }
   }
 }
@@ -657,15 +670,23 @@
     if (!ParsedExpr)
       return;
 
-    ExprParentFinder Finder(ParsedExpr, [](ASTWalker::ParentTy Node,
-                                           ASTWalker::ParentTy Parent) {
+    ExprParentFinder Finder(ParsedExpr, [&](ASTWalker::ParentTy Node,
+                                            ASTWalker::ParentTy Parent) {
       if (auto E = Node.getAsExpr()) {
         switch (E->getKind()) {
-        case ExprKind::Call:
+        case ExprKind::Call: {
+          // Iff the cursor is in argument position.
+          auto argsRange = cast<CallExpr>(E)->getArg()->getSourceRange();
+          return SM.rangeContains(argsRange, ParsedExpr->getSourceRange());
+        }
+        case ExprKind::Subscript: {
+          // Iff the cursor is in index position.
+          auto argsRange = cast<SubscriptExpr>(E)->getIndex()->getSourceRange();
+          return SM.rangeContains(argsRange, ParsedExpr->getSourceRange());
+        }
         case ExprKind::Binary:
         case ExprKind::PrefixUnary:
         case ExprKind::Assign:
-        case ExprKind::Subscript:
         case ExprKind::Array:
           return true;
         case ExprKind::Tuple: {
diff --git a/lib/Migrator/FixitApplyDiagnosticConsumer.cpp b/lib/Migrator/FixitApplyDiagnosticConsumer.cpp
index c2bd92b..5e040ec 100644
--- a/lib/Migrator/FixitApplyDiagnosticConsumer.cpp
+++ b/lib/Migrator/FixitApplyDiagnosticConsumer.cpp
@@ -31,12 +31,11 @@
   RewriteBuf.write(OS);
 }
 
-void FixitApplyDiagnosticConsumer::
-handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                 DiagnosticKind Kind,
-                 StringRef FormatString,
-                 ArrayRef<DiagnosticArgument> FormatArgs,
-                 const DiagnosticInfo &Info) {
+void FixitApplyDiagnosticConsumer::handleDiagnostic(
+    SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+    StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
+    const DiagnosticInfo &Info,
+    const SourceLoc bufferIndirectlyCausingDiagnostic) {
   if (Loc.isInvalid()) {
     return;
   }
diff --git a/lib/SILGen/CMakeLists.txt b/lib/SILGen/CMakeLists.txt
index d502c77..76802fc 100644
--- a/lib/SILGen/CMakeLists.txt
+++ b/lib/SILGen/CMakeLists.txt
@@ -28,6 +28,7 @@
   SILGenPoly.cpp
   SILGenProlog.cpp
   SILGenStmt.cpp
+  SILGenSILBuilder.cpp
   SILGenThunk.cpp
   SILGenType.cpp)
 target_link_libraries(swiftSILGen PRIVATE
diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp
index d6c2bd4..b5fb726 100644
--- a/lib/SILGen/SILGenBuilder.cpp
+++ b/lib/SILGen/SILGenBuilder.cpp
@@ -33,153 +33,15 @@
 //===----------------------------------------------------------------------===//
 
 SILGenBuilder::SILGenBuilder(SILGenFunction &SGF)
-    : SILBuilder(SGF.F), SGF(SGF) {}
+    : SILGenSILBuilder(SGF), SGF(SGF) {}
 
 SILGenBuilder::SILGenBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB,
                              SmallVectorImpl<SILInstruction *> *insertedInsts)
-    : SILBuilder(insertBB, insertedInsts), SGF(SGF) {}
+    : SILGenSILBuilder(SGF, insertBB, insertedInsts), SGF(SGF) {}
 
 SILGenBuilder::SILGenBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB,
                              SILBasicBlock::iterator insertInst)
-    : SILBuilder(insertBB, insertInst), SGF(SGF) {}
-
-//===----------------------------------------------------------------------===//
-//              Instruction Emission + Conformance Endowed APIs
-//===----------------------------------------------------------------------===//
-//
-// This section contains wrappers around SILBuilder SILValue APIs that add extra
-// conformances. These are the only places where we should be accessing
-// SILBuilder APIs directly.
-//
-
-MetatypeInst *SILGenBuilder::createMetatype(SILLocation loc, SILType metatype) {
-  auto theMetatype = metatype.castTo<MetatypeType>();
-  // Getting a nontrivial metatype requires forcing any conformances necessary
-  // to instantiate the type.
-  switch (theMetatype->getRepresentation()) {
-  case MetatypeRepresentation::Thin:
-    break;
-  case MetatypeRepresentation::Thick:
-  case MetatypeRepresentation::ObjC: {
-    // Walk the type recursively to look for substitutions we may need.
-    theMetatype.getInstanceType().findIf([&](Type t) -> bool {
-      auto *decl = t->getAnyNominal();
-      if (!decl)
-        return false;
-
-      if (isa<ProtocolDecl>(decl))
-        return false;
-
-      auto *genericSig = decl->getGenericSignature();
-      if (!genericSig)
-        return false;
-
-      auto subMap = t->getContextSubstitutionMap(getSILGenModule().SwiftModule,
-                                                 decl);
-      getSILGenModule().useConformancesFromSubstitutions(subMap);
-      return false;
-    });
-
-    break;
-  }
-  }
-
-  return SILBuilder::createMetatype(loc, metatype);
-}
-
-ApplyInst *SILGenBuilder::createApply(SILLocation loc, SILValue fn,
-                                      SILType substFnTy, SILType result,
-                                      SubstitutionMap subs,
-                                      ArrayRef<SILValue> args) {
-  getSILGenModule().useConformancesFromSubstitutions(subs);
-  return SILBuilder::createApply(loc, fn, subs, args, false);
-}
-
-TryApplyInst *
-SILGenBuilder::createTryApply(SILLocation loc, SILValue fn, SILType substFnTy,
-                              SubstitutionMap subs, ArrayRef<SILValue> args,
-                              SILBasicBlock *normalBB, SILBasicBlock *errorBB) {
-  getSILGenModule().useConformancesFromSubstitutions(subs);
-  return SILBuilder::createTryApply(loc, fn, subs, args, normalBB, errorBB);
-}
-
-BeginApplyInst *
-SILGenBuilder::createBeginApply(SILLocation loc, SILValue fn,
-                                SubstitutionMap subs,
-                                ArrayRef<SILValue> args) {
-  getSILGenModule().useConformancesFromSubstitutions(subs);
-  return SILBuilder::createBeginApply(loc, fn, subs, args, false);
-}
-
-PartialApplyInst *
-SILGenBuilder::createPartialApply(SILLocation loc, SILValue fn,
-                                  SILType substFnTy, SubstitutionMap subs,
-                                  ArrayRef<SILValue> args, SILType closureTy) {
-  getSILGenModule().useConformancesFromSubstitutions(subs);
-  return SILBuilder::createPartialApply(
-      loc, fn, subs, args,
-      closureTy.getAs<SILFunctionType>()->getCalleeConvention());
-}
-
-
-BuiltinInst *SILGenBuilder::createBuiltin(SILLocation loc, Identifier name,
-                                          SILType resultTy,
-                                          SubstitutionMap subs,
-                                          ArrayRef<SILValue> args) {
-  getSILGenModule().useConformancesFromSubstitutions(subs);
-  return SILBuilder::createBuiltin(loc, name, resultTy, subs, args);
-}
-
-InitExistentialAddrInst *SILGenBuilder::createInitExistentialAddr(
-    SILLocation loc, SILValue existential, CanType formalConcreteType,
-    SILType loweredConcreteType,
-    ArrayRef<ProtocolConformanceRef> conformances) {
-  for (auto conformance : conformances)
-    getSILGenModule().useConformance(conformance);
-
-  return SILBuilder::createInitExistentialAddr(
-      loc, existential, formalConcreteType, loweredConcreteType, conformances);
-}
-
-InitExistentialValueInst *SILGenBuilder::createInitExistentialValue(
-    SILLocation Loc, SILType ExistentialType, CanType FormalConcreteType,
-    SILValue Concrete, ArrayRef<ProtocolConformanceRef> Conformances) {
-  for (auto conformance : Conformances)
-    getSILGenModule().useConformance(conformance);
-
-  return SILBuilder::createInitExistentialValue(
-      Loc, ExistentialType, FormalConcreteType, Concrete, Conformances);
-}
-
-InitExistentialMetatypeInst *SILGenBuilder::createInitExistentialMetatype(
-    SILLocation loc, SILValue metatype, SILType existentialType,
-    ArrayRef<ProtocolConformanceRef> conformances) {
-  for (auto conformance : conformances)
-    getSILGenModule().useConformance(conformance);
-
-  return SILBuilder::createInitExistentialMetatype(
-      loc, metatype, existentialType, conformances);
-}
-
-InitExistentialRefInst *SILGenBuilder::createInitExistentialRef(
-    SILLocation loc, SILType existentialType, CanType formalConcreteType,
-    SILValue concreteValue, ArrayRef<ProtocolConformanceRef> conformances) {
-  for (auto conformance : conformances)
-    getSILGenModule().useConformance(conformance);
-
-  return SILBuilder::createInitExistentialRef(
-      loc, existentialType, formalConcreteType, concreteValue, conformances);
-}
-
-AllocExistentialBoxInst *SILGenBuilder::createAllocExistentialBox(
-    SILLocation loc, SILType existentialType, CanType concreteType,
-    ArrayRef<ProtocolConformanceRef> conformances) {
-  for (auto conformance : conformances)
-    getSILGenModule().useConformance(conformance);
-
-  return SILBuilder::createAllocExistentialBox(loc, existentialType,
-                                               concreteType, conformances);
-}
+    : SILGenSILBuilder(SGF, insertBB, insertInst), SGF(SGF) {}
 
 //===----------------------------------------------------------------------===//
 //                             Managed Value APIs
@@ -209,8 +71,8 @@
                                      SILType resultTy,
                                      bool withoutActuallyEscaping) {
   CleanupCloner cloner(*this, fn);
-  SILValue result = SILBuilder::createConvertFunction(
-      loc, fn.forward(getSILGenFunction()), resultTy, withoutActuallyEscaping);
+  SILValue result = createConvertFunction(loc, fn.forward(getSILGenFunction()),
+                                          resultTy, withoutActuallyEscaping);
   return cloner.clone(result);
 }
 
@@ -741,7 +603,7 @@
   CleanupCloner cloner(*this, value);
   SILValue cast = createUncheckedBitCast(loc, value.getValue(), type);
 
-  // Currently SILBuilder::createUncheckedBitCast only produces these
+  // Currently createUncheckedBitCast only produces these
   // instructions. We assert here to make sure if this changes, this code is
   // updated.
   assert((isa<UncheckedTrivialBitCastInst>(cast) ||
@@ -962,14 +824,14 @@
     SILLocation loc, ManagedValue value,
     llvm::function_ref<void(unsigned, ManagedValue)> func) {
   CleanupCloner cloner(*this, value);
-  SILBuilder::emitDestructureValueOperation(
-      loc, value.forward(SGF), [&](unsigned index, SILValue subValue) {
-        return func(index, cloner.clone(subValue));
-      });
+  emitDestructureValueOperation(loc, value.forward(SGF),
+                                [&](unsigned index, SILValue subValue) {
+                                  return func(index, cloner.clone(subValue));
+                                });
 }
 
 ManagedValue SILGenBuilder::createProjectBox(SILLocation loc, ManagedValue mv,
                                              unsigned index) {
-  auto *pbi = SILBuilder::createProjectBox(loc, mv.getValue(), index);
+  auto *pbi = createProjectBox(loc, mv.getValue(), index);
   return ManagedValue::forUnmanaged(pbi);
 }
diff --git a/lib/SILGen/SILGenBuilder.h b/lib/SILGen/SILGenBuilder.h
index b563917..ee1cbe8 100644
--- a/lib/SILGen/SILGenBuilder.h
+++ b/lib/SILGen/SILGenBuilder.h
@@ -26,8 +26,8 @@
 #include "JumpDest.h"
 #include "ManagedValue.h"
 #include "RValue.h"
+#include "SILGenSILBuilder.h"
 #include "swift/Basic/ProfileCounter.h"
-#include "swift/SIL/SILBuilder.h"
 
 namespace swift {
 namespace Lowering {
@@ -40,7 +40,7 @@
 ///
 /// The goal is to make this eventually composed with SILBuilder so that all
 /// APIs only vend ManagedValues.
-class SILGenBuilder : public SILBuilder {
+class SILGenBuilder : public SILGenSILBuilder {
   SILGenFunction &SGF;
 
 public:
@@ -53,40 +53,25 @@
   // Create a new builder, inheriting the given builder's context and debug
   // scope.
   SILGenBuilder(SILGenBuilder &builder, SILBasicBlock *insertBB)
-    : SILBuilder(insertBB, builder.getCurrentDebugScope(),
-                 builder.getBuilderContext()),
-      SGF(builder.SGF)
-  {}
+      : SILGenSILBuilder(builder.SGF, insertBB, builder.getCurrentDebugScope(),
+                         builder.getBuilderContext()),
+        SGF(builder.SGF) {}
 
   SILGenModule &getSILGenModule() const;
   SILGenFunction &getSILGenFunction() const { return SGF; }
 
-  // Metatype instructions use the conformances necessary to instantiate the
-  // type.
+  using SILGenSILBuilder::createInitExistentialValue;
+  ManagedValue
+  createInitExistentialValue(SILLocation loc, SILType existentialType,
+                             CanType formalConcreteType, ManagedValue concrete,
+                             ArrayRef<ProtocolConformanceRef> conformances);
+  using SILGenSILBuilder::createInitExistentialRef;
+  ManagedValue
+  createInitExistentialRef(SILLocation loc, SILType existentialType,
+                           CanType formalConcreteType, ManagedValue concrete,
+                           ArrayRef<ProtocolConformanceRef> conformances);
 
-  MetatypeInst *createMetatype(SILLocation loc, SILType metatype);
-
-  // Generic apply instructions use the conformances necessary to form the call.
-
-  using SILBuilder::createApply;
-
-  ApplyInst *createApply(SILLocation loc, SILValue fn, SILType SubstFnTy,
-                         SILType result, SubstitutionMap subs,
-                         ArrayRef<SILValue> args);
-
-  TryApplyInst *createTryApply(SILLocation loc, SILValue fn, SILType substFnTy,
-                               SubstitutionMap subs,
-                               ArrayRef<SILValue> args, SILBasicBlock *normalBB,
-                               SILBasicBlock *errorBB);
-
-  BeginApplyInst *createBeginApply(SILLocation loc, SILValue fn,
-                                   SubstitutionMap subs,
-                                   ArrayRef<SILValue> args);
-
-  PartialApplyInst *createPartialApply(SILLocation loc, SILValue fn,
-                                       SILType substFnTy, SubstitutionMap subs,
-                                       ArrayRef<SILValue> args,
-                                       SILType closureTy);
+  using SILGenSILBuilder::createPartialApply;
   ManagedValue createPartialApply(SILLocation loc, SILValue fn,
                                   SILType substFnTy, SubstitutionMap subs,
                                   ArrayRef<ManagedValue> args,
@@ -99,60 +84,15 @@
                               closureTy);
   }
 
-  BuiltinInst *createBuiltin(SILLocation loc, Identifier name, SILType resultTy,
-                             SubstitutionMap subs, ArrayRef<SILValue> args);
-
-  // Existential containers use the conformances needed by the existential
-  // box.
-
-  InitExistentialAddrInst *
-  createInitExistentialAddr(SILLocation loc, SILValue existential,
-                            CanType formalConcreteType,
-                            SILType loweredConcreteType,
-                            ArrayRef<ProtocolConformanceRef> conformances);
-
-  InitExistentialValueInst *
-  createInitExistentialValue(SILLocation loc, SILType existentialType,
-                             CanType formalConcreteType, SILValue concrete,
-                             ArrayRef<ProtocolConformanceRef> conformances);
-  ManagedValue
-  createInitExistentialValue(SILLocation loc, SILType existentialType,
-                             CanType formalConcreteType, ManagedValue concrete,
-                             ArrayRef<ProtocolConformanceRef> conformances);
-
-  InitExistentialMetatypeInst *
-  createInitExistentialMetatype(SILLocation loc, SILValue metatype,
-                                SILType existentialType,
-                                ArrayRef<ProtocolConformanceRef> conformances);
-
-  InitExistentialRefInst *
-  createInitExistentialRef(SILLocation loc, SILType existentialType,
-                           CanType formalConcreteType, SILValue concreteValue,
-                           ArrayRef<ProtocolConformanceRef> conformances);
-
-  ManagedValue
-  createInitExistentialRef(SILLocation loc, SILType existentialType,
-                           CanType formalConcreteType, ManagedValue concrete,
-                           ArrayRef<ProtocolConformanceRef> conformances);
-
-  AllocExistentialBoxInst *
-  createAllocExistentialBox(SILLocation loc, SILType existentialType,
-                            CanType concreteType,
-                            ArrayRef<ProtocolConformanceRef> conformances);
-
-  //===---
-  // Ownership Endowed APIs
-  //
-
-  using SILBuilder::createStructExtract;
+  using SILGenSILBuilder::createStructExtract;
   ManagedValue createStructExtract(SILLocation loc, ManagedValue base,
                                    VarDecl *decl);
 
-  using SILBuilder::createRefElementAddr;
+  using SILGenSILBuilder::createRefElementAddr;
   ManagedValue createRefElementAddr(SILLocation loc, ManagedValue operand,
                                     VarDecl *field, SILType resultTy);
 
-  using SILBuilder::createCopyValue;
+  using SILGenSILBuilder::createCopyValue;
 
   /// Emit a +1 copy on \p originalValue that lives until the end of the current
   /// lexical scope.
@@ -177,9 +117,9 @@
   ManagedValue createFormalAccessCopyValue(SILLocation loc,
                                            ManagedValue originalValue);
 
-#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
-  using SILBuilder::createCopy##Name##Value; \
-  ManagedValue createCopy##Name##Value(SILLocation loc, \
+#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...)            \
+  using SILGenSILBuilder::createCopy##Name##Value;                             \
+  ManagedValue createCopy##Name##Value(SILLocation loc,                        \
                                        ManagedValue originalValue);
 #define UNCHECKED_REF_STORAGE(Name, ...) \
   ManagedValue createUnsafeCopy##Name##Value(SILLocation loc, \
@@ -189,40 +129,40 @@
   ManagedValue createOwnedPhiArgument(SILType type);
   ManagedValue createGuaranteedPhiArgument(SILType type);
 
-  using SILBuilder::createMarkUninitialized;
+  using SILGenSILBuilder::createMarkUninitialized;
   ManagedValue createMarkUninitialized(ValueDecl *decl, ManagedValue operand,
                                        MarkUninitializedInst::Kind muKind);
 
-  using SILBuilder::createAllocRef;
+  using SILGenSILBuilder::createAllocRef;
   ManagedValue createAllocRef(SILLocation loc, SILType refType, bool objc,
                               bool canAllocOnStack,
                               ArrayRef<SILType> elementTypes,
                               ArrayRef<ManagedValue> elementCountOperands);
-  using SILBuilder::createAllocRefDynamic;
+  using SILGenSILBuilder::createAllocRefDynamic;
   ManagedValue
   createAllocRefDynamic(SILLocation loc, ManagedValue operand, SILType refType,
                         bool objc, ArrayRef<SILType> elementTypes,
                         ArrayRef<ManagedValue> elementCountOperands);
 
-  using SILBuilder::createTuple;
+  using SILGenSILBuilder::createTuple;
   ManagedValue createTuple(SILLocation loc, SILType type,
                            ArrayRef<ManagedValue> elements);
-  using SILBuilder::createTupleExtract;
+  using SILGenSILBuilder::createTupleExtract;
   ManagedValue createTupleExtract(SILLocation loc, ManagedValue value,
                                   unsigned index, SILType type);
   ManagedValue createTupleExtract(SILLocation loc, ManagedValue value,
                                   unsigned index);
-  using SILBuilder::createTupleElementAddr;
+  using SILGenSILBuilder::createTupleElementAddr;
   ManagedValue createTupleElementAddr(SILLocation loc, ManagedValue addr,
                                       unsigned index, SILType type);
   ManagedValue createTupleElementAddr(SILLocation loc, ManagedValue addr,
                                       unsigned index);
 
-  using SILBuilder::createLoadBorrow;
+  using SILGenSILBuilder::createLoadBorrow;
   ManagedValue createLoadBorrow(SILLocation loc, ManagedValue base);
   ManagedValue createFormalAccessLoadBorrow(SILLocation loc, ManagedValue base);
 
-  using SILBuilder::createStoreBorrow;
+  using SILGenSILBuilder::createStoreBorrow;
   void createStoreBorrow(SILLocation loc, ManagedValue value, SILValue address);
 
   /// Create a store_borrow if we have a non-trivial value and a store [trivial]
@@ -241,11 +181,11 @@
                              const TypeLowering &lowering, SGFContext context,
                              llvm::function_ref<void(SILValue)> rvalueEmitter);
 
-  using SILBuilder::createUncheckedEnumData;
+  using SILGenSILBuilder::createUncheckedEnumData;
   ManagedValue createUncheckedEnumData(SILLocation loc, ManagedValue operand,
                                        EnumElementDecl *element);
 
-  using SILBuilder::createUncheckedTakeEnumDataAddr;
+  using SILGenSILBuilder::createUncheckedTakeEnumDataAddr;
   ManagedValue createUncheckedTakeEnumDataAddr(SILLocation loc, ManagedValue operand,
                                                EnumElementDecl *element, SILType ty);
 
@@ -271,7 +211,7 @@
   ManagedValue createInputFunctionArgument(SILType type,
                                            Optional<SILLocation> loc);
 
-  using SILBuilder::createEnum;
+  using SILGenSILBuilder::createEnum;
   ManagedValue createEnum(SILLocation loc, ManagedValue payload,
                           EnumElementDecl *decl, SILType type);
 
@@ -282,16 +222,16 @@
                             const TypeLowering &lowering, SGFContext context,
                             llvm::function_ref<void(SILValue)> rvalueEmitter);
 
-  using SILBuilder::createUnconditionalCheckedCastValue;
+  using SILGenSILBuilder::createUnconditionalCheckedCastValue;
   ManagedValue
   createUnconditionalCheckedCastValue(SILLocation loc,
                                       ManagedValue operand, SILType type);
-  using SILBuilder::createUnconditionalCheckedCast;
+  using SILGenSILBuilder::createUnconditionalCheckedCast;
   ManagedValue createUnconditionalCheckedCast(SILLocation loc,
                                               ManagedValue operand,
                                               SILType type);
 
-  using SILBuilder::createCheckedCastBranch;
+  using SILGenSILBuilder::createCheckedCastBranch;
   void createCheckedCastBranch(SILLocation loc, bool isExact,
                                ManagedValue operand, SILType type,
                                SILBasicBlock *trueBlock,
@@ -299,49 +239,49 @@
                                ProfileCounter Target1Count,
                                ProfileCounter Target2Count);
 
-  using SILBuilder::createCheckedCastValueBranch;
+  using SILGenSILBuilder::createCheckedCastValueBranch;
   void createCheckedCastValueBranch(SILLocation loc, ManagedValue operand,
                                     SILType type, SILBasicBlock *trueBlock,
                                     SILBasicBlock *falseBlock);
 
-  using SILBuilder::createUpcast;
+  using SILGenSILBuilder::createUpcast;
   ManagedValue createUpcast(SILLocation loc, ManagedValue original,
                             SILType type);
 
-  using SILBuilder::tryCreateUncheckedRefCast;
+  using SILGenSILBuilder::tryCreateUncheckedRefCast;
   ManagedValue tryCreateUncheckedRefCast(SILLocation loc, ManagedValue original,
                                          SILType type);
 
-  using SILBuilder::createUncheckedTrivialBitCast;
+  using SILGenSILBuilder::createUncheckedTrivialBitCast;
   ManagedValue createUncheckedTrivialBitCast(SILLocation loc,
                                              ManagedValue original,
                                              SILType type);
 
-  using SILBuilder::createUncheckedRefCast;
+  using SILGenSILBuilder::createUncheckedRefCast;
   ManagedValue createUncheckedRefCast(SILLocation loc, ManagedValue original,
                                       SILType type);
 
-  using SILBuilder::createUncheckedAddrCast;
+  using SILGenSILBuilder::createUncheckedAddrCast;
   ManagedValue createUncheckedAddrCast(SILLocation loc, ManagedValue op,
                                        SILType resultTy);
 
-  using SILBuilder::createUncheckedBitCast;
+  using SILGenSILBuilder::createUncheckedBitCast;
   ManagedValue createUncheckedBitCast(SILLocation loc, ManagedValue original,
                                       SILType type);
 
-  using SILBuilder::createOpenExistentialRef;
+  using SILGenSILBuilder::createOpenExistentialRef;
   ManagedValue createOpenExistentialRef(SILLocation loc, ManagedValue arg,
                                         SILType openedType);
 
-  using SILBuilder::createOpenExistentialValue;
+  using SILGenSILBuilder::createOpenExistentialValue;
   ManagedValue createOpenExistentialValue(SILLocation loc,
                                           ManagedValue original, SILType type);
 
-  using SILBuilder::createOpenExistentialBoxValue;
+  using SILGenSILBuilder::createOpenExistentialBoxValue;
   ManagedValue createOpenExistentialBoxValue(SILLocation loc,
                                           ManagedValue original, SILType type);
 
-  using SILBuilder::createOpenExistentialMetatype;
+  using SILGenSILBuilder::createOpenExistentialMetatype;
   ManagedValue createOpenExistentialMetatype(SILLocation loc,
                                              ManagedValue value,
                                              SILType openedType);
@@ -350,7 +290,7 @@
   ManagedValue createBlockToAnyObject(SILLocation loc, ManagedValue block,
                                       SILType type);
 
-  using SILBuilder::createOptionalSome;
+  using SILGenSILBuilder::createOptionalSome;
   ManagedValue createOptionalSome(SILLocation Loc, ManagedValue Arg);
   ManagedValue createManagedOptionalNone(SILLocation Loc, SILType Type);
 
@@ -358,17 +298,17 @@
   // are removed.
   ManagedValue createManagedFunctionRef(SILLocation loc, SILFunction *f);
 
-  using SILBuilder::createConvertFunction;
+  using SILGenSILBuilder::createConvertFunction;
   ManagedValue createConvertFunction(SILLocation loc, ManagedValue fn,
                                      SILType resultTy,
                                      bool WithoutActuallyEscaping = false);
 
-  using SILBuilder::createConvertEscapeToNoEscape;
+  using SILGenSILBuilder::createConvertEscapeToNoEscape;
   ManagedValue
   createConvertEscapeToNoEscape(SILLocation loc, ManagedValue fn,
                                 SILType resultTy);
 
-  using SILBuilder::createStore;
+  using SILGenSILBuilder::createStore;
   /// Forward \p value into \p address.
   ///
   /// This will forward value's cleanup (if it has one) into the equivalent
@@ -378,41 +318,41 @@
   ManagedValue createStore(SILLocation loc, ManagedValue value,
                            SILValue address, StoreOwnershipQualifier qualifier);
 
-  using SILBuilder::createSuperMethod;
+  using SILGenSILBuilder::createSuperMethod;
   ManagedValue createSuperMethod(SILLocation loc, ManagedValue operand,
                                  SILDeclRef member, SILType methodTy);
 
-  using SILBuilder::createObjCSuperMethod;
+  using SILGenSILBuilder::createObjCSuperMethod;
   ManagedValue createObjCSuperMethod(SILLocation loc, ManagedValue operand,
                                      SILDeclRef member, SILType methodTy);
 
-  using SILBuilder::createValueMetatype;
+  using SILGenSILBuilder::createValueMetatype;
   ManagedValue createValueMetatype(SILLocation loc, SILType metatype,
                                    ManagedValue base);
 
-  using SILBuilder::createBridgeObjectToRef;
+  using SILGenSILBuilder::createBridgeObjectToRef;
   ManagedValue createBridgeObjectToRef(SILLocation loc, ManagedValue mv,
                                        SILType destType);
 
-  using SILBuilder::createRefToBridgeObject;
+  using SILGenSILBuilder::createRefToBridgeObject;
   ManagedValue createRefToBridgeObject(SILLocation loc, ManagedValue mv,
                                        SILValue bits);
 
-  using SILBuilder::createBranch;
+  using SILGenSILBuilder::createBranch;
   BranchInst *createBranch(SILLocation Loc, SILBasicBlock *TargetBlock,
                            ArrayRef<ManagedValue> Args);
 
-  using SILBuilder::createReturn;
+  using SILGenSILBuilder::createReturn;
   ReturnInst *createReturn(SILLocation Loc, ManagedValue ReturnValue);
 
-  using SILBuilder::emitDestructureValueOperation;
+  using SILGenSILBuilder::emitDestructureValueOperation;
   /// Perform either a tuple or struct destructure and then pass its components
   /// as managed value one by one with an index to the closure.
   void emitDestructureValueOperation(
       SILLocation loc, ManagedValue value,
       function_ref<void(unsigned, ManagedValue)> func);
 
-  using SILBuilder::createProjectBox;
+  using SILGenSILBuilder::createProjectBox;
   ManagedValue createProjectBox(SILLocation loc, ManagedValue mv,
                                 unsigned index);
 };
diff --git a/lib/SILGen/SILGenSILBuilder.cpp b/lib/SILGen/SILGenSILBuilder.cpp
new file mode 100644
index 0000000..3bd7fba
--- /dev/null
+++ b/lib/SILGen/SILGenSILBuilder.cpp
@@ -0,0 +1,174 @@
+//===--- SILGenSILBuilder.cpp ---------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#include "SILGenSILBuilder.h"
+#include "SILGenFunction.h"
+
+using namespace swift;
+using namespace Lowering;
+
+//===----------------------------------------------------------------------===//
+//                              Utility Methods
+//===----------------------------------------------------------------------===//
+
+SILGenModule &SILGenSILBuilder::getSILGenModule() const { return SGF.SGM; }
+
+//===----------------------------------------------------------------------===//
+//                                Constructors
+//===----------------------------------------------------------------------===//
+
+SILGenSILBuilder::SILGenSILBuilder(SILGenFunction &SGF)
+    : SILBuilder(SGF.F), SGF(SGF) {}
+
+SILGenSILBuilder::SILGenSILBuilder(
+    SILGenFunction &SGF, SILBasicBlock *insertBB,
+    SmallVectorImpl<SILInstruction *> *insertedInsts)
+    : SILBuilder(insertBB, insertedInsts), SGF(SGF) {}
+
+SILGenSILBuilder::SILGenSILBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB,
+                                   SILBasicBlock::iterator insertInst)
+    : SILBuilder(insertBB, insertInst), SGF(SGF) {}
+
+//===----------------------------------------------------------------------===//
+//              Instruction Emission + Conformance Endowed APIs
+//===----------------------------------------------------------------------===//
+//
+// This section contains wrappers around SILBuilder SILValue APIs that add extra
+// conformances. These are the only places where we should be accessing
+// SILBuilder APIs directly.
+//
+
+MetatypeInst *SILGenSILBuilder::createMetatype(SILLocation loc,
+                                               SILType metatype) {
+  auto theMetatype = metatype.castTo<MetatypeType>();
+  // Getting a nontrivial metatype requires forcing any conformances necessary
+  // to instantiate the type.
+  switch (theMetatype->getRepresentation()) {
+  case MetatypeRepresentation::Thin:
+    break;
+  case MetatypeRepresentation::Thick:
+  case MetatypeRepresentation::ObjC: {
+    // Walk the type recursively to look for substitutions we may need.
+    theMetatype.getInstanceType().findIf([&](Type t) -> bool {
+      auto *decl = t->getAnyNominal();
+      if (!decl)
+        return false;
+
+      if (isa<ProtocolDecl>(decl))
+        return false;
+
+      auto *genericSig = decl->getGenericSignature();
+      if (!genericSig)
+        return false;
+
+      auto subMap =
+          t->getContextSubstitutionMap(getSILGenModule().SwiftModule, decl);
+      getSILGenModule().useConformancesFromSubstitutions(subMap);
+      return false;
+    });
+
+    break;
+  }
+  }
+
+  return SILBuilder::createMetatype(loc, metatype);
+}
+
+ApplyInst *SILGenSILBuilder::createApply(SILLocation loc, SILValue fn,
+                                         SILType substFnTy, SILType result,
+                                         SubstitutionMap subs,
+                                         ArrayRef<SILValue> args) {
+  getSILGenModule().useConformancesFromSubstitutions(subs);
+  return SILBuilder::createApply(loc, fn, subs, args, false);
+}
+
+TryApplyInst *SILGenSILBuilder::createTryApply(
+    SILLocation loc, SILValue fn, SILType substFnTy, SubstitutionMap subs,
+    ArrayRef<SILValue> args, SILBasicBlock *normalBB, SILBasicBlock *errorBB) {
+  getSILGenModule().useConformancesFromSubstitutions(subs);
+  return SILBuilder::createTryApply(loc, fn, subs, args, normalBB, errorBB);
+}
+
+BeginApplyInst *SILGenSILBuilder::createBeginApply(SILLocation loc, SILValue fn,
+                                                   SubstitutionMap subs,
+                                                   ArrayRef<SILValue> args) {
+  getSILGenModule().useConformancesFromSubstitutions(subs);
+  return SILBuilder::createBeginApply(loc, fn, subs, args, false);
+}
+
+PartialApplyInst *SILGenSILBuilder::createPartialApply(
+    SILLocation loc, SILValue fn, SILType substFnTy, SubstitutionMap subs,
+    ArrayRef<SILValue> args, SILType closureTy) {
+  getSILGenModule().useConformancesFromSubstitutions(subs);
+  return SILBuilder::createPartialApply(
+      loc, fn, subs, args,
+      closureTy.getAs<SILFunctionType>()->getCalleeConvention());
+}
+
+BuiltinInst *SILGenSILBuilder::createBuiltin(SILLocation loc, Identifier name,
+                                             SILType resultTy,
+                                             SubstitutionMap subs,
+                                             ArrayRef<SILValue> args) {
+  getSILGenModule().useConformancesFromSubstitutions(subs);
+  return SILBuilder::createBuiltin(loc, name, resultTy, subs, args);
+}
+
+InitExistentialAddrInst *SILGenSILBuilder::createInitExistentialAddr(
+    SILLocation loc, SILValue existential, CanType formalConcreteType,
+    SILType loweredConcreteType,
+    ArrayRef<ProtocolConformanceRef> conformances) {
+  for (auto conformance : conformances)
+    getSILGenModule().useConformance(conformance);
+
+  return SILBuilder::createInitExistentialAddr(
+      loc, existential, formalConcreteType, loweredConcreteType, conformances);
+}
+
+InitExistentialValueInst *SILGenSILBuilder::createInitExistentialValue(
+    SILLocation Loc, SILType ExistentialType, CanType FormalConcreteType,
+    SILValue Concrete, ArrayRef<ProtocolConformanceRef> Conformances) {
+  for (auto conformance : Conformances)
+    getSILGenModule().useConformance(conformance);
+
+  return SILBuilder::createInitExistentialValue(
+      Loc, ExistentialType, FormalConcreteType, Concrete, Conformances);
+}
+
+InitExistentialMetatypeInst *SILGenSILBuilder::createInitExistentialMetatype(
+    SILLocation loc, SILValue metatype, SILType existentialType,
+    ArrayRef<ProtocolConformanceRef> conformances) {
+  for (auto conformance : conformances)
+    getSILGenModule().useConformance(conformance);
+
+  return SILBuilder::createInitExistentialMetatype(
+      loc, metatype, existentialType, conformances);
+}
+
+InitExistentialRefInst *SILGenSILBuilder::createInitExistentialRef(
+    SILLocation loc, SILType existentialType, CanType formalConcreteType,
+    SILValue concreteValue, ArrayRef<ProtocolConformanceRef> conformances) {
+  for (auto conformance : conformances)
+    getSILGenModule().useConformance(conformance);
+
+  return SILBuilder::createInitExistentialRef(
+      loc, existentialType, formalConcreteType, concreteValue, conformances);
+}
+
+AllocExistentialBoxInst *SILGenSILBuilder::createAllocExistentialBox(
+    SILLocation loc, SILType existentialType, CanType concreteType,
+    ArrayRef<ProtocolConformanceRef> conformances) {
+  for (auto conformance : conformances)
+    getSILGenModule().useConformance(conformance);
+
+  return SILBuilder::createAllocExistentialBox(loc, existentialType,
+                                               concreteType, conformances);
+}
diff --git a/lib/SILGen/SILGenSILBuilder.h b/lib/SILGen/SILGenSILBuilder.h
new file mode 100644
index 0000000..9ecdbdb
--- /dev/null
+++ b/lib/SILGen/SILGenSILBuilder.h
@@ -0,0 +1,102 @@
+//===--- SILGenSILBuilder.h -----------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_SILGEN_SILGENSILBUILDER_H
+#define SWIFT_SILGEN_SILGENSILBUILDER_H
+
+#include "swift/SIL/SILBuilder.h"
+
+namespace swift {
+namespace Lowering {
+
+class SILGenFunction;
+
+class SILGenSILBuilder : public SILBuilder {
+  SILGenFunction &SGF;
+
+public:
+  SILGenSILBuilder(SILGenFunction &SGF);
+  SILGenSILBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB,
+                   SmallVectorImpl<SILInstruction *> *insertedInsts = nullptr);
+  SILGenSILBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB,
+                   SILBasicBlock::iterator insertInst);
+
+  // Create a new builder, inheriting the given builder's context and debug
+  // scope.
+  SILGenSILBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB,
+                   const SILDebugScope *debugScope,
+                   SILBuilderContext &builderCtx)
+      : SILBuilder(insertBB, debugScope, builderCtx), SGF(SGF) {}
+
+  SILGenModule &getSILGenModule() const;
+
+  // Metatype instructions use the conformances necessary to instantiate the
+  // type.
+
+  MetatypeInst *createMetatype(SILLocation loc, SILType metatype);
+  // Generic apply instructions use the conformances necessary to form the call.
+
+  using SILBuilder::createApply;
+
+  ApplyInst *createApply(SILLocation loc, SILValue fn, SILType SubstFnTy,
+                         SILType result, SubstitutionMap subs,
+                         ArrayRef<SILValue> args);
+
+  TryApplyInst *createTryApply(SILLocation loc, SILValue fn, SILType substFnTy,
+                               SubstitutionMap subs, ArrayRef<SILValue> args,
+                               SILBasicBlock *normalBB, SILBasicBlock *errorBB);
+
+  BeginApplyInst *createBeginApply(SILLocation loc, SILValue fn,
+                                   SubstitutionMap subs,
+                                   ArrayRef<SILValue> args);
+
+  PartialApplyInst *createPartialApply(SILLocation loc, SILValue fn,
+                                       SILType substFnTy, SubstitutionMap subs,
+                                       ArrayRef<SILValue> args,
+                                       SILType closureTy);
+  BuiltinInst *createBuiltin(SILLocation loc, Identifier name, SILType resultTy,
+                             SubstitutionMap subs, ArrayRef<SILValue> args);
+
+  // Existential containers use the conformances needed by the existential
+  // box.
+
+  InitExistentialAddrInst *
+  createInitExistentialAddr(SILLocation loc, SILValue existential,
+                            CanType formalConcreteType,
+                            SILType loweredConcreteType,
+                            ArrayRef<ProtocolConformanceRef> conformances);
+
+  InitExistentialValueInst *
+  createInitExistentialValue(SILLocation loc, SILType existentialType,
+                             CanType formalConcreteType, SILValue concrete,
+                             ArrayRef<ProtocolConformanceRef> conformances);
+
+  InitExistentialMetatypeInst *
+  createInitExistentialMetatype(SILLocation loc, SILValue metatype,
+                                SILType existentialType,
+                                ArrayRef<ProtocolConformanceRef> conformances);
+
+  InitExistentialRefInst *
+  createInitExistentialRef(SILLocation loc, SILType existentialType,
+                           CanType formalConcreteType, SILValue concreteValue,
+                           ArrayRef<ProtocolConformanceRef> conformances);
+
+  AllocExistentialBoxInst *
+  createAllocExistentialBox(SILLocation loc, SILType existentialType,
+                            CanType concreteType,
+                            ArrayRef<ProtocolConformanceRef> conformances);
+};
+
+} // namespace Lowering
+} // namespace swift
+
+#endif
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index f649e11..f7aabf9 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -811,8 +811,10 @@
       // Figure out the actual base type, and whether we have an instance of
       // that type or its metatype.
       bool baseIsInstance = true;
+      bool isExistentialMetatype = false;
       if (auto baseMeta = baseTy->getAs<AnyMetatypeType>()) {
         baseIsInstance = false;
+        isExistentialMetatype = baseMeta->is<ExistentialMetatypeType>();
         baseTy = baseMeta->getInstanceType();
       }
 
@@ -900,11 +902,15 @@
                  base, selfParamTy, member, semantics,
                  locator.withPathElement(ConstraintLocator::MemberRefBase));
       } else {
-        // Convert the base to an rvalue of the appropriate metatype.
-        base = coerceToType(base,
-                            MetatypeType::get(isDynamic ? selfTy : containerTy),
-                            locator.withPathElement(
-                              ConstraintLocator::MemberRefBase));
+        if (!isExistentialMetatype || openedExistential) {
+          // Convert the base to an rvalue of the appropriate metatype.
+          base = coerceToType(base,
+                              MetatypeType::get(
+                                isDynamic ? selfTy : containerTy),
+                              locator.withPathElement(
+                                ConstraintLocator::MemberRefBase));
+        }
+
         if (!base)
           return nullptr;
 
diff --git a/lib/Sema/InstrumenterSupport.cpp b/lib/Sema/InstrumenterSupport.cpp
index 75b2bb7..d13f367 100644
--- a/lib/Sema/InstrumenterSupport.cpp
+++ b/lib/Sema/InstrumenterSupport.cpp
@@ -33,11 +33,12 @@
     diags.addConsumer(*this);
   }
   ~ErrorGatherer() override { diags.takeConsumers(); }
-  void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                        DiagnosticKind Kind,
-                        StringRef FormatString,
-                        ArrayRef<DiagnosticArgument> FormatArgs,
-                        const DiagnosticInfo &Info) override {
+  void
+  handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+                   StringRef FormatString,
+                   ArrayRef<DiagnosticArgument> FormatArgs,
+                   const DiagnosticInfo &Info,
+                   const SourceLoc bufferIndirectlyCausingDiagnostic) override {
     if (Kind == swift::DiagnosticKind::Error) {
       error = true;
     }
diff --git a/lib/Sema/ResilienceDiagnostics.cpp b/lib/Sema/ResilienceDiagnostics.cpp
index d87a8fa..10bc318 100644
--- a/lib/Sema/ResilienceDiagnostics.cpp
+++ b/lib/Sema/ResilienceDiagnostics.cpp
@@ -102,6 +102,8 @@
                                            const DeclContext *DC,
                                            FragileFunctionKind Kind,
                                            bool TreatUsableFromInlineAsPublic) {
+  // Do some important fast-path checks that apply to all cases.
+
   // Local declarations are OK.
   if (D->getDeclContext()->isLocalContext())
     return false;
@@ -110,6 +112,23 @@
   if (isa<AbstractTypeParamDecl>(D))
     return false;
 
+  // Check whether the declaration is accessible.
+  if (diagnoseInlinableDeclRefAccess(loc, D, DC, Kind,
+                                     TreatUsableFromInlineAsPublic))
+    return true;
+
+  // Check whether the declaration comes from a publically-imported module.
+  if (diagnoseDeclRefExportability(loc, D, DC))
+    return true;
+
+  return false;
+}
+
+bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
+                                           const ValueDecl *D,
+                                           const DeclContext *DC,
+                                           FragileFunctionKind Kind,
+                                           bool TreatUsableFromInlineAsPublic) {
   // Public declarations are OK.
   if (D->getFormalAccessScope(/*useDC=*/nullptr,
                               TreatUsableFromInlineAsPublic).isPublic())
@@ -178,3 +197,38 @@
   return (downgradeToWarning == DowngradeToWarning::No);
 }
 
+bool TypeChecker::diagnoseDeclRefExportability(SourceLoc loc,
+                                               const ValueDecl *D,
+                                               const DeclContext *DC) {
+  // We're only interested in diagnosing uses from source files.
+  auto userSF = DC->getParentSourceFile();
+  if (!userSF)
+    return false;
+
+  // If the source file doesn't have any implementation-only imports,
+  // we can fast-path this.  In the current language design, we never
+  // need to consider the possibility of implementation-only imports
+  // from other source files in the module (or indirectly in other modules).
+  // TODO: maybe check whether D is from a bridging header?
+  if (!userSF->hasImplementationOnlyImports())
+    return false;
+
+  auto userModule = userSF->getParentModule();
+  auto definingModule = D->getModuleContext();
+
+  // Nothing to diagnose in the very common case of the same module.
+  if (userModule == definingModule)
+    return false;
+
+  // Nothing to diagnose in the very common case that the module is
+  // imported for use in signatures.
+  if (!userSF->isImportedImplementationOnly(definingModule))
+    return false;
+
+  // TODO: different diagnostics
+  diagnose(loc, diag::inlinable_decl_ref_implementation_only,
+           D->getDescriptiveKind(), D->getFullName());
+
+  // TODO: notes explaining why
+  return true;
+}
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index a9fbdba..78b7a46 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -460,6 +460,7 @@
     return;
 
   auto &Ctx = SF.getASTContext();
+  BufferIndirectlyCausingDiagnosticRAII cpr(SF);
 
   // Make sure we have a type checker.
   TypeChecker &TC = createTypeChecker(Ctx);
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 9d9a433..7aabd5d 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1933,6 +1933,19 @@
                                 FragileFunctionKind Kind,
                                 bool TreatUsableFromInlineAsPublic);
 
+private:
+  bool diagnoseInlinableDeclRefAccess(SourceLoc loc, const ValueDecl *D,
+                                      const DeclContext *DC,
+                                      FragileFunctionKind Kind,
+                                      bool TreatUsableFromInlineAsPublic);
+
+public:
+  /// Given that a declaration is used from a particular context which
+  /// exposes it in the interface of the current module, diagnose if it cannot
+  /// reasonably be shared.
+  bool diagnoseDeclRefExportability(SourceLoc loc, const ValueDecl *D,
+                                    const DeclContext *DC);
+
   /// Given that \p DC is within a fragile context for some reason, describe
   /// why.
   ///
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 5f1598c..74ee9b2 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -205,7 +205,7 @@
 #endif
 _Block_release(void) { }\n")
     _add_swift_library_single(
-      BlocksRuntimeStub-${SDK}-${ARCH}
+      BlocksRuntimeStub${VARIANT_SUFFIX}
       BlocksRuntimeStub
       SHARED
       DONT_EMBED_BITCODE
@@ -214,12 +214,12 @@
       SDK ${SDK}
       INSTALL_IN_COMPONENT dev
       ${test_bin_dir}/BlocksRuntime.c)
-    set_target_properties(BlocksRuntimeStub-${SDK}-${ARCH} PROPERTIES
+    set_target_properties(BlocksRuntimeStub${VARIANT_SUFFIX} PROPERTIES
       ARCHIVE_OUTPUT_DIRECTORY ${test_bin_dir}
       LIBRARY_OUTPUT_DIRECTORY ${test_bin_dir}
       RUNTIME_OUTPUT_DIRECTORY ${test_bin_dir}
       OUTPUT_NAME BlocksRuntime)
-    list(APPEND test_dependencies BlocksRuntimeStub-${SDK}-${ARCH})
+    list(APPEND test_dependencies BlocksRuntimeStub${VARIANT_SUFFIX})
 
     list(APPEND test_dependencies
         "swift-test-stdlib-${SWIFT_SDK_${SDK}_LIB_SUBDIR}")
diff --git a/test/Constraints/protocols.swift b/test/Constraints/protocols.swift
index a538d97..c01e0d1 100644
--- a/test/Constraints/protocols.swift
+++ b/test/Constraints/protocols.swift
@@ -107,6 +107,9 @@
   func bar(_ x: Int)
   mutating func mut(_ x: Int)
   static func tum()
+  
+  typealias E = Int
+  typealias F = Self.E
 }
 
 protocol ClassP : class {
@@ -216,6 +219,13 @@
   // Static member of metatype -- not allowed
   _ = pp.tum // expected-error{{static member 'tum' cannot be used on protocol metatype 'P.Protocol'}}
   _ = P.tum // expected-error{{static member 'tum' cannot be used on protocol metatype 'P.Protocol'}}
+
+  // Access typealias through protocol and existential metatypes
+  _ = pp.E.self
+  _ = p.E.self
+
+  _ = pp.F.self
+  _ = p.F.self
 }
 
 protocol StaticP {
diff --git a/test/IDE/complete_at_eof_in_call_1.swift b/test/IDE/complete_at_eof_in_call_1.swift
index a26db97..f552236 100644
--- a/test/IDE/complete_at_eof_in_call_1.swift
+++ b/test/IDE/complete_at_eof_in_call_1.swift
@@ -4,7 +4,7 @@
 // Don't add any tests at the end of the file!
 //
 // A: Begin completions
-// A-DAG: Pattern/CurrModule:               ['(']{#(x): Int#}[')'][#Void#]{{; name=.+$}}
+// A-DAG: Decl[FreeFunction]/CurrModule:               ['(']{#(x): Int#}[')'][#Void#]{{; name=.+$}}
 // A: End completions
 func f(_ x: Int) {}
 f(#^A^#
diff --git a/test/IDE/complete_at_eof_in_call_no_newline_1.swift b/test/IDE/complete_at_eof_in_call_no_newline_1.swift
index 7ba13b8..2fbed5b 100644
--- a/test/IDE/complete_at_eof_in_call_no_newline_1.swift
+++ b/test/IDE/complete_at_eof_in_call_no_newline_1.swift
@@ -4,7 +4,7 @@
 // Don't add any tests at the end of the file!
 //
 // A: Begin completions
-// A-DAG: Pattern/CurrModule:               ['(']{#(x): Int#}[')'][#Void#]{{; name=.+$}}
+// A-DAG: Decl[FreeFunction]/CurrModule:               ['(']{#(x): Int#}[')'][#Void#]{{; name=.+$}}
 // A: End completions
 func f(_ x: Int) {}
 f(#^A^#
\ No newline at end of file
diff --git a/test/IDE/complete_call_arg.swift b/test/IDE/complete_call_arg.swift
index 2583d18..f6a1ef3 100644
--- a/test/IDE/complete_call_arg.swift
+++ b/test/IDE/complete_call_arg.swift
@@ -246,6 +246,7 @@
 
   func f6(obj: C3) {
     overloaded(#^OVERLOAD6^#
+    func sync() {}
     obj.overloaded(#^OVERLOAD7^#
   }
 }
@@ -279,15 +280,15 @@
 // NEGATIVE_OVERLOAD4-NOT: Decl[Class]{{.*}} C2
 
 // OVERLOAD5: Begin completions
-// OVERLOAD5-DAG: Pattern/CurrModule:                 ['(']{#(a): C1#}, {#b1: C2#}[')'][#Void#]; name=a: C1, b1: C2
-// OVERLOAD5-DAG: Pattern/CurrModule:                 ['(']{#(a): C2#}, {#b2: C1#}[')'][#Void#]; name=a: C2, b2: C1
+// OVERLOAD5-DAG: Decl[FreeFunction]/CurrModule:      ['(']{#(a): C1#}, {#b1: C2#}[')'][#Void#]; name=a: C1, b1: C2
+// OVERLOAD5-DAG: Decl[FreeFunction]/CurrModule:      ['(']{#(a): C2#}, {#b2: C1#}[')'][#Void#]; name=a: C2, b2: C1
 // OVERLOAD5-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: C1I[#C1#]; name=C1I
 // OVERLOAD5-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: C2I[#C2#]; name=C2I
 // OVERLOAD5: End completions
 
 // OVERLOAD6: Begin completions
-// OVERLOAD6-DAG: Pattern/CurrModule:                 ['(']{#(a1): C1#}, {#b1: C2#}[')'][#Void#]; name=a1: C1, b1: C2
-// OVERLOAD6-DAG: Pattern/CurrModule:                 ['(']{#a2: C2#}, {#b2: C1#}[')'][#Void#]; name=a2: C2, b2: C1
+// OVERLOAD6-DAG: Decl[InstanceMethod]/CurrNominal:   ['(']{#(a1): C1#}, {#b1: C2#}[')'][#Void#]; name=a1: C1, b1: C2
+// OVERLOAD6-DAG: Decl[InstanceMethod]/CurrNominal:   ['(']{#a2: C2#}, {#b2: C1#}[')'][#Void#]; name=a2: C2, b2: C1
 // OVERLOAD6-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: C1I[#C1#]; name=C1I
 // OVERLOAD6-DAG: Decl[InstanceVar]/CurrNominal:      C2I[#C2#]; name=C2I
 // OVERLOAD6: End completions
@@ -304,7 +305,7 @@
 }
 
 // HASERROR1: Begin completions
-// HASERROR1-DAG: Pattern/CurrModule:                 ['(']{#a1: C1#}, {#b1: <<error type>>#}[')'][#Int#];
+// HASERROR1-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#a1: C1#}, {#b1: <<error type>>#}[')'][#Int#];
 // HASERROR1: End completions
 
 // HASERROR2: Begin completions
@@ -442,7 +443,7 @@
   firstArg(#^FIRST_ARG_NAME_3^#,
 }
 // FIRST_ARG_NAME_3: Keyword/ExprSpecific: arg1: [#Argument name#]
-// FIRST_ARG_NAME_4: Pattern/CurrModule: ['(']{#arg1: Int#}, {#arg2: Int#}[')'][#Void#];
+// FIRST_ARG_NAME_4: Decl[FreeFunction]/CurrModule: ['(']{#arg1: Int#}, {#arg2: Int#}[')'][#Void#];
 
 func takeArray<T>(_ x: [T]) {}
 struct TestBoundGeneric1 {
@@ -484,7 +485,7 @@
 func other() {
   _ = fopen(#^CALLARG_IUO^#)
 // CALLARG_IUO: Begin completions, 1 items
-// CALLARG_IUO: Pattern/CurrModule: ['('][')'][#TestBoundGeneric1!#]; name=
+// CALLARG_IUO: Decl[FreeFunction]/CurrModule: ['('][')'][#TestBoundGeneric1!#]; name=
 // CALLARG_IUO: End completions
 }
 
@@ -601,12 +602,14 @@
 
   static func test() {
     foo(#^CURRIED_SELF_1^#
+    func sync();
     self.foo(#^CURRIED_SELF_2^#
+    func sync();
     TestImplicitlyCurriedSelf.foo(#^CURRIED_SELF_3^#
 
 // CURRIED_SELF_1: Begin completions, 2 items
-// CURRIED_SELF_1-DAG: Pattern/CurrModule: ['(']{#(self): TestImplicitlyCurriedSelf#}[')'][#(Int) -> ()#]{{; name=.+$}}
-// CURRIED_SELF_1-DAG: Pattern/CurrModule: ['(']{#(self): TestImplicitlyCurriedSelf#}[')'][#(Int, Int) -> ()#]{{; name=.+$}}
+// CURRIED_SELF_1-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#(self): TestImplicitlyCurriedSelf#}[')'][#(Int) -> ()#]{{; name=.+$}}
+// CURRIED_SELF_1-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#(self): TestImplicitlyCurriedSelf#}[')'][#(Int, Int) -> ()#]{{; name=.+$}}
 // CURRIED_SELF_1: End completions
   }
 }
diff --git a/test/IDE/complete_constructor.swift b/test/IDE/complete_constructor.swift
index 785ee2b..002e01a 100644
--- a/test/IDE/complete_constructor.swift
+++ b/test/IDE/complete_constructor.swift
@@ -48,7 +48,7 @@
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CLOSURE_IN_INIT_4 | %FileCheck %s -check-prefix=CLOSURE_IN_INIT_1
 
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=AVAILABLE_1 | %FileCheck %s -check-prefix=AVAILABLE_1
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=AVAILABLE_2 | %FileCheck %s -check-prefix=AVAILABLE_2
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=AVAILABLE_2 | %FileCheck %s -check-prefix=AVAILABLE_1
 
 func freeFunc() {}
 
@@ -334,7 +334,7 @@
   var prop1: S = {
     return S(#^CLOSURE_IN_INIT_1^#
   }
-// CLOSURE_IN_INIT_1: Decl[Constructor]/CurrNominal:      ['(']{#Int#}[')'][#ClosureInInit1.S#];
+// CLOSURE_IN_INIT_1: Decl[Constructor]/CurrNominal{{(/TypeRelation\[Identical\])?}}:      ['(']{#Int#}[')'][#ClosureInInit1.S#];
   var prop2: S = {
     return S(#^CLOSURE_IN_INIT_2^#
   }()
@@ -368,10 +368,4 @@
 // AVAILABLE_1: End completions
 
   let _ = AvailableTest.init(#^AVAILABLE_2^#
-// AVAILABLE_2: Begin completions, 3 items
-// AVAILABLE_2-DAG: Pattern/CurrModule:                 ['(']{#opt: Int#}[')'][#AvailableTest?#]; name=opt: Int
-// AVAILABLE_2-DAG: Pattern/CurrModule:                 ['(']{#normal1: Int#}[')'][#AvailableTest#]; name=normal1: Int
-// AVAILABLE_2-DAG: Pattern/CurrModule:                 ['(']{#normal2: Int#}[')'][#AvailableTest#]; name=normal2: Int
-// AVAILABLE_2: End completions
-
 }
diff --git a/test/IDE/complete_default_arguments.swift b/test/IDE/complete_default_arguments.swift
index df06310..5b0837d 100644
--- a/test/IDE/complete_default_arguments.swift
+++ b/test/IDE/complete_default_arguments.swift
@@ -67,16 +67,16 @@
   freeFuncWithDefaultArgs1#^DEFAULT_ARGS_2^#
 }
 // DEFAULT_ARGS_2: Begin completions
-// DEFAULT_ARGS_2-DAG: Pattern/CurrModule:      ({#(a): Int#})[#Void#]{{; name=.+$}}
-// DEFAULT_ARGS_2-DAG: Pattern/CurrModule:      ({#(a): Int#}, {#b: Int#})[#Void#]{{; name=.+$}}
+// DEFAULT_ARGS_2-DAG: Decl[FreeFunction]/CurrModule:      ({#(a): Int#})[#Void#]{{; name=.+$}}
+// DEFAULT_ARGS_2-DAG: Decl[FreeFunction]/CurrModule:      ({#(a): Int#}, {#b: Int#})[#Void#]{{; name=.+$}}
 // DEFAULT_ARGS_2: End completions
 
 func testDefaultArgs3() {
   freeFuncWithDefaultArgs3#^DEFAULT_ARGS_3^#
 }
 // DEFAULT_ARGS_3: Begin completions
-// DEFAULT_ARGS_3-DAG: Pattern/CurrModule:      ()[#Void#]{{; name=.+$}}
-// DEFAULT_ARGS_3-DAG: Pattern/CurrModule:      ({#a: Int#})[#Void#]{{; name=.+$}}
+// DEFAULT_ARGS_3-DAG: Decl[FreeFunction]/CurrModule:      ()[#Void#]{{; name=.+$}}
+// DEFAULT_ARGS_3-DAG: Decl[FreeFunction]/CurrModule:      ({#a: Int#})[#Void#]{{; name=.+$}}
 // DEFAULT_ARGS_3: End completions
 
 func testDefaultArgs4(_ x: A) {
@@ -91,8 +91,8 @@
   x.methodWithDefaultArgs1#^DEFAULT_ARGS_5^#
 }
 // DEFAULT_ARGS_5: Begin completions
-// DEFAULT_ARGS_5-DAG: Pattern/CurrModule:      ()[#Void#]{{; name=.+$}}
-// DEFAULT_ARGS_5-DAG: Pattern/CurrModule:      ({#a: Int#})[#Void#]{{; name=.+$}}
+// DEFAULT_ARGS_5-DAG: Decl[InstanceMethod]/CurrNominal:      ()[#Void#]{{; name=.+$}}
+// DEFAULT_ARGS_5-DAG: Decl[InstanceMethod]/CurrNominal:      ({#a: Int#})[#Void#]{{; name=.+$}}
 // DEFAULT_ARGS_5: End completions
 
 func testDefaultArgs6() {
diff --git a/test/IDE/complete_dynamic_lookup.swift b/test/IDE/complete_dynamic_lookup.swift
index 8f6c576..07c3c9e 100644
--- a/test/IDE/complete_dynamic_lookup.swift
+++ b/test/IDE/complete_dynamic_lookup.swift
@@ -463,7 +463,7 @@
   dl.returnsObjcClass!(#^DL_FUNC_NAME_PAREN_1^#
 }
 // DL_FUNC_NAME_PAREN_1: Begin completions
-// DL_FUNC_NAME_PAREN_1-DAG: Pattern/CurrModule: ['(']{#(i): Int#}[')'][#TopLevelObjcClass#]{{; name=.+$}}
+// DL_FUNC_NAME_PAREN_1-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#(i): Int#}[')'][#TopLevelObjcClass#]{{; name=.+$}}
 // DL_FUNC_NAME_PAREN_1: End completions
 
 func testAnyObject12(_ dl: AnyObject) {
@@ -475,7 +475,7 @@
   dl.returnsObjcClass!#^DL_FUNC_NAME_BANG_1^#
 }
 // DL_FUNC_NAME_BANG_1: Begin completions
-// DL_FUNC_NAME_BANG_1-NEXT: Pattern/CurrModule: ({#(i): Int#})[#TopLevelObjcClass#]
+// DL_FUNC_NAME_BANG_1-NEXT: Decl[InstanceMethod]/CurrNominal: ({#(i): Int#})[#TopLevelObjcClass#]
 // DL_FUNC_NAME_BANG_1-NEXT: Keyword[self]/CurrNominal: .self[#(Int) -> TopLevelObjcClass#]; name=self
 // DL_FUNC_NAME_BANG_1-NEXT: End completions
 
diff --git a/test/IDE/complete_from_clang_framework.swift b/test/IDE/complete_from_clang_framework.swift
index f757c1e..f90fdda 100644
--- a/test/IDE/complete_from_clang_framework.swift
+++ b/test/IDE/complete_from_clang_framework.swift
@@ -227,7 +227,7 @@
 func testCompleteFunctionCall1() {
   fooFunc1#^FUNCTION_CALL_1^#
 // FUNCTION_CALL_1: Begin completions
-// FUNCTION_CALL_1-NEXT: Pattern/CurrModule: ({#(a): Int32#})[#Int32#]{{; name=.+$}}
+// FUNCTION_CALL_1-NEXT: Decl[FreeFunction]/OtherModule[Foo]: ({#(a): Int32#})[#Int32#]{{; name=.+$}}
 // FUNCTION_CALL_1-NEXT: Keyword[self]/CurrNominal: .self[#(Int32) -> Int32#]; name=self
 // FUNCTION_CALL_1-NEXT: End completions
 }
@@ -235,7 +235,7 @@
 func testCompleteFunctionCall2() {
   fooFunc1AnonymousParam#^FUNCTION_CALL_2^#
 // FUNCTION_CALL_2: Begin completions
-// FUNCTION_CALL_2-NEXT: Pattern/CurrModule: ({#Int32#})[#Int32#]{{; name=.+$}}
+// FUNCTION_CALL_2-NEXT: Decl[FreeFunction]/OtherModule[Foo]: ({#Int32#})[#Int32#]{{; name=.+$}}
 // FUNCTION_CALL_2-NEXT: Keyword[self]/CurrNominal: .self[#(Int32) -> Int32#]; name=self
 // FUNCTION_CALL_2-NEXT: End completions
 }
diff --git a/test/IDE/complete_init_inherited.swift b/test/IDE/complete_init_inherited.swift
index 865bacc..d84f6c9 100644
--- a/test/IDE/complete_init_inherited.swift
+++ b/test/IDE/complete_init_inherited.swift
@@ -77,7 +77,7 @@
 
 // TEST_D_PAREN: Decl[Constructor]/CurrNominal:       ['(']{#d: D#}[')'][#D#]; name=d: D
 // TEST_D_PAREN-NEXT: Decl[Constructor]/CurrNominal:  ['(']{#int: Int#}[')'][#D#]; name=int: Int
-// TEST_D_PAREN-NEXT: Decl[Constructor]/Super:        ['(']{#c: C#}[')'][#C#]; name=c: C
+// TEST_D_PAREN-NEXT: Decl[Constructor]/Super:  ['(']{#c: C#}[')'][#C#]; name=c: C
 
 func testA() {
   A#^TEST_A^#
diff --git a/test/IDE/complete_operators.swift b/test/IDE/complete_operators.swift
index e3b607e..a2be1ac 100644
--- a/test/IDE/complete_operators.swift
+++ b/test/IDE/complete_operators.swift
@@ -292,8 +292,8 @@
 }
 
 // INFIX_16: Begin completions, 2 items
-// INFIX_16-NEXT: Pattern/CurrModule:               ({#(self): T#})[#() -> S2#]; name=(self: T)
-// INFIX_16-NEXT: Keyword[self]/CurrNominal:         .self[#(T) -> () -> S2#]; name=self
+// INFIX_16-NEXT: Decl[InstanceMethod]/CurrNominal: ({#(self): P#})[#() -> S2#]; name=(self: P)
+// INFIX_16-NEXT: Keyword[self]/CurrNominal:        .self[#(T) -> () -> S2#]; name=self
 // INFIX_16: End completions
 
 func testInfix17(x: Void) {
diff --git a/test/IDE/complete_value_expr.swift b/test/IDE/complete_value_expr.swift
index a54b76c..346544e 100644
--- a/test/IDE/complete_value_expr.swift
+++ b/test/IDE/complete_value_expr.swift
@@ -567,37 +567,37 @@
 func testImplicitlyCurriedFunc(_ fs: inout FooStruct) {
   FooStruct.instanceFunc0(&fs)#^IMPLICITLY_CURRIED_FUNC_0^#
 // IMPLICITLY_CURRIED_FUNC_0: Begin completions
-// IMPLICITLY_CURRIED_FUNC_0-NEXT: Pattern/CurrModule: ()[#Void#]{{; name=.+$}}
+// IMPLICITLY_CURRIED_FUNC_0-NEXT: Decl[InstanceMethod]/CurrNominal: ()[#Void#]{{; name=.+$}}
 // IMPLICITLY_CURRIED_FUNC_0-NEXT: Keyword[self]/CurrNominal: .self[#() -> ()#]; name=self
 // IMPLICITLY_CURRIED_FUNC_0-NEXT: End completions
 
   FooStruct.instanceFunc1(&fs)#^IMPLICITLY_CURRIED_FUNC_1^#
 // IMPLICITLY_CURRIED_FUNC_1: Begin completions
-// IMPLICITLY_CURRIED_FUNC_1-NEXT: Pattern/CurrModule: ({#(a): Int#})[#Void#]{{; name=.+$}}
+// IMPLICITLY_CURRIED_FUNC_1-NEXT: Decl[InstanceMethod]/CurrNominal: ({#(a): Int#})[#Void#]{{; name=.+$}}
 // IMPLICITLY_CURRIED_FUNC_1-NEXT: Keyword[self]/CurrNominal: .self[#(Int) -> ()#]; name=self
 // IMPLICITLY_CURRIED_FUNC_1-NEXT: End completions
 
   FooStruct.instanceFunc2(&fs)#^IMPLICITLY_CURRIED_FUNC_2^#
 // IMPLICITLY_CURRIED_FUNC_2: Begin completions
-// IMPLICITLY_CURRIED_FUNC_2-NEXT: Pattern/CurrModule: ({#(a): Int#}, {#b: &Double#})[#Void#]{{; name=.+$}}
+// IMPLICITLY_CURRIED_FUNC_2-NEXT: Decl[InstanceMethod]/CurrNominal: ({#(a): Int#}, {#b: &Double#})[#Void#]{{; name=.+$}}
 // IMPLICITLY_CURRIED_FUNC_2-NEXT: Keyword[self]/CurrNominal: .self[#(Int, inout Double) -> ()#]; name=self
 // IMPLICITLY_CURRIED_FUNC_2-NEXT: End completions
 
   FooStruct.varargInstanceFunc0(&fs)#^IMPLICITLY_CURRIED_VARARG_FUNC_0^#
 // IMPLICITLY_CURRIED_VARARG_FUNC_0: Begin completions
-// IMPLICITLY_CURRIED_VARARG_FUNC_0-NEXT: Pattern/CurrModule: ({#(v): Int...#})[#Void#]{{; name=.+$}}
+// IMPLICITLY_CURRIED_VARARG_FUNC_0-NEXT: Decl[InstanceMethod]/CurrNominal: ({#(v): Int...#})[#Void#]{{; name=.+$}}
 // IMPLICITLY_CURRIED_VARARG_FUNC_0-NEXT: Keyword[self]/CurrNominal: .self[#(Int...) -> ()#]; name=self
 // IMPLICITLY_CURRIED_VARARG_FUNC_0-NEXT: End completions
 
   FooStruct.varargInstanceFunc1(&fs)#^IMPLICITLY_CURRIED_VARARG_FUNC_1^#
 // IMPLICITLY_CURRIED_VARARG_FUNC_1: Begin completions
-// IMPLICITLY_CURRIED_VARARG_FUNC_1-NEXT: Pattern/CurrModule: ({#(a): Float#}, {#v: Int...#})[#Void#]{{; name=.+$}}
+// IMPLICITLY_CURRIED_VARARG_FUNC_1-NEXT: Decl[InstanceMethod]/CurrNominal: ({#(a): Float#}, {#v: Int...#})[#Void#]{{; name=.+$}}
 // IMPLICITLY_CURRIED_VARARG_FUNC_1-NEXT: Keyword[self]/CurrNominal: .self[#(Float, Int...) -> ()#]; name=self
 // IMPLICITLY_CURRIED_VARARG_FUNC_1-NEXT: End completions
 
   FooStruct.varargInstanceFunc2(&fs)#^IMPLICITLY_CURRIED_VARARG_FUNC_2^#
 // IMPLICITLY_CURRIED_VARARG_FUNC_2: Begin completions
-// IMPLICITLY_CURRIED_VARARG_FUNC_2-NEXT: Pattern/CurrModule: ({#(a): Float#}, {#b: Double#}, {#v: Int...#})[#Void#]{{; name=.+$}}
+// IMPLICITLY_CURRIED_VARARG_FUNC_2-NEXT: Decl[InstanceMethod]/CurrNominal: ({#(a): Float#}, {#b: Double#}, {#v: Int...#})[#Void#]{{; name=.+$}}
 // IMPLICITLY_CURRIED_VARARG_FUNC_2-NEXT: Keyword[self]/CurrNominal: .self[#(Float, Double, Int...) -> ()#]; name=self
 // IMPLICITLY_CURRIED_VARARG_FUNC_2-NEXT: End completions
 
@@ -737,7 +737,7 @@
   var a = FooStruct()
   a.instanceFunc0(#^INSIDE_FUNCTION_CALL_1^#
 // INSIDE_FUNCTION_CALL_1: Begin completions, 1 items
-// INSIDE_FUNCTION_CALL_1: Pattern/CurrModule: ['('][')'][#Void#]; name=
+// INSIDE_FUNCTION_CALL_1: Decl[InstanceMethod]/CurrNominal: ['('][')'][#Void#]; name=
 // INSIDE_FUNCTION_CALL_1: End completions
 }
 
@@ -745,7 +745,7 @@
   var a = FooStruct()
   a.instanceFunc1(#^INSIDE_FUNCTION_CALL_2^#
 // INSIDE_FUNCTION_CALL_2: Begin completions
-// INSIDE_FUNCTION_CALL_2-DAG: Pattern/CurrModule:       ['(']{#(a): Int#}[')'][#Void#]{{; name=.+$}}
+// INSIDE_FUNCTION_CALL_2-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#(a): Int#}[')'][#Void#]{{; name=.+$}}
 // INSIDE_FUNCTION_CALL_2-DAG: Decl[GlobalVar]/CurrModule: fooObject[#FooStruct#]{{; name=.+$}}
 // INSIDE_FUNCTION_CALL_2: End completions
 }
@@ -759,7 +759,7 @@
   var a = FooStruct()
   a.instanceFunc2(#^INSIDE_FUNCTION_CALL_4^#
 // INSIDE_FUNCTION_CALL_4: Begin completions
-// INSIDE_FUNCTION_CALL_4-DAG: Pattern/CurrModule:       ['(']{#(a): Int#}, {#b: &Double#}[')'][#Void#]{{; name=.+$}}
+// INSIDE_FUNCTION_CALL_4-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#(a): Int#}, {#b: &Double#}[')'][#Void#]{{; name=.+$}}
 // INSIDE_FUNCTION_CALL_4-DAG: Decl[GlobalVar]/CurrModule: fooObject[#FooStruct#]{{; name=.+$}}
 // INSIDE_FUNCTION_CALL_4: End completions
 }
@@ -775,7 +775,7 @@
   var a = FooStruct()
   a.instanceFunc7(#^INSIDE_FUNCTION_CALL_6^#
 // INSIDE_FUNCTION_CALL_6: Begin completions
-// INSIDE_FUNCTION_CALL_6-NEXT: Pattern/CurrModule: ['(']{#a: Int#}[')'][#Void#]{{; name=.+$}}
+// INSIDE_FUNCTION_CALL_6-NEXT: Decl[InstanceMethod]/CurrNominal: ['(']{#a: Int#}[')'][#Void#]{{; name=.+$}}
 // INSIDE_FUNCTION_CALL_6-NEXT: End completions
 }
 
@@ -783,21 +783,21 @@
   var a = FooStruct()
   a.instanceFunc8(#^INSIDE_FUNCTION_CALL_7^#
 // INSIDE_FUNCTION_CALL_7: Begin completions
-// INSIDE_FUNCTION_CALL_7: Pattern/CurrModule: ['(']{#(a): (Int, Int)#}[')'][#Void#]{{; name=.+$}}
+// INSIDE_FUNCTION_CALL_7: Decl[InstanceMethod]/CurrNominal: ['(']{#(a): (Int, Int)#}[')'][#Void#]{{; name=.+$}}
 // INSIDE_FUNCTION_CALL_7: End completions
 }
 
 func testInsideFunctionCall8(_ x: inout FooStruct) {
   x.instanceFunc0(#^INSIDE_FUNCTION_CALL_8^#)
 // INSIDE_FUNCTION_CALL_8: Begin completions
-// INSIDE_FUNCTION_CALL_8: Pattern/CurrModule: ['('][')'][#Void#]; name=
+// INSIDE_FUNCTION_CALL_8: Decl[InstanceMethod]/CurrNominal: ['('][')'][#Void#]; name=
 // INSIDE_FUNCTION_CALL_8: End completions
 }
 func testInsideFunctionCall9(_ x: inout FooStruct) {
   x.instanceFunc1(#^INSIDE_FUNCTION_CALL_9^#)
 // Annotated ')'
 // INSIDE_FUNCTION_CALL_9: Begin completions
-// INSIDE_FUNCTION_CALL_9-DAG: Pattern/CurrModule: ['(']{#(a): Int#}[')'][#Void#]{{; name=.+$}}
+// INSIDE_FUNCTION_CALL_9-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#(a): Int#}[')'][#Void#]{{; name=.+$}}
 // INSIDE_FUNCTION_CALL_9-DAG: Decl[GlobalVar]/CurrModule: fooObject[#FooStruct#]{{; name=.+$}}
 // INSIDE_FUNCTION_CALL_9: End completions
 }
@@ -805,25 +805,25 @@
   x.instanceFunc2(#^INSIDE_FUNCTION_CALL_10^#)
 // Annotated ')'
 // INSIDE_FUNCTION_CALL_10: Begin completions
-// INSIDE_FUNCTION_CALL_10-DAG: Pattern/CurrModule: ['(']{#(a): Int#}, {#b: &Double#}[')'][#Void#]{{; name=.+$}}
+// INSIDE_FUNCTION_CALL_10-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#(a): Int#}, {#b: &Double#}[')'][#Void#]{{; name=.+$}}
 // INSIDE_FUNCTION_CALL_10-DAG: Decl[GlobalVar]/CurrModule: fooObject[#FooStruct#]{{; name=.+$}}
 // INSIDE_FUNCTION_CALL_10: End completions
 }
 func testInsideFunctionCall11(_ x: inout FooStruct) {
   x.instanceFunc2(#^INSIDE_FUNCTION_CALL_11^#,
 // INSIDE_FUNCTION_CALL_11-NOT: Pattern/{{.*}}:{{.*}}({{.*}}{#Int#}
-// INSIDE_FUNCTION_CALL_11B: Pattern/CurrModule: ['(']{#Int#}, {#b: &Double#}[')'][#Void#];
+// INSIDE_FUNCTION_CALL_11B: Decl[InstanceMethod]/CurrNominal: ['(']{#Int#}, {#b: &Double#}[')'][#Void#];
 }
 func testInsideFunctionCall12(_ x: inout FooStruct) {
   x.instanceFunc2(#^INSIDE_FUNCTION_CALL_12^#<#placeholder#>
-// INSIDE_FUNCTION_CALL_12-NOT: Pattern/{{.*}}:{{.*}}({{.*}}{#Int#}
+// INSIDE_FUNCTION_CALL_12-NOT: Decl[InstanceMethod]/{{.*}}:{{.*}}({{.*}}{#Int#}
 }
 
 func testInsideVarargFunctionCall1() {
   var a = FooStruct()
   a.varargInstanceFunc0(#^INSIDE_VARARG_FUNCTION_CALL_1^#
 // INSIDE_VARARG_FUNCTION_CALL_1: Begin completions
-// INSIDE_VARARG_FUNCTION_CALL_1-DAG: Pattern/CurrModule:       ['(']{#(v): Int...#}[')'][#Void#]{{; name=.+$}}
+// INSIDE_VARARG_FUNCTION_CALL_1-DAG: Decl[InstanceMethod]/CurrNominal: ['(']{#(v): Int...#}[')'][#Void#]{{; name=.+$}}
 // INSIDE_VARARG_FUNCTION_CALL_1-DAG: Decl[GlobalVar]/CurrModule: fooObject[#FooStruct#]{{; name=.+$}}
 // INSIDE_VARARG_FUNCTION_CALL_1: End completions
 }
@@ -854,7 +854,7 @@
 func testInsideFunctionCallOnClassInstance1(_ a: FooClass) {
   a.fooClassInstanceFunc1(#^INSIDE_FUNCTION_CALL_ON_CLASS_INSTANCE_1^#
 // INSIDE_FUNCTION_CALL_ON_CLASS_INSTANCE_1: Begin completions
-// INSIDE_FUNCTION_CALL_ON_CLASS_INSTANCE_1-DAG: Pattern/CurrModule:       ['(']{#(a): Int#}[')'][#Void#]{{; name=.+$}}
+// INSIDE_FUNCTION_CALL_ON_CLASS_INSTANCE_1-DAG: Decl[InstanceMethod]/CurrNominal:       ['(']{#(a): Int#}[')'][#Void#]{{; name=.+$}}
 // INSIDE_FUNCTION_CALL_ON_CLASS_INSTANCE_1-DAG: Decl[GlobalVar]/CurrModule: fooObject[#FooStruct#]{{; name=.+$}}
 // INSIDE_FUNCTION_CALL_ON_CLASS_INSTANCE_1: End completions
 }
@@ -1156,7 +1156,7 @@
 func testFuncParenPattern3(_ fpp: inout FuncParenPattern) {
   fpp.instanceFunc#^FUNC_PAREN_PATTERN_3^#
 // FUNC_PAREN_PATTERN_3: Begin completions
-// FUNC_PAREN_PATTERN_3-NEXT: Pattern/CurrModule: ({#Int#})[#Void#]{{; name=.+$}}
+// FUNC_PAREN_PATTERN_3-NEXT: Decl[InstanceMethod]/CurrNominal: ({#Int#})[#Void#]{{; name=.+$}}
 // FUNC_PAREN_PATTERN_3-NEXT: Keyword[self]/CurrNominal: .self[#(Int) -> ()#]; name=self
 // FUNC_PAREN_PATTERN_3-NEXT: End completions
 }
@@ -1832,7 +1832,7 @@
 // PROTOCOL_EXT_INIT_2: Decl[Constructor]/CurrNominal: ['(']{#x: Int#}[')'][#P4#]{{; name=.+$}}
 // PROTOCOL_EXT_INIT_3: Decl[Constructor]/CurrNominal: init({#x: Int#})[#P4#]{{; name=.+$}}
 // PROTOCOL_EXT_INIT_4: Decl[Constructor]/CurrNominal: ({#x: Int#})[#P4#]{{; name=.+$}}
-// PROTOCOL_EXT_INIT_5: Pattern/CurrModule:            ['(']{#x: Int#}[')'][#S#]{{; name=.+$}}
+// PROTOCOL_EXT_INIT_5: Decl[Constructor]/CurrNominal: ['(']{#x: Int#}[')'][#P4#]{{; name=.+$}}
 
 extension P4 where Self.T == OnlyMe {
   final func test1() {
@@ -1944,14 +1944,14 @@
   globalFuncThrows#^THROWS1^#
 
 // THROWS1: Begin completions
-// THROWS1: Pattern/CurrModule:               ()[' throws'][#Void#]; name=() throws
+// THROWS1: Decl[FreeFunction]/CurrModule: ()[' throws'][#Void#]; name=() throws
 // THROWS1: End completions
 }
 func testThrows002() {
   globalFuncRethrows#^THROWS2^#
 
 // THROWS2: Begin completions
-// THROWS2: Pattern/CurrModule:               ({#(x): () throws -> ()##() throws -> ()#})[' rethrows'][#Void#]; name=(x: () throws -> ()) rethrows
+// THROWS2: Decl[FreeFunction]/CurrModule: ({#(x): () throws -> ()##() throws -> ()#})[' rethrows'][#Void#]; name=(x: () throws -> ()) rethrows
 // THROWS2: End completions
 }
 func testThrows003(_ x: HasThrowingMembers) {
@@ -1965,13 +1965,13 @@
 func testThrows004(_ x: HasThrowingMembers) {
   x.memberThrows#^MEMBER_THROWS2^#
 // MEMBER_THROWS2: Begin completions
-// MEMBER_THROWS2: Pattern/CurrModule:               ()[' throws'][#Void#]; name=() throws
+// MEMBER_THROWS2: Decl[InstanceMethod]/CurrNominal: ()[' throws'][#Void#]; name=() throws
 // MEMBER_THROWS2: End completions
 }
 func testThrows005(_ x: HasThrowingMembers) {
   x.memberRethrows#^MEMBER_THROWS3^#
 // MEMBER_THROWS3: Begin completions
-// MEMBER_THROWS3: Pattern/CurrModule: ({#(x): () throws -> ()##() throws -> ()#})[' rethrows'][#Void#]; name=(x: () throws -> ()) rethrows
+// MEMBER_THROWS3: Decl[InstanceMethod]/CurrNominal: ({#(x): () throws -> ()##() throws -> ()#})[' rethrows'][#Void#]; name=(x: () throws -> ()) rethrows
 // MEMBER_THROWS3: End completions
 }
 func testThrows006() {
diff --git a/test/IDE/complete_vararg.swift b/test/IDE/complete_vararg.swift
index c2b234b..32ffa32 100644
--- a/test/IDE/complete_vararg.swift
+++ b/test/IDE/complete_vararg.swift
@@ -54,10 +54,10 @@
   freeFunc2(#^FREE_FUNC_2^#
 }
 // FREE_FUNC_1: Begin completions, 1 items
-// FREE_FUNC_1: Pattern/CurrModule:               ['(']{#x: Int...#}[')'][#Void#]{{; name=.+$}}
+// FREE_FUNC_1: Decl[FreeFunction]/CurrModule: ['(']{#x: Int...#}[')'][#Void#]{{; name=.+$}}
 // FREE_FUNC_1: End completions
 // FREE_FUNC_2: Begin completions, 1 items
-// FREE_FUNC_2: Pattern/CurrModule:               ['(']{#x: Int#}, {#y: Int...#}[')'][#Void#]{{; name=.+$}}
+// FREE_FUNC_2: Decl[FreeFunction]/CurrModule: ['(']{#x: Int#}, {#y: Int...#}[')'][#Void#]{{; name=.+$}}
 // FREE_FUNC_2: End completions
 
 func testInit() {
@@ -72,10 +72,10 @@
   obj.method2(#^METHOD_2^#
 }
 // METHOD_1: Begin completions, 1 items
-// METHOD_1: Pattern/CurrModule:               ['(']{#x: Int...#}[')'][#Void#]{{; name=.+$}}
+// METHOD_1: Decl[InstanceMethod]/CurrNominal: ['(']{#x: Int...#}[')'][#Void#]{{; name=.+$}}
 // METHOD_1: End completions
 // METHOD_2: Begin completions, 1 items
-// METHOD_2: Pattern/CurrModule:               ['(']{#x: Int#}, {#y: Int...#}[')'][#Void#]{{; name=.+$}}
+// METHOD_2: Decl[InstanceMethod]/CurrNominal: ['(']{#x: Int#}, {#y: Int...#}[')'][#Void#]{{; name=.+$}}
 // METHOD_2: End completions
 
 func testSubscript() {
@@ -89,7 +89,7 @@
   genericFreeFunc1(#^GENERIC_FREE_FUNC_1^#
 }
 // GENERIC_FREE_FUNC_1: Begin completions, 1 items
-// GENERIC_FREE_FUNC_1: Pattern/CurrModule:               ['(']{#t: _...#}[')'][#Void#]{{; name=.+$}}
+// GENERIC_FREE_FUNC_1: Decl[FreeFunction]/CurrModule: ['(']{#t: _...#}[')'][#Void#]{{; name=.+$}}
 // GENERIC_FREE_FUNC_1: End completions
 
 
@@ -97,5 +97,5 @@
   interestingType1(#^INTERESTING_TYPE_1^#
 }
 // INTERESTING_TYPE_1: Begin completions, 1 items
-// INTERESTING_TYPE_1: Pattern/CurrModule:               ['(']{#x: (Int, (Int, String))...#}[')'][#Void#]{{; name=.+$}}
+// INTERESTING_TYPE_1: Decl[FreeFunction]/CurrModule: ['(']{#x: (Int, (Int, String))...#}[')'][#Void#]{{; name=.+$}}
 // INTERESTING_TYPE_1: End completions
diff --git a/test/Misc/serialized-diagnostics-batch-mode-nonprimary-errors-only.swift b/test/Misc/serialized-diagnostics-batch-mode-nonprimary-errors-only.swift
index 8d7464e..9d477ca 100644
--- a/test/Misc/serialized-diagnostics-batch-mode-nonprimary-errors-only.swift
+++ b/test/Misc/serialized-diagnostics-batch-mode-nonprimary-errors-only.swift
@@ -1,10 +1,21 @@
-// Ensure that an error in a non-primary causes an error in the errorless primary.
+// Ensure that an error in a non-primary is reported in the causal primary's .dia file,
+// and that the other primary's .dia file is truncated to indicate a failed compilation.
 //
 // RUN: rm -f %t.*
 
+// First, put the causal primary first:
+
 // RUN: not %target-swift-frontend -typecheck  -primary-file %s  -serialize-diagnostics-path %t.main.dia -primary-file %S/../Inputs/empty.swift  -serialize-diagnostics-path %t.empty.dia %S/Inputs/serialized-diagnostics-batch-mode-suppression-helper.swift  2> %t.stderr.txt
 
-// RUN: test -e %t.main.dia -a ! -s %t.empty.dia
+// RUN: test -e %t.main.dia -a -s %t.main.dia
+// RUN: test -e %t.empty.dia -a ! -s %t.empty.dia
+
+// Now, put the causal primary second:
+// (No matter which order, the error message goes with the causal primary.)
+
+// RUN: not %target-swift-frontend -typecheck  -primary-file %S/../Inputs/empty.swift  -serialize-diagnostics-path %t.empty.dia -primary-file %s  -serialize-diagnostics-path %t.main.dia  %S/Inputs/serialized-diagnostics-batch-mode-suppression-helper.swift  2> %t.stderr.txt
+
+// RUN: test -e %t.main.dia -a -s %t.main.dia
 // RUN: test -e %t.empty.dia -a ! -s %t.empty.dia
 
 func test(x: SomeType) {
diff --git a/test/Misc/serialized-diagnostics-batch-mode-nonprimary-errors.swift b/test/Misc/serialized-diagnostics-batch-mode-nonprimary-errors.swift
deleted file mode 100644
index 8cfd5dc..0000000
--- a/test/Misc/serialized-diagnostics-batch-mode-nonprimary-errors.swift
+++ /dev/null
@@ -1,16 +0,0 @@
-// Ensure that an error in a non-primary causes an error in the errorless primary.
-//
-// RUN: rm -f %t.*
-
-// RUN: not %target-swift-frontend -typecheck  -primary-file %s  -serialize-diagnostics-path %t.main.dia -primary-file %S/../Inputs/empty.swift  -serialize-diagnostics-path %t.empty.dia %S/Inputs/serialized-diagnostics-batch-mode-suppression-helper.swift  2> %t.stderr.txt
-// RUN: c-index-test -read-diagnostics %t.main.dia 2> %t.main.txt
-
-// RUN: %FileCheck -check-prefix=NO-GENERAL-ERROR-OCCURRED %s <%t.main.txt
-// RUN: test -e %t.empty.dia -a ! -s %t.empty.dia
-// GENERAL-ERROR-OCCURRED: compilation stopped by errors in other files
-// NO-GENERAL-ERROR-OCCURRED-NOT: compilation stopped by errors in other files
-
-
-func test(x: SomeType) {
-    nonexistant()
-}
diff --git a/test/Misc/serialized-diagnostics-batch-mode-primary-errors.swift b/test/Misc/serialized-diagnostics-batch-mode-primary-errors.swift
index 1e6396a..7c1fdeb 100644
--- a/test/Misc/serialized-diagnostics-batch-mode-primary-errors.swift
+++ b/test/Misc/serialized-diagnostics-batch-mode-primary-errors.swift
@@ -1,4 +1,5 @@
-// Ensure that an error in a primary causes an error in the errorless primary.
+// Ensure that an error in a primary is reflected in the right .dia file and
+// that it causes other .dia files to be truncated, signalling incomplete compilation.
 //
 // RUN: rm -f %t.*
 
@@ -6,12 +7,9 @@
 // RUN: c-index-test -read-diagnostics %t.main.dia 2> %t.main.txt
 
 // RUN: %FileCheck -check-prefix=ERROR %s <%t.main.txt
-// RUN: %FileCheck -check-prefix=NO-NONSPECIFIC-ERROR %s <%t.main.txt
 // RUN: test -e %t.empty.dia -a ! -s %t.empty.dia
 
 // ERROR: error:
-// NONSPECIFIC-ERROR: error: compilation stopped by errors in other files
-// NO-NONSPECIFIC-ERROR-NOT: error: compilation stopped by errors in other files
 
 func test(x: SomeType) {
   nonexistent()
diff --git a/test/Sema/Inputs/implementation-only-imports/directs.swift b/test/Sema/Inputs/implementation-only-imports/directs.swift
new file mode 100644
index 0000000..4053dce
--- /dev/null
+++ b/test/Sema/Inputs/implementation-only-imports/directs.swift
@@ -0,0 +1,30 @@
+@_exported import indirects
+
+public struct StructFromDirect {
+  public func method() {}
+  public var property: Int {
+    get { return 0 }
+    set {}
+  }
+  public subscript(index: Int) -> Int {
+    get { return 0 }
+    set {}
+  }
+}
+public typealias AliasFromDirect = StructFromDirect
+public typealias GenericAliasFromDirect<T> = (StructFromDirect, T)
+
+public func globalFunctionFromDirect() {}
+public var globalVariableFromDirect = 0
+
+extension StructFromIndirect {
+  public func extensionMethodFromDirect() {}
+  public var extensionPropertyFromDirect: Int {
+    get { return 0 }
+    set {}
+  }
+  public subscript(extensionSubscript index: Int) -> Int {
+    get { return 0 }
+    set {}
+  }
+}
diff --git a/test/Sema/Inputs/implementation-only-imports/indirects.swift b/test/Sema/Inputs/implementation-only-imports/indirects.swift
new file mode 100644
index 0000000..08becd2
--- /dev/null
+++ b/test/Sema/Inputs/implementation-only-imports/indirects.swift
@@ -0,0 +1,8 @@
+public struct StructFromIndirect {
+  public init() {}
+}
+public typealias AliasFromIndirect = StructFromIndirect
+public typealias GenericAliasFromIndirect<T> = (StructFromIndirect, T)
+
+public func globalFunctionFromIndirect() {}
+public var globalVariableFromIndirect = 0
diff --git a/test/Sema/Inputs/implementation-only-imports/secondary_file.swift b/test/Sema/Inputs/implementation-only-imports/secondary_file.swift
new file mode 100644
index 0000000..1827822
--- /dev/null
+++ b/test/Sema/Inputs/implementation-only-imports/secondary_file.swift
@@ -0,0 +1 @@
+@_exported import indirects
diff --git a/test/Sema/implementation-only-import-inlinable-indirect.swift b/test/Sema/implementation-only-import-inlinable-indirect.swift
new file mode 100644
index 0000000..c577ea9
--- /dev/null
+++ b/test/Sema/implementation-only-import-inlinable-indirect.swift
@@ -0,0 +1,43 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t/indirects.swiftmodule %S/Inputs/implementation-only-imports/indirects.swift
+// RUN: %target-swift-frontend -emit-module -o %t/directs.swiftmodule -I %t %S/Inputs/implementation-only-imports/directs.swift
+
+// RUN: %target-swift-frontend -typecheck -verify %s -I %t
+
+@_implementationOnly import directs
+
+// Types
+
+@inlinable
+public func testStructFromIndirect() {
+  _ = StructFromIndirect() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testAliasFromIndirect() {
+  _ = AliasFromIndirect() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testGenericAliasFromIndirect() {
+  _ = GenericAliasFromIndirect<Int>() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+// Functions
+
+@inlinable
+public func testFunctionFromIndirect() {
+  globalFunctionFromIndirect() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+// Variables
+
+@inlinable
+public func testVariableFromIndirect_get() {
+  _ = globalVariableFromIndirect // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testVariableFromIndirect_set() {
+  globalVariableFromIndirect = 5 // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
diff --git a/test/Sema/implementation-only-import-inlinable-multifile.swift b/test/Sema/implementation-only-import-inlinable-multifile.swift
new file mode 100644
index 0000000..53bc5ff
--- /dev/null
+++ b/test/Sema/implementation-only-import-inlinable-multifile.swift
@@ -0,0 +1,104 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t/indirects.swiftmodule %S/Inputs/implementation-only-imports/indirects.swift
+// RUN: %target-swift-frontend -emit-module -o %t/directs.swiftmodule -I %t %S/Inputs/implementation-only-imports/directs.swift
+
+// RUN: %target-swift-frontend -typecheck -verify -primary-file %s %S/Inputs/implementation-only-imports/secondary_file.swift -I %t
+
+@_implementationOnly import directs
+// 'indirects' is imported for re-export in a secondary file
+
+// Types
+
+@inlinable
+public func testStructFromDirect() {
+  _ = StructFromDirect() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testStructFromIndirect() {
+  _ = StructFromIndirect()
+}
+
+@inlinable
+public func testAliasFromDirect() {
+  _ = AliasFromDirect() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testAliasFromIndirect() {
+  _ = AliasFromIndirect()
+}
+
+@inlinable
+public func testGenericAliasFromDirect() {
+  _ = GenericAliasFromDirect<Int>() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testGenericAliasFromIndirect() {
+  let tmp: GenericAliasFromIndirect<Int>?
+  _ = tmp
+}
+
+// Functions
+
+@inlinable
+public func testFunctionFromDirect() {
+  globalFunctionFromDirect() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testFunctionFromIndirect() {
+  globalFunctionFromIndirect()
+}
+
+// Variables
+
+@inlinable
+public func testVariableFromDirect_get() {
+  _ = globalVariableFromDirect // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testVariableFromIndirect_get() {
+  _ = globalVariableFromIndirect
+}
+
+@inlinable
+public func testVariableFromDirect_set() {
+  globalVariableFromDirect = 5 // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testVariableFromIndirect_set() {
+  globalVariableFromIndirect = 5
+}
+
+// Extensions
+
+@inlinable
+public func testExtensionMethod(s: inout StructFromIndirect) {
+  s.extensionMethodFromDirect() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testExtensionProperty_get(s: inout StructFromIndirect) {
+  _ = s.extensionPropertyFromDirect // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testExtensionProperty_set(s: inout StructFromIndirect) {
+  s.extensionPropertyFromDirect = 5 // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testExtensionSubscript_get(s: inout StructFromIndirect) {
+  // FIXME: why is this error being double-emitted?
+  _ = s[extensionSubscript: 0] // expected-error 2 {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testExtensionSubscript_set(s: inout StructFromIndirect) {
+  // FIXME: why is this error being double-emitted?
+  s[extensionSubscript: 0] = 5 // expected-error 2 {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
diff --git a/test/Sema/implementation-only-import-inlinable.swift b/test/Sema/implementation-only-import-inlinable.swift
new file mode 100644
index 0000000..e843caf
--- /dev/null
+++ b/test/Sema/implementation-only-import-inlinable.swift
@@ -0,0 +1,104 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t/indirects.swiftmodule %S/Inputs/implementation-only-imports/indirects.swift
+// RUN: %target-swift-frontend -emit-module -o %t/directs.swiftmodule -I %t %S/Inputs/implementation-only-imports/directs.swift
+
+// RUN: %target-swift-frontend -typecheck -verify %s -I %t
+
+@_implementationOnly import directs
+import indirects
+
+// Types
+
+@inlinable
+public func testStructFromDirect() {
+  _ = StructFromDirect() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testStructFromIndirect() {
+  _ = StructFromIndirect()
+}
+
+@inlinable
+public func testAliasFromDirect() {
+  _ = AliasFromDirect() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testAliasFromIndirect() {
+  _ = AliasFromIndirect()
+}
+
+@inlinable
+public func testGenericAliasFromDirect() {
+  _ = GenericAliasFromDirect<Int>() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testGenericAliasFromIndirect() {
+  let tmp: GenericAliasFromIndirect<Int>?
+  _ = tmp
+}
+
+// Functions
+
+@inlinable
+public func testFunctionFromDirect() {
+  globalFunctionFromDirect() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testFunctionFromIndirect() {
+  globalFunctionFromIndirect()
+}
+
+// Variables
+
+@inlinable
+public func testVariableFromDirect_get() {
+  _ = globalVariableFromDirect // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testVariableFromIndirect_get() {
+  _ = globalVariableFromIndirect
+}
+
+@inlinable
+public func testVariableFromDirect_set() {
+  globalVariableFromDirect = 5 // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testVariableFromIndirect_set() {
+  globalVariableFromIndirect = 5
+}
+
+// Extensions
+
+@inlinable
+public func testExtensionMethod(s: inout StructFromIndirect) {
+  s.extensionMethodFromDirect() // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testExtensionProperty_get(s: inout StructFromIndirect) {
+  _ = s.extensionPropertyFromDirect // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testExtensionProperty_set(s: inout StructFromIndirect) {
+  s.extensionPropertyFromDirect = 5 // expected-error {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testExtensionSubscript_get(s: inout StructFromIndirect) {
+  // FIXME: why is this error being double-emitted?
+  _ = s[extensionSubscript: 0] // expected-error 2 {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
+
+@inlinable
+public func testExtensionSubscript_set(s: inout StructFromIndirect) {
+  // FIXME: why is this error being double-emitted?
+  s[extensionSubscript: 0] = 5 // expected-error 2 {{cannot be used in an inlinable function because its module was imported implementation-only}}
+}
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
index 8d3650c..0c78d63 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
@@ -46,11 +46,12 @@
 public:
   StreamDiagConsumer(llvm::raw_ostream &OS) : OS(OS) {}
 
-  void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                        DiagnosticKind Kind,
-                        StringRef FormatString,
-                        ArrayRef<DiagnosticArgument> FormatArgs,
-                        const DiagnosticInfo &Info) override {
+  void
+  handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+                   StringRef FormatString,
+                   ArrayRef<DiagnosticArgument> FormatArgs,
+                   const DiagnosticInfo &Info,
+                   const SourceLoc bufferIndirectlyCausingDiagnostic) override {
     // FIXME: Print location info if available.
     switch (Kind) {
       case DiagnosticKind::Error: OS << "error: "; break;
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
index 7d64446..d976274 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
@@ -1180,13 +1180,13 @@
   Impl.accept(SM, RegionType, Replacements);
 }
 
-void RequestRefactoringEditConsumer::
-handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
-                 StringRef FormatString,
-                 ArrayRef<DiagnosticArgument> FormatArgs,
-                 const DiagnosticInfo &Info) {
+void RequestRefactoringEditConsumer::handleDiagnostic(
+    SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+    StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
+    const DiagnosticInfo &Info,
+    const SourceLoc bufferIndirectlyCausingDiagnostic) {
   Impl.DiagConsumer.handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs,
-                                     Info);
+                                     Info, bufferIndirectlyCausingDiagnostic);
 }
 
 class RequestRenameRangeConsumer::Implementation {
@@ -1240,15 +1240,13 @@
   Impl.accept(SM, RegionType, Ranges);
 }
 
-void RequestRenameRangeConsumer::
-handleDiagnostic(SourceManager &SM,
-                 SourceLoc Loc,
-                 DiagnosticKind Kind,
-                 StringRef FormatString,
-                 ArrayRef<DiagnosticArgument> FormatArgs,
-                 const DiagnosticInfo &Info) {
+void RequestRenameRangeConsumer::handleDiagnostic(
+    SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+    StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
+    const DiagnosticInfo &Info,
+    const SourceLoc bufferIndirectlyCausingDiagnostic) {
   Impl.DiagConsumer.handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs,
-                                     Info);
+                                     Info, bufferIndirectlyCausingDiagnostic);
 }
 
 static NameUsage getNameUsage(RenameType Type) {
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
index 5d52d49..2ba1c7b 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
@@ -77,7 +77,8 @@
 void EditorDiagConsumer::handleDiagnostic(
     SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
     StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
-    const DiagnosticInfo &Info) {
+    const DiagnosticInfo &Info,
+    const SourceLoc bufferIndirectlyCausingDiagnostic) {
 
   if (Kind == DiagnosticKind::Error) {
     HadAnyError = true;
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditorDiagConsumer.h b/tools/SourceKit/lib/SwiftLang/SwiftEditorDiagConsumer.h
index 06611e9..896abd8 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditorDiagConsumer.h
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditorDiagConsumer.h
@@ -67,10 +67,10 @@
   bool hadAnyError() const { return HadAnyError; }
 
   void handleDiagnostic(swift::SourceManager &SM, swift::SourceLoc Loc,
-                        swift::DiagnosticKind Kind,
-                        StringRef FormatString,
+                        swift::DiagnosticKind Kind, StringRef FormatString,
                         ArrayRef<swift::DiagnosticArgument> FormatArgs,
-                        const swift::DiagnosticInfo &Info) override;
+                        const swift::DiagnosticInfo &Info,
+                        swift::SourceLoc bufferIndirectlyCausingDiagnostic) override;
 };
 
 } // namespace SourceKit
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
index dc40e08..caf855d 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
@@ -246,11 +246,12 @@
   ~RequestRefactoringEditConsumer();
   void accept(swift::SourceManager &SM, swift::ide::RegionType RegionType,
               ArrayRef<swift::ide::Replacement> Replacements) override;
-  void handleDiagnostic(swift::SourceManager &SM, swift::SourceLoc Loc,
-                        swift::DiagnosticKind Kind,
-                        StringRef FormatString,
-                        ArrayRef<swift::DiagnosticArgument> FormatArgs,
-                        const swift::DiagnosticInfo &Info) override;
+  void
+  handleDiagnostic(swift::SourceManager &SM, swift::SourceLoc Loc,
+                   swift::DiagnosticKind Kind, StringRef FormatString,
+                   ArrayRef<swift::DiagnosticArgument> FormatArgs,
+                   const swift::DiagnosticInfo &Info,
+                   swift::SourceLoc bufferIndirectlyCausingDiagnostic) override;
 };
 
 class RequestRenameRangeConsumer : public swift::ide::FindRenameRangesConsumer,
@@ -263,11 +264,12 @@
   ~RequestRenameRangeConsumer();
   void accept(swift::SourceManager &SM, swift::ide::RegionType RegionType,
               ArrayRef<swift::ide::RenameRangeDetail> Ranges) override;
-  void handleDiagnostic(swift::SourceManager &SM, swift::SourceLoc Loc,
-                        swift::DiagnosticKind Kind,
-                        StringRef FormatString,
-                        ArrayRef<swift::DiagnosticArgument> FormatArgs,
-                        const swift::DiagnosticInfo &Info) override;
+  void
+  handleDiagnostic(swift::SourceManager &SM, swift::SourceLoc Loc,
+                   swift::DiagnosticKind Kind, StringRef FormatString,
+                   ArrayRef<swift::DiagnosticArgument> FormatArgs,
+                   const swift::DiagnosticInfo &Info,
+                   swift::SourceLoc bufferIndirectlyCausingDiagnostic) override;
 };
 
 struct SwiftStatistics {
diff --git a/tools/driver/swift_format_main.cpp b/tools/driver/swift_format_main.cpp
index 7ee178d..9815a54 100644
--- a/tools/driver/swift_format_main.cpp
+++ b/tools/driver/swift_format_main.cpp
@@ -41,10 +41,11 @@
   CompilerInvocation CompInv;
   std::unique_ptr<ParserUnit> Parser;
   class FormatterDiagConsumer : public swift::DiagnosticConsumer {
-    void handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
-                          StringRef FormatString,
-                          ArrayRef<DiagnosticArgument> FormatArgs,
-                          const swift::DiagnosticInfo &Info) override {
+    void handleDiagnostic(
+        SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+        StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
+        const swift::DiagnosticInfo &Info,
+        const SourceLoc bufferIndirectlyCausingDiagnostic) override {
       llvm::errs() << "Parse error: ";
       DiagnosticEngine::formatDiagnosticText(llvm::errs(), FormatString,
                                              FormatArgs);
diff --git a/tools/libSwiftSyntaxParser/libSwiftSyntaxParser.cpp b/tools/libSwiftSyntaxParser/libSwiftSyntaxParser.cpp
index 24324ca..dcbdcb8 100644
--- a/tools/libSwiftSyntaxParser/libSwiftSyntaxParser.cpp
+++ b/tools/libSwiftSyntaxParser/libSwiftSyntaxParser.cpp
@@ -229,11 +229,12 @@
   const unsigned BufferID;
   SynParserDiagConsumer(SynParser &Parser, unsigned BufferID):
     Parser(Parser), BufferID(BufferID) {}
-  void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                        DiagnosticKind Kind,
-                        StringRef FormatString,
-                        ArrayRef<DiagnosticArgument> FormatArgs,
-                        const DiagnosticInfo &Info) override {
+  void
+  handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+                   StringRef FormatString,
+                   ArrayRef<DiagnosticArgument> FormatArgs,
+                   const DiagnosticInfo &Info,
+                   const SourceLoc bufferIndirectlyCausingDiagnostic) override {
     assert(Kind != DiagnosticKind::Remark && "Shouldn't see this in parser.");
     // The buffer where all char* will point into.
     llvm::SmallString<256> Buffer;
diff --git a/tools/swift-api-digester/ModuleDiagsConsumer.cpp b/tools/swift-api-digester/ModuleDiagsConsumer.cpp
index ac9637e..ddd3fe0 100644
--- a/tools/swift-api-digester/ModuleDiagsConsumer.cpp
+++ b/tools/swift-api-digester/ModuleDiagsConsumer.cpp
@@ -90,16 +90,16 @@
 #include "swift/AST/DiagnosticsModuleDiffer.def"
 }
 
-void swift::ide::api::
-ModuleDifferDiagsConsumer::handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                        DiagnosticKind Kind,
-                        StringRef FormatString,
-                        ArrayRef<DiagnosticArgument> FormatArgs,
-                        const DiagnosticInfo &Info) {
+void swift::ide::api::ModuleDifferDiagsConsumer::handleDiagnostic(
+    SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+    StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
+    const DiagnosticInfo &Info,
+    const SourceLoc bufferIndirectlyCausingDiagnostic) {
   auto Category = getCategoryName((uint32_t)Info.ID);
   if (Category.empty()) {
-    PrintingDiagnosticConsumer::handleDiagnostic(SM, Loc, Kind, FormatString,
-      FormatArgs, Info);
+    PrintingDiagnosticConsumer::handleDiagnostic(
+        SM, Loc, Kind, FormatString, FormatArgs, Info,
+        bufferIndirectlyCausingDiagnostic);
     return;
   }
   if (!DiagnoseModuleDiff)
diff --git a/tools/swift-api-digester/ModuleDiagsConsumer.h b/tools/swift-api-digester/ModuleDiagsConsumer.h
index 5ef90d1..47cd1d4 100644
--- a/tools/swift-api-digester/ModuleDiagsConsumer.h
+++ b/tools/swift-api-digester/ModuleDiagsConsumer.h
@@ -39,11 +39,11 @@
   ModuleDifferDiagsConsumer(bool DiagnoseModuleDiff,
                             llvm::raw_ostream &OS = llvm::errs());
   ~ModuleDifferDiagsConsumer();
-  void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                        DiagnosticKind Kind,
+  void handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
                         StringRef FormatString,
                         ArrayRef<DiagnosticArgument> FormatArgs,
-                        const DiagnosticInfo &Info) override;
+                        const DiagnosticInfo &Info,
+                        SourceLoc bufferIndirectlyCausingDiagnostic) override;
 };
 }
 }
diff --git a/unittests/AST/DiagnosticConsumerTests.cpp b/unittests/AST/DiagnosticConsumerTests.cpp
index 29776fc..6fba6ff 100644
--- a/unittests/AST/DiagnosticConsumerTests.cpp
+++ b/unittests/AST/DiagnosticConsumerTests.cpp
@@ -34,10 +34,11 @@
       EXPECT_TRUE(expected.empty());
     }
 
-    void handleDiagnostic(SourceManager &SM, SourceLoc loc, DiagnosticKind kind,
-                          StringRef formatString,
-                          ArrayRef<DiagnosticArgument> formatArgs,
-                          const DiagnosticInfo &info) override {
+    void handleDiagnostic(
+        SourceManager &SM, SourceLoc loc, DiagnosticKind kind,
+        StringRef formatString, ArrayRef<DiagnosticArgument> formatArgs,
+        const DiagnosticInfo &info,
+        const SourceLoc bufferIndirectlyCausingDiagnostic) override {
       ASSERT_FALSE(expected.empty());
       EXPECT_EQ(std::make_pair(loc, formatString), expected.front());
       expected.erase(expected.begin());
@@ -90,7 +91,7 @@
   auto topConsumer =
       FileSpecificDiagnosticConsumer::consolidateSubconsumers(consumers);
   topConsumer->handleDiagnostic(sourceMgr, SourceLoc(), DiagnosticKind::Error,
-                                "dummy", {}, DiagnosticInfo());
+                                "dummy", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->finishProcessing();
 }
 
@@ -131,17 +132,17 @@
   auto topConsumer =
       FileSpecificDiagnosticConsumer::consolidateSubconsumers(consumers);
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
-                                "front", {}, DiagnosticInfo());
+                                "front", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
-                                "front", {}, DiagnosticInfo());
+                                "front", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Error,
-                                "middle", {}, DiagnosticInfo());
+                                "middle", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Error,
-                                "middle", {}, DiagnosticInfo());
+                                "middle", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Error,
-                                "back", {}, DiagnosticInfo());
+                                "back", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Error,
-                                "back", {}, DiagnosticInfo());
+                                "back", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->finishProcessing();
 }
 
@@ -186,17 +187,17 @@
   auto topConsumer =
       FileSpecificDiagnosticConsumer::consolidateSubconsumers(consumers);
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
-                                "front", {}, DiagnosticInfo());
+                                "front", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
-                                "front", {}, DiagnosticInfo());
+                                "front", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Error,
-                                "middle", {}, DiagnosticInfo());
+                                "middle", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Error,
-                                "middle", {}, DiagnosticInfo());
+                                "middle", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Error,
-                                "back", {}, DiagnosticInfo());
+                                "back", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Error,
-                                "back", {}, DiagnosticInfo());
+                                "back", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->finishProcessing();
 }
 
@@ -232,13 +233,13 @@
   auto topConsumer =
       FileSpecificDiagnosticConsumer::consolidateSubconsumers(consumers);
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Warning,
-                                "warning", {}, DiagnosticInfo());
+                                "warning", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Warning,
-                                "warning", {}, DiagnosticInfo());
+                                "warning", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Remark,
-                                "remark", {}, DiagnosticInfo());
+                                "remark", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Remark,
-                                "remark", {}, DiagnosticInfo());
+                                "remark", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->finishProcessing();
 }
 
@@ -285,23 +286,23 @@
   auto topConsumer =
       FileSpecificDiagnosticConsumer::consolidateSubconsumers(consumers);
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
-                                "error", {}, DiagnosticInfo());
+                                "error", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
-                                "error", {}, DiagnosticInfo());
+                                "error", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
-                                "error", {}, DiagnosticInfo());
+                                "error", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->finishProcessing();
 }
 
@@ -348,23 +349,23 @@
   auto topConsumer =
       FileSpecificDiagnosticConsumer::consolidateSubconsumers(consumers);
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Warning,
-                                "warning", {}, DiagnosticInfo());
+                                "warning", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Warning,
-                                "warning", {}, DiagnosticInfo());
+                                "warning", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Remark,
-                                "remark", {}, DiagnosticInfo());
+                                "remark", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->finishProcessing();
 }
 
@@ -408,23 +409,23 @@
   auto topConsumer =
       FileSpecificDiagnosticConsumer::consolidateSubconsumers(consumers);
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
-                                "error", {}, DiagnosticInfo());
+                                "error", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
-                                "error", {}, DiagnosticInfo());
+                                "error", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
-                                "error", {}, DiagnosticInfo());
+                                "error", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->finishProcessing();
 }
 
@@ -472,23 +473,23 @@
   auto topConsumer =
       FileSpecificDiagnosticConsumer::consolidateSubconsumers(consumers);
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
-                                "error", {}, DiagnosticInfo());
+                                "error", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
-                                "error", {}, DiagnosticInfo());
+                                "error", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
-                                "error", {}, DiagnosticInfo());
+                                "error", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->finishProcessing();
 }
 
@@ -528,16 +529,16 @@
   auto topConsumer =
       FileSpecificDiagnosticConsumer::consolidateSubconsumers(consumers);
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
-                                "error", {}, DiagnosticInfo());
+                                "error", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, SourceLoc(), DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
-                                "error", {}, DiagnosticInfo());
+                                "error", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, SourceLoc(), DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
-                                "error", {}, DiagnosticInfo());
+                                "error", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->handleDiagnostic(sourceMgr, SourceLoc(), DiagnosticKind::Note,
-                                "note", {}, DiagnosticInfo());
+                                "note", {}, DiagnosticInfo(), SourceLoc());
   topConsumer->finishProcessing();
 }
diff --git a/unittests/Parse/LexerTests.cpp b/unittests/Parse/LexerTests.cpp
index a1428e4..282295a 100644
--- a/unittests/Parse/LexerTests.cpp
+++ b/unittests/Parse/LexerTests.cpp
@@ -747,10 +747,12 @@
 
 class StringCaptureDiagnosticConsumer : public DiagnosticConsumer {
 public:
-  virtual void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
-                                DiagnosticKind Kind, StringRef FormatString,
-                                ArrayRef<DiagnosticArgument> FormatArgs,
-                                const swift::DiagnosticInfo &Info) override {
+  virtual void
+  handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+                   StringRef FormatString,
+                   ArrayRef<DiagnosticArgument> FormatArgs,
+                   const swift::DiagnosticInfo &Info,
+                   SourceLoc bufferIndirectlyCausingDiagnostic) override {
     std::string DiagMsg;
     llvm::raw_string_ostream DiagOS(DiagMsg);
     DiagnosticEngine::formatDiagnosticText(DiagOS, FormatString, FormatArgs);