Merge pull request #10729 from itaiferber/4.0-non-optional-coding-paths

[4.0] Make coding paths non-optional [DO NOT MERGE]
diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def
index 975053d..e098c22 100644
--- a/include/swift/AST/DiagnosticsFrontend.def
+++ b/include/swift/AST/DiagnosticsFrontend.def
@@ -167,6 +167,17 @@
 ERROR(error_parse_input_file,none,
   "error parsing input file '%0' (%1)", (StringRef, StringRef))
 
+ERROR(error_write_index_unit,none,
+  "writing index unit file: %0", (StringRef))
+ERROR(error_create_index_dir,none,
+  "creating index directory: %0", (StringRef))
+ERROR(error_write_index_record,none,
+  "writing index record file: %0", (StringRef))
+ERROR(error_index_failed_status_check,none,
+  "failed file status check: %0", (StringRef))
+ERROR(error_index_inputs_more_than_outputs,none,
+  "index output filenames do not match input source files", ())
+
 ERROR(error_formatting_multiple_file_ranges,none,
   "file ranges don't support multiple input files", ())
 
@@ -183,6 +194,14 @@
       "symbol '%0' (%1) is in generated IR file, but not in TBD file",
       (StringRef, StringRef))
 
+ERROR(invalid_conditional_compilation_flag,none,
+      "conditional compilation flags must be valid Swift identifiers (rather than '%0')",
+      (StringRef))
+
+WARNING(cannot_assign_value_to_conditional_compilation_flag,none,
+        "conditional compilation flags do not have values in Swift; they are "
+        "either present or absent (rather than '%0')", (StringRef))
+
 #ifndef DIAG_NO_UNDEF
 # if defined(DIAG)
 #  undef DIAG
diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h
index c422d7d..44d0f18 100644
--- a/include/swift/AST/ProtocolConformance.h
+++ b/include/swift/AST/ProtocolConformance.h
@@ -462,6 +462,8 @@
   /// protocol, which line up with the conformance constraints in the
   /// protocol's requirement signature.
   ArrayRef<ProtocolConformanceRef> getSignatureConformances() const {
+    if (Resolver)
+      resolveLazyInfo();
     return SignatureConformances;
   }
 
diff --git a/include/swift/ClangImporter/ClangImporterOptions.h b/include/swift/ClangImporter/ClangImporterOptions.h
index 9704256..b3da68c 100644
--- a/include/swift/ClangImporter/ClangImporterOptions.h
+++ b/include/swift/ClangImporter/ClangImporterOptions.h
@@ -37,6 +37,9 @@
   /// Equivalent to Clang's -mcpu=.
   std::string TargetCPU;
 
+  /// The path to which we should store indexing data, if any.
+  std::string IndexStorePath;
+
   /// The bridging header or PCH that will be imported.
   std::string BridgingHeader;
 
diff --git a/include/swift/Driver/Types.def b/include/swift/Driver/Types.def
index 0306909..98cb9b3 100644
--- a/include/swift/Driver/Types.def
+++ b/include/swift/Driver/Types.def
@@ -61,6 +61,10 @@
 TYPE("tbd",             TBD,                "tbd",             "")
 TYPE("module-trace",    ModuleTrace,        "trace.json",      "")
 
+// BEGIN APPLE-ONLY OUTPUT TYPES
+TYPE("index-data",      IndexData,          "",                "")
+// END APPLE-ONLY OUTPUT TYPES
+
 // Misc types
 TYPE("pcm",             ClangModuleFile,    "pcm",             "")
 TYPE("pch",             PCH,                "pch",             "")
diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h
index 021e27b..92ce827 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -132,6 +132,12 @@
   /// The path to collect the group information for the compiled source files.
   std::string GroupInfoPath;
 
+  /// The path to which we should store indexing data, if any.
+  std::string IndexStorePath;
+
+  /// Emit index data for imported serialized swift system modules.
+  bool IndexSystemModules = false;
+
   /// If non-zero, warn when a function body takes longer than this many
   /// milliseconds to type-check.
   ///
diff --git a/include/swift/Index/IndexRecord.h b/include/swift/Index/IndexRecord.h
new file mode 100644
index 0000000..8ddcb44
--- /dev/null
+++ b/include/swift/Index/IndexRecord.h
@@ -0,0 +1,83 @@
+//===--- IndexRecord.h - Entry point for recording index data ---*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_INDEX_INDEXRECORD_H
+#define SWIFT_INDEX_INDEXRECORD_H
+
+#include "swift/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace swift {
+class DependencyTracker;
+class ModuleDecl;
+class SourceFile;
+
+namespace index {
+
+/// Index the given source file and store the results to \p indexStorePath.
+///
+/// \param primarySourceFile The source file to index.
+///
+/// \param indexUnitToken A unique identifier for this translation unit in the
+/// form of a file path.
+///
+/// \param indexStorePath The location to write the indexing data to.
+///
+/// \param indexSystemModules If true, emit index data for imported serialized
+/// swift system modules.
+///
+/// \param isDebugCompilation true for non-optimized compiler invocation.
+///
+/// \param targetTriple The target for this compilation.
+///
+/// \param dependencyTracker The set of dependencies seen while building.
+bool indexAndRecord(SourceFile *primarySourceFile, StringRef indexUnitToken,
+                    StringRef indexStorePath, bool indexSystemModules,
+                    bool isDebugCompilation, StringRef targetTriple,
+                    const DependencyTracker &dependencyTracker);
+
+/// Index the given module and store the results to \p indexStorePath.
+///
+/// \param module The module to index.
+///
+/// \param indexUnitTokens A list of unique identifiers for the index units to
+/// be written. This may either be one unit per source file of \p module, or it
+/// may be a single unit, in which case all the index information will be
+/// combined into a single unit.
+///
+/// \param moduleUnitToken A unique identifier for this module unit in the form
+/// of a file path. Only used if \p indexUnitTokens are specified for each
+/// source file, otherwise the single \p indexUnitTokens value is used instead.
+///
+/// \param indexStorePath The location to write the indexing data to.
+///
+/// \param indexSystemModules If true, emit index data for imported serialized
+/// swift system modules.
+///
+/// \param isDebugCompilation true for non-optimized compiler invocation.
+///
+/// \param targetTriple The target for this compilation.
+///
+/// \param dependencyTracker The set of dependencies seen while building.
+bool indexAndRecord(ModuleDecl *module, ArrayRef<std::string> indexUnitTokens,
+                    StringRef moduleUnitToken, StringRef indexStorePath,
+                    bool indexSystemModules, bool isDebugCompilation,
+                    StringRef targetTriple,
+                    const DependencyTracker &dependencyTracker);
+// FIXME: indexUnitTokens could be StringRef, but that creates an impedance
+// mismatch in the caller.
+
+} // end namespace index
+} // end namespace swift
+
+#endif // SWIFT_INDEX_INDEXRECORD_H
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index 4bc4968..d814367 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -414,6 +414,9 @@
     HelpText<"Use the pass pipeline defined by <pass_pipeline_file>">,
     MetaVarName<"<pass_pipeline_file>">;
 
+def index_system_modules : Flag<["-"], "index-system-modules">,
+  HelpText<"Emit index data for imported serialized swift system modules">;
+
 def dump_interface_hash : Flag<["-"], "dump-interface-hash">,
    HelpText<"Parse input file(s) and dump interface token hash(es)">,
    ModeOpt;
diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td
index 73b9261..2bdbe29 100644
--- a/include/swift/Option/Options.td
+++ b/include/swift/Option/Options.td
@@ -646,6 +646,18 @@
   HelpText<"Specify the type of coverage instrumentation for Sanitizers and"
   " additional options separated by commas">;
 
+def index_file : Flag<["-"], "index-file">,
+  HelpText<"Produce index data for a source file">, ModeOpt,
+  Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>;
+def index_file_path : Separate<["-"], "index-file-path">,
+  Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
+  HelpText<"Produce index data for file <path>">,
+  MetaVarName<"<path>">;
+
+def index_store_path : Separate<["-"], "index-store-path">,
+  Flags<[FrontendOption]>, MetaVarName<"<path>">,
+  HelpText<"Store indexing data to <path>">;
+
 def enforce_exclusivity_EQ : Joined<["-"], "enforce-exclusivity=">,
   Flags<[FrontendOption]>, MetaVarName<"<enforcement>">,
   HelpText<"Enforce law of exclusivity">;
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index d10e77e..e61924c 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -46,6 +46,7 @@
 #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/Frontend/Utils.h"
+#include "clang/Index/IndexingAction.h"
 #include "clang/Serialization/ASTReader.h"
 #include "clang/Serialization/ASTWriter.h"
 #include "clang/Lex/Preprocessor.h"
@@ -705,6 +706,11 @@
     invocationArgStrs.push_back(overrideResourceDir);
   }
 
+  if (!importerOpts.IndexStorePath.empty()) {
+    invocationArgStrs.push_back("-index-store-path");
+    invocationArgStrs.push_back(importerOpts.IndexStorePath);
+  }
+
   for (auto extraArg : importerOpts.ExtraArgs) {
     invocationArgStrs.push_back(extraArg);
   }
@@ -1306,6 +1312,7 @@
   invocation->getFrontendOpts().Inputs.push_back(
       clang::FrontendInputFile(headerPath, clang::IK_ObjC));
   invocation->getFrontendOpts().OutputFile = outputPCHPath;
+  invocation->getFrontendOpts().ProgramAction = clang::frontend::GeneratePCH;
   invocation->getPreprocessorOpts().resetNonModularOptions();
 
   clang::CompilerInstance emitInstance(
@@ -1319,8 +1326,15 @@
   emitInstance.createSourceManager(fileManager);
   emitInstance.setTarget(&Impl.Instance->getTarget());
 
-  clang::GeneratePCHAction action;
-  emitInstance.ExecuteAction(action);
+  std::unique_ptr<clang::FrontendAction> action;
+  action.reset(new clang::GeneratePCHAction());
+  if (!emitInstance.getFrontendOpts().IndexStorePath.empty()) {
+    action = clang::index::
+      createIndexDataRecordingAction(emitInstance.getFrontendOpts(),
+                                     std::move(action));
+  }
+  emitInstance.ExecuteAction(*action);
+
   if (emitInstance.getDiagnostics().hasErrorOccurred()) {
     Impl.SwiftContext.Diags.diagnose({},
                                      diag::bridging_header_pch_error,
@@ -1407,6 +1421,17 @@
     auto importRAII = diagClient.handleImport(clangPath.front().first,
                                               importLoc);
 
+    std::string preservedIndexStorePathOption;
+    auto &clangFEOpts = Impl.Instance->getFrontendOpts();
+    if (!clangFEOpts.IndexStorePath.empty()) {
+      StringRef moduleName = path[0].first->getName();
+      // Ignore the SwiftShims module for the index data.
+      if (moduleName == Impl.SwiftContext.SwiftShimsModuleName.str()) {
+        preservedIndexStorePathOption = clangFEOpts.IndexStorePath;
+        clangFEOpts.IndexStorePath.clear();
+      }
+    }
+
     // FIXME: The source location here is completely bogus. It can't be
     // invalid, it can't be the same thing twice in a row, and it has to come
     // from an actual buffer, so we make a fake buffer and just use a counter.
@@ -1427,6 +1452,12 @@
     clang::ModuleLoadResult result =
         Impl.Instance->loadModule(clangImportLoc, path, visibility,
                                   /*IsInclusionDirective=*/false);
+
+    if (!preservedIndexStorePathOption.empty()) {
+      // Restore the -index-store-path option.
+      clangFEOpts.IndexStorePath = preservedIndexStorePathOption;
+    }
+
     if (result && makeVisible)
       Impl.getClangPreprocessor().makeModuleVisible(result, clangImportLoc);
     return result;
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 93c92fa..7d6a172 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -6348,7 +6348,8 @@
     auto conformance = ctx.getConformance(dc->getDeclaredTypeInContext(),
                                           protocols[i], SourceLoc(), dc,
                                           ProtocolConformanceState::Incomplete);
-    Impl.scheduleFinishProtocolConformance(conformance);
+    conformance->setLazyLoader(&Impl, /*context*/0);
+    conformance->setState(ProtocolConformanceState::Complete);
     conformances.push_back(conformance);
   }
 
@@ -7286,6 +7287,9 @@
 
 void ClangImporter::Implementation::finishPendingActions() {
   while (true) {
+    // The odd shape of this loop comes from previously having more than one
+    // possible kind of pending action. It's left this way to make it easy to
+    // add another one back in an `else if` clause.
     if (!RegisteredExternalDecls.empty()) {
       if (hasFinishedTypeChecking()) {
         RegisteredExternalDecls.clear();
@@ -7297,22 +7301,22 @@
             if (!nominal->hasDelayedMembers())
               typeResolver->resolveExternalDeclImplicitMembers(nominal);
       }
-    } else if (!DelayedProtocolConformances.empty()) {
-      NormalProtocolConformance *conformance =
-          DelayedProtocolConformances.pop_back_val();
-      finishProtocolConformance(conformance);
     } else {
       break;
     }
   }
 }
 
-/// Finish the given protocol conformance (for an imported type)
-/// by filling in any missing witnesses.
-void ClangImporter::Implementation::finishProtocolConformance(
-    NormalProtocolConformance *conformance) {
+void ClangImporter::Implementation::finishNormalConformance(
+    NormalProtocolConformance *conformance,
+    uint64_t unused) {
+  (void)unused;
   const ProtocolDecl *proto = conformance->getProtocol();
 
+  PrettyStackTraceType trace(SwiftContext, "completing conformance for",
+                             conformance->getType());
+  PrettyStackTraceDecl traceTo("... to", proto);
+
   // Create witnesses for requirements not already met.
   for (auto req : proto->getMembers()) {
     auto valueReq = dyn_cast<ValueDecl>(req);
diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h
index 25c964d..174e075 100644
--- a/lib/ClangImporter/ImporterImpl.h
+++ b/lib/ClangImporter/ImporterImpl.h
@@ -496,9 +496,6 @@
   /// External Decls that we have imported but not passed to the ASTContext yet.
   SmallVector<Decl *, 4> RegisteredExternalDecls;
 
-  /// Protocol conformances that may be missing witnesses.
-  SmallVector<NormalProtocolConformance *, 4> DelayedProtocolConformances;
-
   unsigned NumCurrentImportingEntities = 0;
 
   /// Mapping from delayed conformance IDs to the set of delayed
@@ -517,7 +514,6 @@
   void startedImportingEntity();
   void finishedImportingEntity();
   void finishPendingActions();
-  void finishProtocolConformance(NormalProtocolConformance *conformance);
 
   struct ImportingEntityRAII {
     Implementation &Impl;
@@ -567,10 +563,6 @@
     RegisteredExternalDecls.push_back(D);
   }
 
-  void scheduleFinishProtocolConformance(NormalProtocolConformance *C) {
-    DelayedProtocolConformances.push_back(C);
-  }
-
   /// \brief Retrieve the Clang AST context.
   clang::ASTContext &getClangASTContext() const {
     return Instance->getASTContext();
@@ -1115,6 +1107,9 @@
     const Decl *D, uint64_t contextData,
     SmallVectorImpl<ProtocolConformance *> &Conformances) override;
 
+  void finishNormalConformance(NormalProtocolConformance *conformance,
+                               uint64_t unused) override;
+
   template <typename DeclTy, typename ...Targs>
   DeclTy *createDeclWithClangNode(ClangNode ClangN, Accessibility access,
                                   Targs &&... Args) {
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index cc1c307..42a4640 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -161,7 +161,7 @@
     diags.diagnose(SourceLoc(), diag::error_conflicting_options,
                    "-warnings-as-errors", "-suppress-warnings");
   }
-  
+
   // Check for missing debug option when verifying debug info.
   if (Args.hasArg(options::OPT_verify_debug_info)) {
     bool hasDebugOption = true;
@@ -172,6 +172,18 @@
       diags.diagnose(SourceLoc(),
                      diag::verify_debug_info_requires_debug_option);
   }
+
+  for (const Arg *A : make_range(Args.filtered_begin(options::OPT_D),
+                                 Args.filtered_end())) {
+    StringRef name = A->getValue();
+    if (name.find('=') != StringRef::npos)
+      diags.diagnose(SourceLoc(),
+                     diag::cannot_assign_value_to_conditional_compilation_flag,
+                     name);
+    else if (!Lexer::isIdentifier(name))
+      diags.diagnose(SourceLoc(), diag::invalid_conditional_compilation_flag,
+                     name);
+  }
 }
 
 /// Creates an appropriate ToolChain for a given driver and target triple.
@@ -1128,6 +1140,17 @@
       OI.CompilerMode = OutputInfo::Mode::SingleCompile;
       break;
 
+    // BEGIN APPLE-ONLY OUTPUT ACTIONS
+    case options::OPT_index_file:
+      OI.CompilerMode = OutputInfo::Mode::SingleCompile;
+      OI.CompilerOutputType = types::TY_IndexData;
+      break;
+    // END APPLE-ONLY OUTPUT ACTIONS
+
+    case options::OPT_update_code:
+      OI.CompilerOutputType = types::TY_Remapping;
+      OI.LinkAction = LinkKind::None;
+      break;
     case options::OPT_parse:
     case options::OPT_typecheck:
     case options::OPT_dump_parse:
@@ -1300,6 +1323,27 @@
                                          OI.SelectedSanitizer);
 }
 
+static void
+currentDependsOnPCHIfPresent(JobAction *PCH,
+                             std::unique_ptr<Action> &Current,
+                             ActionList &Actions) {
+  if (PCH) {
+    // FIXME: When we have a PCH job, it's officially owned by the Actions
+    // array; but it's also a secondary input to each of the current
+    // JobActions, which means that we need to flip the "owns inputs" bit
+    // on the JobActions so they don't try to free it. That in turn means
+    // we need to transfer ownership of all the JobActions' existing
+    // inputs to the Actions array, since the JobActions either own or
+    // don't own _all_ of their inputs. Ownership can't vary
+    // input-by-input.
+    auto *job = cast<JobAction>(Current.get());
+    auto inputs = job->getInputs();
+    Actions.append(inputs.begin(), inputs.end());
+    job->setOwnsInputs(false);
+    job->addInput(PCH);
+  }
+}
+
 void Driver::buildActions(const ToolChain &TC,
                           const DerivedArgList &Args,
                           const InputFileList &Inputs,
@@ -1364,6 +1408,7 @@
           Current.reset(new CompileJobAction(Current.release(),
                                              types::TY_LLVM_BC,
                                              previousBuildState));
+          currentDependsOnPCHIfPresent(PCH, Current, Actions);
           AllModuleInputs.push_back(Current.get());
           Current.reset(new BackendJobAction(Current.release(),
                                              OI.CompilerOutputType, 0));
@@ -1371,23 +1416,9 @@
           Current.reset(new CompileJobAction(Current.release(),
                                              OI.CompilerOutputType,
                                              previousBuildState));
+          currentDependsOnPCHIfPresent(PCH, Current, Actions);
           AllModuleInputs.push_back(Current.get());
         }
-        if (PCH) {
-          // FIXME: When we have a PCH job, it's officially owned by the Actions
-          // array; but it's also a secondary input to each of the current
-          // JobActions, which means that we need to flip the "owns inputs" bit
-          // on the JobActions so they don't try to free it. That in turn means
-          // we need to transfer ownership of all the JobActions' existing
-          // inputs to the Actions array, since the JobActions either own or
-          // don't own _all_ of their inputs. Ownership can't vary
-          // input-by-input.
-          auto *job = cast<JobAction>(Current.get());
-          auto inputs = job->getInputs();
-          Actions.append(inputs.begin(), inputs.end());
-          job->setOwnsInputs(false);
-          job->addInput(PCH);
-        }
         AllLinkerInputs.push_back(Current.release());
         break;
       }
@@ -1420,6 +1451,7 @@
       case types::TY_ClangModuleFile:
       case types::TY_SwiftDeps:
       case types::TY_Remapping:
+      case types::TY_IndexData:
       case types::TY_PCH:
       case types::TY_ImportedModules:
       case types::TY_TBD:
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index eafeb20..c2fd1d8 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -231,6 +231,13 @@
     case types::TY_TBD:
       FrontendModeOption = "-emit-tbd";
       break;
+
+    // BEGIN APPLE-ONLY OUTPUT TYPES
+    case types::TY_IndexData:
+      FrontendModeOption = "-typecheck";
+      break;
+    // END APPLE-ONLY OUTPUT TYPES
+
     case types::TY_Remapping:
       FrontendModeOption = "-update-code";
       break;
@@ -311,6 +318,12 @@
     break;
   }
   case OutputInfo::Mode::SingleCompile: {
+    if (context.Output.getPrimaryOutputType() == types::TY_IndexData) {
+      if (Arg *A = context.Args.getLastArg(options::OPT_index_file_path)) {
+        Arguments.push_back("-primary-file");
+        Arguments.push_back(A->getValue());
+      }
+    }
     if (context.Args.hasArg(options::OPT_driver_use_filelists) ||
         context.InputActions.size() > TOO_MANY_FILES) {
       Arguments.push_back("-filelist");
@@ -456,6 +469,11 @@
   if (context.Args.hasArg(options::OPT_embed_bitcode_marker))
     Arguments.push_back("-embed-bitcode-marker");
 
+  if (context.Args.hasArg(options::OPT_index_store_path)) {
+    context.Args.AddLastArg(Arguments, options::OPT_index_store_path);
+    Arguments.push_back("-index-system-modules");
+  }
+
   return II;
 }
 
@@ -541,6 +559,7 @@
     case types::TY_SIL:
     case types::TY_SIB:
     case types::TY_PCH:
+    case types::TY_IndexData:
       llvm_unreachable("Cannot be output from backend job");
     case types::TY_Swift:
     case types::TY_dSYM:
@@ -824,6 +843,7 @@
                         Arguments);
 
   addInputsOfType(Arguments, context.InputActions, types::TY_ObjCHeader);
+  context.Args.AddLastArg(Arguments, options::OPT_index_store_path);
 
   if (job.isPersistentPCH()) {
     Arguments.push_back("-emit-pch");
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index e6b87da..d0b60bc 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -92,6 +92,7 @@
   case types::TY_SwiftDeps:
   case types::TY_Nothing:
   case types::TY_Remapping:
+  case types::TY_IndexData:
     return false;
   case types::TY_INVALID:
     llvm_unreachable("Invalid type ID.");
@@ -128,6 +129,7 @@
   case types::TY_SwiftDeps:
   case types::TY_Nothing:
   case types::TY_Remapping:
+  case types::TY_IndexData:
   case types::TY_ModuleTrace:
     return false;
   case types::TY_INVALID:
@@ -165,6 +167,7 @@
   case types::TY_SwiftDeps:
   case types::TY_Nothing:
   case types::TY_Remapping:
+  case types::TY_IndexData:
   case types::TY_ModuleTrace:
     return false;
   case types::TY_INVALID:
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 1763da2..826f24e 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -169,6 +169,11 @@
     Opts.GroupInfoPath = A->getValue();
   }
 
+  if (const Arg *A = Args.getLastArg(OPT_index_store_path)) {
+    Opts.IndexStorePath = A->getValue();
+  }
+  Opts.IndexSystemModules |= Args.hasArg(OPT_index_system_modules);
+
   Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil);
   Opts.EmitSortedSIL |= Args.hasArg(OPT_emit_sorted_sil);
 
@@ -1143,6 +1148,9 @@
   if (const Arg *A = Args.getLastArg(OPT_target_cpu))
     Opts.TargetCPU = A->getValue();
 
+  if (const Arg *A = Args.getLastArg(OPT_index_store_path))
+    Opts.IndexStorePath = A->getValue();
+
   for (const Arg *A : make_range(Args.filtered_begin(OPT_Xcc),
                                  Args.filtered_end())) {
     Opts.ExtraArgs.push_back(A->getValue());
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index 0704189..7075aa6 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -97,6 +97,12 @@
   if (!Invocation.getFrontendOptions().ModuleDocOutputPath.empty())
     Invocation.getLangOptions().AttachCommentsToDecls = true;
 
+  // If we are doing index-while-building, configure lexing and parsing to
+  // remember comments.
+  if (!Invocation.getFrontendOptions().IndexStorePath.empty()) {
+    Invocation.getLangOptions().AttachCommentsToDecls = true;
+  }
+
   Context.reset(new ASTContext(Invocation.getLangOptions(),
                                Invocation.getSearchPathOptions(),
                                SourceMgr, Diagnostics));
diff --git a/lib/FrontendTool/CMakeLists.txt b/lib/FrontendTool/CMakeLists.txt
index 1168a59..882b8ab 100644
--- a/lib/FrontendTool/CMakeLists.txt
+++ b/lib/FrontendTool/CMakeLists.txt
@@ -5,6 +5,7 @@
   TBD.cpp
   DEPENDS SwiftOptions
   LINK_LIBRARIES
+    swiftIndex
     swiftIDE
     swiftTBDGen swiftIRGen swiftSIL swiftSILGen swiftSILOptimizer
     swiftDemangling
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index 28ca3ab..bdf06df 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -48,6 +48,7 @@
 #include "swift/Frontend/PrintingDiagnosticConsumer.h"
 #include "swift/Frontend/SerializedDiagnosticConsumer.h"
 #include "swift/Immediate/Immediate.h"
+#include "swift/Index/IndexRecord.h"
 #include "swift/Option/Options.h"
 #include "swift/Migrator/FixitFilter.h"
 #include "swift/Migrator/Migrator.h"
@@ -368,6 +369,10 @@
   LLVM_BUILTIN_TRAP;
 }
 
+static bool emitIndexData(SourceFile *PrimarySourceFile,
+      const CompilerInvocation &Invocation,
+      CompilerInstance &Instance);
+
 static void countStatsPostSema(UnifiedStatsReporter &Stats,
                                CompilerInstance& Instance) {
   auto &C = Stats.getFrontendCounters();
@@ -646,8 +651,16 @@
     (void)emitLoadedModuleTrace(Context, *Instance.getDependencyTracker(),
                                 opts);
 
-  if (Context.hadError())
+  bool shouldIndex = !opts.IndexStorePath.empty();
+
+  if (Context.hadError()) {
+    if (shouldIndex) {
+      //  Emit the index store data even if there were compiler errors.
+      if (emitIndexData(PrimarySourceFile, Invocation, Instance))
+        return true;
+    }
     return true;
+  }
 
   // FIXME: This is still a lousy approximation of whether the module file will
   // be externally consumed.
@@ -661,6 +674,10 @@
     if (!opts.ObjCHeaderOutputPath.empty())
       return printAsObjC(opts.ObjCHeaderOutputPath, Instance.getMainModule(),
                          opts.ImplicitObjCHeaderPath, moduleIsPublic);
+    if (shouldIndex) {
+      if (emitIndexData(PrimarySourceFile, Invocation, Instance))
+        return true;
+    }
     return Context.hadError();
   }
 
@@ -858,8 +875,13 @@
       serialize(DC, serializationOpts, SM.get());
     }
 
-    if (Action == FrontendOptions::EmitModuleOnly)
+    if (Action == FrontendOptions::EmitModuleOnly) {
+      if (shouldIndex) {
+        if (emitIndexData(PrimarySourceFile, Invocation, Instance))
+          return true;
+      }
       return Context.hadError();
+    }
   }
 
   assert(Action >= FrontendOptions::EmitSIL &&
@@ -918,6 +940,13 @@
                                    &HashGlobal);
   }
 
+  // Walk the AST for indexing after IR generation. Walking it before seems
+  // to cause miscompilation issues.
+  if (shouldIndex) {
+    if (emitIndexData(PrimarySourceFile, Invocation, Instance))
+      return true;
+  }
+
   // Just because we had an AST error it doesn't mean we can't performLLVM.
   bool HadError = Instance.getASTContext().hadError();
   
@@ -975,6 +1004,52 @@
                   opts.getSingleOutputFilename(), Stats) || HadError;
 }
 
+static bool emitIndexData(SourceFile *PrimarySourceFile,
+      const CompilerInvocation &Invocation,
+      CompilerInstance &Instance) {
+  const FrontendOptions &opts = Invocation.getFrontendOptions();
+  assert(!opts.IndexStorePath.empty());
+  // FIXME: provide index unit token(s) explicitly and only use output file
+  // paths as a fallback.
+
+  bool isDebugCompilation;
+  switch (Invocation.getSILOptions().Optimization) {
+    case SILOptions::SILOptMode::NotSet:
+    case SILOptions::SILOptMode::None:
+    case SILOptions::SILOptMode::Debug:
+      isDebugCompilation = true;
+      break;
+    case SILOptions::SILOptMode::Optimize:
+    case SILOptions::SILOptMode::OptimizeUnchecked:
+      isDebugCompilation = false;
+      break;
+  }
+
+  if (PrimarySourceFile) {
+    if (index::indexAndRecord(
+            PrimarySourceFile, opts.getSingleOutputFilename(),
+            opts.IndexStorePath, opts.IndexSystemModules,
+            isDebugCompilation, Invocation.getTargetTriple(),
+            *Instance.getDependencyTracker())) {
+      return true;
+    }
+  } else {
+    StringRef moduleToken = opts.ModuleOutputPath;
+    if (moduleToken.empty())
+      moduleToken = opts.getSingleOutputFilename();
+
+    if (index::indexAndRecord(Instance.getMainModule(), opts.OutputFilenames,
+                              moduleToken, opts.IndexStorePath,
+                              opts.IndexSystemModules,
+                              isDebugCompilation, Invocation.getTargetTriple(),
+                              *Instance.getDependencyTracker())) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 /// Returns true if an error occurred.
 static bool dumpAPI(ModuleDecl *Mod, StringRef OutDir) {
   using namespace llvm::sys;
@@ -1209,6 +1284,7 @@
   DependencyTracker depTracker;
   if (!Invocation.getFrontendOptions().DependenciesFilePath.empty() ||
       !Invocation.getFrontendOptions().ReferenceDependenciesFilePath.empty() ||
+      !Invocation.getFrontendOptions().IndexStorePath.empty() ||
       !Invocation.getFrontendOptions().LoadedModuleTracePath.empty()) {
     Instance->setDependencyTracker(&depTracker);
   }
diff --git a/lib/Index/CMakeLists.txt b/lib/Index/CMakeLists.txt
index d91c5a8..47aee9a 100644
--- a/lib/Index/CMakeLists.txt
+++ b/lib/Index/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_swift_library(swiftIndex STATIC
   Index.cpp
   IndexDataConsumer.cpp
+  IndexRecord.cpp
   IndexSymbol.cpp
   LINK_LIBRARIES
     swiftAST)
diff --git a/lib/Index/IndexRecord.cpp b/lib/Index/IndexRecord.cpp
new file mode 100644
index 0000000..91be812
--- /dev/null
+++ b/lib/Index/IndexRecord.cpp
@@ -0,0 +1,747 @@
+//===--- IndexRecord.cpp --------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#include "swift/Index/IndexRecord.h"
+#include "swift/AST/ASTContext.h"
+#include "swift/AST/Decl.h"
+#include "swift/AST/Expr.h"
+#include "swift/AST/Module.h"
+#include "swift/AST/ParameterList.h"
+#include "swift/AST/Pattern.h"
+#include "swift/AST/Stmt.h"
+#include "swift/AST/Types.h"
+#include "swift/AST/DiagnosticsFrontend.h"
+#include "swift/AST/ModuleLoader.h"
+#include "swift/ClangImporter/ClangModule.h"
+#include "swift/Index/Index.h"
+#include "swift/Strings.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Index/IndexingAction.h"
+#include "clang/Index/IndexRecordWriter.h"
+#include "clang/Index/IndexUnitWriter.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/Path.h"
+
+using namespace swift;
+using namespace swift::index;
+using clang::index::IndexUnitWriter;
+using clang::index::IndexRecordWriter;
+using clang::index::SymbolRole;
+using clang::index::SymbolRoleSet;
+
+//===----------------------------------------------------------------------===//
+// Index data collection and record writing
+//===----------------------------------------------------------------------===//
+
+namespace {
+class SymbolTracker {
+public:
+  struct SymbolRelation {
+    size_t symbolIndex;
+    SymbolRoleSet roles;
+
+    llvm::hash_code hash() const { return llvm::hash_combine(symbolIndex, roles); }
+  };
+  struct SymbolOccurrence {
+    size_t symbolIndex;
+    SymbolRoleSet roles;
+    unsigned line;
+    unsigned column;
+    SmallVector<SymbolRelation, 3> related;
+
+    llvm::hash_code hash() const {
+      auto hash = llvm::hash_combine(symbolIndex, roles, line, column);
+      for (auto &relation : related) {
+        hash = llvm::hash_combine(hash, relation.hash());
+      }
+      return hash;
+    }
+  };
+  struct Symbol {
+    StringRef name;
+    StringRef USR;
+    StringRef group;
+
+    SymbolInfo symInfo;
+    unsigned isTestCandidate : 1;
+
+    llvm::hash_code hash() const {
+      return llvm::hash_combine(
+          name, USR, group,
+          static_cast<unsigned>(symInfo.Kind),
+          static_cast<unsigned>(symInfo.SubKind),
+          symInfo.Properties, isTestCandidate);
+    }
+  };
+
+  Symbol *getSymbol(size_t index) {
+    assert(index < symbols.size());
+    return &symbols[index];
+  }
+
+  ArrayRef<SymbolOccurrence> getOccurrences() {
+    if (!sorted) {
+      std::stable_sort(occurrences.begin(), occurrences.end(),
+          [](const SymbolOccurrence &a, const SymbolOccurrence& b) {
+        if (a.line < b.line)
+          return true;
+        if (b.line < a.line)
+          return false;
+        return a.column < b.column;
+      });
+      sorted = true;
+    }
+    return occurrences;
+  }
+
+  size_t addSymbol(const IndexRelation &indexSym) {
+    auto pair = USRToSymbol.insert(std::make_pair(indexSym.USR.data(),
+                                                  symbols.size()));
+    if (pair.second) {
+      Symbol symbol{indexSym.name,
+                    indexSym.USR,
+                    indexSym.group,
+                    indexSym.symInfo,
+                    0};
+      recordHash = llvm::hash_combine(recordHash, symbol.hash());
+      symbols.push_back(std::move(symbol));
+    }
+
+    return pair.first->second;
+  }
+
+  void addOccurrence(const IndexSymbol &indexOccur) {
+    sorted = false;
+
+    SmallVector<SymbolRelation, 3> relations;
+    for(IndexRelation indexRel: indexOccur.Relations) {
+      relations.push_back({addSymbol(indexRel), indexRel.roles});
+    }
+
+    occurrences.push_back({/*symbolIndex=*/addSymbol(indexOccur),
+                           indexOccur.roles,
+                           indexOccur.line,
+                           indexOccur.column,
+                           std::move(relations)});
+
+    recordHash = llvm::hash_combine(recordHash, occurrences.back().hash());
+  }
+
+  llvm::hash_code hashRecord() const { return recordHash; }
+
+private:
+  llvm::DenseMap<const char *, size_t> USRToSymbol;
+  std::vector<Symbol> symbols;
+  std::vector<SymbolOccurrence> occurrences;
+  bool sorted = false;
+  llvm::hash_code recordHash = 0;
+};
+
+class IndexRecordingConsumer : public IndexDataConsumer {
+  SymbolTracker record;
+  // Keep a USR map to uniquely identify Decls.
+  // FIXME: if we just passed the original Decl * through we could use that,
+  // which would also let us avoid producing the USR/Name/etc. for decls unless
+  // we actually need it (once per Decl instead of once per occurrence).
+  std::vector<IndexSymbol> symbolStack;
+
+  std::function<void(SymbolTracker &)> onFinish;
+
+public:
+  IndexRecordingConsumer(std::function<void(SymbolTracker &)> onFinish)
+      : onFinish(std::move(onFinish)) {}
+
+  void failed(StringRef error) override {
+    // FIXME: expose errors?
+  }
+
+  bool recordHash(StringRef hash, bool isKnown) override { return true; }
+  bool startDependency(StringRef name, StringRef path, bool isClangModule,
+                       bool isSystem, StringRef hash) override {
+    return true;
+  }
+  bool finishDependency(bool isClangModule) override { return true; }
+  Action startSourceEntity(const IndexSymbol &symbol) override {
+    symbolStack.push_back(symbol);
+    return Action::Continue;
+  }
+  bool finishSourceEntity(SymbolInfo sym, SymbolRoleSet roles) override {
+    IndexSymbol symbol = std::move(symbolStack.back());
+    symbolStack.pop_back();
+    assert(!symbol.USR.empty());
+    record.addOccurrence(symbol);
+    return true;
+  }
+
+  void finish() override { onFinish(record); }
+};
+
+class StdlibGroupsIndexRecordingConsumer : public IndexDataConsumer {
+  llvm::StringMap<std::unique_ptr<SymbolTracker>> TrackerByGroup;
+  // Keep a USR map to uniquely identify Decls.
+  // FIXME: if we just passed the original Decl * through we could use that,
+  // which would also let us avoid producing the USR/Name/etc. for decls unless
+  // we actually need it (once per Decl instead of once per occurrence).
+  std::vector<IndexSymbol> symbolStack;
+
+  std::function<bool(StringRef groupName, SymbolTracker &)> onFinish;
+
+public:
+  StdlibGroupsIndexRecordingConsumer(std::function<bool(StringRef groupName, SymbolTracker &)> onFinish)
+      : onFinish(std::move(onFinish)) {}
+
+  void failed(StringRef error) override {
+    // FIXME: expose errors?
+  }
+
+  bool recordHash(StringRef hash, bool isKnown) override { return true; }
+  bool startDependency(StringRef name, StringRef path, bool isClangModule,
+                       bool isSystem, StringRef hash) override {
+    return true;
+  }
+  bool finishDependency(bool isClangModule) override { return true; }
+  Action startSourceEntity(const IndexSymbol &symbol) override {
+    symbolStack.push_back(symbol);
+    return Action::Continue;
+  }
+  bool finishSourceEntity(SymbolInfo sym, SymbolRoleSet roles) override {
+    IndexSymbol symbol = std::move(symbolStack.back());
+    symbolStack.pop_back();
+    assert(!symbol.USR.empty());
+    StringRef groupName = findGroupForSymbol(symbol);
+    auto &tracker = TrackerByGroup[groupName];
+    if (!tracker) {
+      tracker = llvm::make_unique<SymbolTracker>();
+    }
+    tracker->addOccurrence(symbol);
+    return true;
+  }
+
+  void finish() override {
+    for (auto &pair : TrackerByGroup) {
+      StringRef groupName = pair.first();
+      SymbolTracker &tracker = *pair.second;
+      bool cont = onFinish(groupName, tracker);
+      if (!cont)
+        break;
+    }
+  }
+
+private:
+  StringRef findGroupForSymbol(const IndexSymbol &sym);
+
+};
+} // end anonymous namespace
+
+static StringRef findGroupNameForDecl(const Decl *D) {
+  if (!D || isa<ModuleDecl>(D) || isa<TopLevelCodeDecl>(D))
+    return StringRef();
+
+  auto groupNameOpt = D->getGroupName();
+  if (groupNameOpt)
+    return *groupNameOpt;
+
+  return findGroupNameForDecl(D->getDeclContext()->getInnermostDeclarationDeclContext());
+}
+
+StringRef StdlibGroupsIndexRecordingConsumer::findGroupForSymbol(const IndexSymbol &sym) {
+  bool isDeclOrDef = sym.roles & ((SymbolRoleSet)SymbolRole::Declaration | (SymbolRoleSet)SymbolRole::Definition);
+  if (isDeclOrDef) {
+    if (!sym.group.empty())
+      return sym.group;
+    return findGroupNameForDecl(sym.decl);
+  }
+
+  for (auto &rel : sym.Relations) {
+    if (!rel.group.empty())
+      return rel.group;
+    if (rel.decl)
+      return findGroupNameForDecl(rel.decl);
+  }
+  llvm_unreachable("did not find group name for reference");
+}
+
+static bool writeRecord(SymbolTracker &record, std::string Filename,
+                        std::string indexStorePath, DiagnosticEngine *diags,
+                        std::string &outRecordFile) {
+  if (record.getOccurrences().empty()) {
+    outRecordFile = std::string();
+    return false;
+  }
+
+  IndexRecordWriter recordWriter(indexStorePath);
+  std::string error;
+  auto result = recordWriter.beginRecord(
+      Filename, record.hashRecord(), error, &outRecordFile);
+  switch (result) {
+  case IndexRecordWriter::Result::Failure:
+    diags->diagnose(SourceLoc(), diag::error_write_index_record, error);
+    return true;
+  case IndexRecordWriter::Result::AlreadyExists:
+    return false;
+  case IndexRecordWriter::Result::Success:
+    break;
+  }
+
+  for (auto &occurrence : record.getOccurrences()) {
+    SmallVector<clang::index::writer::SymbolRelation, 3> relations;
+    for(SymbolTracker::SymbolRelation symbolRelation: occurrence.related) {
+      relations.push_back({record.getSymbol(symbolRelation.symbolIndex), symbolRelation.roles});
+    }
+
+    recordWriter.addOccurrence(
+        record.getSymbol(occurrence.symbolIndex), occurrence.roles,
+        occurrence.line, occurrence.column, relations);
+  }
+
+  result = recordWriter.endRecord(error,
+      [&](clang::index::writer::OpaqueDecl opaqueSymbol,
+          SmallVectorImpl<char> &scratch) {
+    auto *symbol = static_cast<const SymbolTracker::Symbol *>(opaqueSymbol);
+    clang::index::writer::Symbol result;
+    result.SymInfo = symbol->symInfo;
+    result.Name = symbol->name;
+    result.USR = symbol->USR;
+    result.CodeGenName = ""; // FIXME
+    return result;
+  });
+
+  if (result == IndexRecordWriter::Result::Failure) {
+    diags->diagnose(SourceLoc(), diag::error_write_index_record, error);
+    return true;
+  }
+
+  return false;
+}
+
+static std::unique_ptr<IndexRecordingConsumer>
+makeRecordingConsumer(std::string Filename, std::string indexStorePath,
+                      DiagnosticEngine *diags,
+                      std::string *outRecordFile,
+                      bool *outFailed) {
+  return llvm::make_unique<IndexRecordingConsumer>([=](SymbolTracker &record) {
+    *outFailed = writeRecord(record, Filename, indexStorePath, diags,
+                             *outRecordFile);
+  });
+}
+
+static bool
+recordSourceFile(SourceFile *SF, StringRef indexStorePath,
+                 DiagnosticEngine &diags,
+                 llvm::function_ref<void(StringRef, StringRef)> callback) {
+  std::string recordFile;
+  bool failed = false;
+  auto consumer = makeRecordingConsumer(SF->getFilename(), indexStorePath,
+                                        &diags, &recordFile, &failed);
+  indexSourceFile(SF, /*Hash=*/"", *consumer);
+
+  if (!failed && !recordFile.empty())
+    callback(recordFile, SF->getFilename());
+  return failed;
+}
+
+//===----------------------------------------------------------------------===//
+// Index unit file writing
+//===----------------------------------------------------------------------===//
+
+// Used to get std::string pointers to pass as writer::OpaqueModule.
+namespace {
+class StringScratchSpace {
+  std::vector<const std::string *> StrsCreated;
+
+public:
+  const std::string *createString(StringRef str) {
+    auto *s = new std::string(str);
+    StrsCreated.push_back(s);
+    return s;
+  }
+
+  ~StringScratchSpace() {
+    for (auto *str : StrsCreated)
+      delete str;
+  }
+};
+}
+
+static clang::index::writer::ModuleInfo
+getModuleInfoFromOpaqueModule(clang::index::writer::OpaqueModule mod,
+                              SmallVectorImpl<char> &Scratch) {
+  clang::index::writer::ModuleInfo info;
+  info.Name = *static_cast<const std::string*>(mod);
+  return info;
+}
+
+static bool
+emitDataForSwiftSerializedModule(ModuleDecl *module,
+                                 StringRef indexStorePath,
+                                 bool indexSystemModules,
+                                 StringRef targetTriple,
+                                 const clang::CompilerInstance &clangCI,
+                                 DiagnosticEngine &diags,
+                                 IndexUnitWriter &parentUnitWriter);
+
+static void addModuleDependencies(ArrayRef<ModuleDecl::ImportedModule> imports,
+                                  StringRef indexStorePath,
+                                  bool indexSystemModules,
+                                  StringRef targetTriple,
+                                  const clang::CompilerInstance &clangCI,
+                                  DiagnosticEngine &diags,
+                                  IndexUnitWriter &unitWriter,
+                                  StringScratchSpace &moduleNameScratch) {
+  auto &fileMgr = clangCI.getFileManager();
+
+  for (auto &import : imports) {
+    ModuleDecl *mod = import.second;
+    if (mod->getNameStr() == SWIFT_ONONE_SUPPORT)
+      continue; // ignore the Onone support library.
+    if (mod->isSwiftShimsModule())
+      continue;
+
+    for (auto *FU : mod->getFiles()) {
+      switch (FU->getKind()) {
+      case FileUnitKind::Source:
+      case FileUnitKind::Derived:
+      case FileUnitKind::Builtin:
+        break;
+      case FileUnitKind::SerializedAST:
+      case FileUnitKind::ClangModule: {
+        auto *LFU = cast<LoadedFile>(FU);
+        if (auto *F = fileMgr.getFile(LFU->getFilename())) {
+          std::string moduleName = mod->getNameStr();
+          bool withoutUnitName = true;
+          if (FU->getKind() == FileUnitKind::ClangModule) {
+            withoutUnitName = false;
+            auto clangModUnit = cast<ClangModuleUnit>(LFU);
+            if (auto clangMod = clangModUnit->getUnderlyingClangModule()) {
+              moduleName = clangMod->getTopLevelModuleName();
+              // FIXME: clang's -Rremarks do not seem to go through Swift's
+              // diagnostic emitter.
+              clang::index::emitIndexDataForModuleFile(clangMod,
+                                                       clangCI, unitWriter);
+            }
+          } else {
+            // Serialized AST file.
+            // Only index system modules (essentially stdlib and overlays).
+            // We don't officially support binary swift modules, so normally
+            // the index data for user modules would get generated while
+            // building them.
+            if (mod->isSystemModule() && indexSystemModules) {
+              emitDataForSwiftSerializedModule(mod, indexStorePath,
+                                               indexSystemModules,
+                                               targetTriple, clangCI, diags,
+                                               unitWriter);
+              withoutUnitName = false;
+            }
+          }
+          clang::index::writer::OpaqueModule opaqMod =
+              moduleNameScratch.createString(moduleName);
+          unitWriter.addASTFileDependency(F, mod->isSystemModule(), opaqMod,
+                                          withoutUnitName);
+        }
+        break;
+      }
+      }
+    }
+  }
+}
+
+/// \returns true if an error occurred.
+static bool
+emitDataForSwiftSerializedModule(ModuleDecl *module,
+                                 StringRef indexStorePath,
+                                 bool indexSystemModules,
+                                 StringRef targetTriple,
+                                 const clang::CompilerInstance &clangCI,
+                                 DiagnosticEngine &diags,
+                                 IndexUnitWriter &parentUnitWriter) {
+  StringRef filename = module->getModuleFilename();
+  std::string moduleName = module->getNameStr();
+
+  std::string error;
+  auto isUptodateOpt = parentUnitWriter.isUnitUpToDateForOutputFile(/*FilePath=*/filename,
+                                                                /*TimeCompareFilePath=*/filename, error);
+  if (!isUptodateOpt.hasValue()) {
+    diags.diagnose(SourceLoc(), diag::error_index_failed_status_check, error);
+    return true;
+  }
+  if (*isUptodateOpt)
+    return false;
+
+  // FIXME: Would be useful for testing if swift had clang's -Rremark system so
+  // we could output a remark here that we are going to create index data for
+  // a module file.
+
+  // Pairs of (recordFile, groupName).
+  std::vector<std::pair<std::string, std::string>> records;
+
+  if (!module->isStdlibModule()) {
+    std::string recordFile;
+    bool failed = false;
+    auto consumer = makeRecordingConsumer(filename, indexStorePath,
+                                          &diags, &recordFile, &failed);
+    indexModule(module, /*Hash=*/"", *consumer);
+
+    if (failed)
+      return true;
+
+    records.emplace_back(recordFile, moduleName);
+  } else {
+    // Record stdlib groups as if they were submodules.
+
+    auto makeSubmoduleNameFromGroupName = [](StringRef groupName, SmallString<128> &buf) {
+      buf += "Swift";
+      if (groupName.empty())
+        return;
+      buf += '.';
+      for (char ch : groupName) {
+        if (ch == '/')
+          buf += '.';
+        else if (ch == ' ' || ch == '-')
+          buf += '_';
+        else
+          buf += ch;
+      }
+    };
+    auto appendGroupNameForFilename = [](StringRef groupName, SmallString<256> &buf) {
+      if (groupName.empty())
+        return;
+      buf += '_';
+      for (char ch : groupName) {
+        if (ch == '/' || ch ==' ')
+          buf += '_';
+        else
+          buf += ch;
+      }
+    };
+
+    bool failed = false;
+    StdlibGroupsIndexRecordingConsumer groupIndexConsumer([&](StringRef groupName, SymbolTracker &tracker) -> bool {
+      SmallString<128> moduleName;
+      makeSubmoduleNameFromGroupName(groupName, moduleName);
+      SmallString<256> fileNameWithGroup = filename;
+      appendGroupNameForFilename(groupName, fileNameWithGroup);
+
+      std::string outRecordFile;
+      failed = failed || writeRecord(tracker, fileNameWithGroup.str(), indexStorePath, &diags, outRecordFile);
+      if (failed)
+        return false;
+      records.emplace_back(outRecordFile, moduleName.str());
+      return true;
+    });
+    indexModule(module, /*Hash=*/"", groupIndexConsumer);
+    if (failed)
+      return true;
+  }
+
+  auto &fileMgr = clangCI.getFileManager();
+  bool isSystem = module->isSystemModule();
+  // FIXME: Get real values for the following.
+  StringRef swiftVersion;
+  StringRef sysrootPath = clangCI.getHeaderSearchOpts().Sysroot;
+  std::string indexUnitToken = module->getModuleFilename();
+  // For indexing serialized modules 'debug compilation' is irrelevant, so
+  // set it to true by default.
+  bool isDebugCompilation = true;
+
+  IndexUnitWriter unitWriter(fileMgr, indexStorePath,
+    "swift", swiftVersion, indexUnitToken, moduleName,
+    /*MainFile=*/nullptr, isSystem, /*IsModuleUnit=*/true,
+    isDebugCompilation, targetTriple, sysrootPath, getModuleInfoFromOpaqueModule);
+
+  const clang::FileEntry *FE = fileMgr.getFile(filename);
+  bool isSystemModule = module->isSystemModule();
+  for (auto &pair : records) {
+    std::string &recordFile = pair.first;
+    std::string &groupName = pair.second;
+    if (recordFile.empty())
+      continue;
+    clang::index::writer::OpaqueModule mod = &groupName;
+    unitWriter.addRecordFile(recordFile, FE, isSystemModule, mod);
+  }
+
+  SmallVector<ModuleDecl::ImportedModule, 8> imports;
+  module->getImportedModules(imports, ModuleDecl::ImportFilter::All);
+  StringScratchSpace moduleNameScratch;
+  addModuleDependencies(imports, indexStorePath, indexSystemModules,
+                        targetTriple, clangCI, diags, unitWriter, moduleNameScratch);
+
+  if (unitWriter.write(error)) {
+    diags.diagnose(SourceLoc(), diag::error_write_index_unit, error);
+    return true;
+  }
+
+  return false;
+}
+
+static bool
+recordSourceFileUnit(SourceFile *primarySourceFile, StringRef indexUnitToken,
+                     StringRef indexStorePath, bool indexSystemModules,
+                     bool isDebugCompilation, StringRef targetTriple,
+                     ArrayRef<const clang::FileEntry *> fileDependencies,
+                     const clang::CompilerInstance &clangCI,
+                     DiagnosticEngine &diags) {
+  auto &fileMgr = clangCI.getFileManager();
+  auto *module = primarySourceFile->getParentModule();
+  bool isSystem = module->isSystemModule();
+  auto *mainFile = fileMgr.getFile(primarySourceFile->getFilename());
+  // FIXME: Get real values for the following.
+  StringRef swiftVersion;
+  StringRef sysrootPath = clangCI.getHeaderSearchOpts().Sysroot;
+
+  IndexUnitWriter unitWriter(fileMgr, indexStorePath,
+    "swift", swiftVersion, indexUnitToken, module->getNameStr(),
+    mainFile, isSystem, /*isModuleUnit=*/false, isDebugCompilation,
+    targetTriple, sysrootPath, getModuleInfoFromOpaqueModule);
+
+  // Module dependencies.
+  SmallVector<ModuleDecl::ImportedModule, 8> imports;
+  primarySourceFile->getImportedModules(imports, ModuleDecl::ImportFilter::All);
+  StringScratchSpace moduleNameScratch;
+  addModuleDependencies(imports, indexStorePath, indexSystemModules,
+                        targetTriple, clangCI, diags, unitWriter, moduleNameScratch);
+
+  // File dependencies.
+  for (auto *F : fileDependencies)
+    unitWriter.addFileDependency(F, /*FIXME:isSystem=*/false, /*Module=*/nullptr);
+
+  recordSourceFile(primarySourceFile, indexStorePath, diags,
+                   [&](StringRef recordFile, StringRef filename) {
+    unitWriter.addRecordFile(recordFile, fileMgr.getFile(filename),
+                             module->isSystemModule(), /*Module=*/nullptr);
+  });
+
+  std::string error;
+  if (unitWriter.write(error)) {
+    diags.diagnose(SourceLoc(), diag::error_write_index_unit, error);
+    return true;
+  }
+
+  return false;
+}
+
+// Not currently used, see related comments in the call sites.
+#if 0
+static void
+collectFileDependencies(llvm::SetVector<const clang::FileEntry *> &result,
+                        const DependencyTracker &dependencyTracker,
+                        ModuleDecl *module, clang::FileManager &fileMgr) {
+  for (auto *F : module->getFiles()) {
+    if (auto *SF = dyn_cast<SourceFile>(F)) {
+      if (auto *dep = fileMgr.getFile(SF->getFilename())) {
+        result.insert(dep);
+      }
+    }
+  }
+  for (StringRef filename : dependencyTracker.getDependencies()) {
+    if (auto *F = fileMgr.getFile(filename))
+      result.insert(F);
+  }
+}
+#endif
+
+//===----------------------------------------------------------------------===//
+// Indexing entry points
+//===----------------------------------------------------------------------===//
+
+bool index::indexAndRecord(SourceFile *primarySourceFile,
+                           StringRef indexUnitToken,
+                           StringRef indexStorePath,
+                           bool indexSystemModules,
+                           bool isDebugCompilation,
+                           StringRef targetTriple,
+                           const DependencyTracker &dependencyTracker) {
+  auto &astContext = primarySourceFile->getASTContext();
+  auto &clangCI = astContext.getClangModuleLoader()->getClangInstance();
+  auto &diags = astContext.Diags;
+
+  std::string error;
+  if (IndexUnitWriter::initIndexDirectory(indexStorePath, error)) {
+    diags.diagnose(SourceLoc(), diag::error_create_index_dir, error);
+    return true;
+  }
+
+  llvm::SetVector<const clang::FileEntry *> fileDependencies;
+  // FIXME: This is not desirable because:
+  // 1. It picks shim header files as file dependencies
+  // 2. Having all the other swift files of the module as file dependencies ends
+  //   up making all of them associated with all the other files as main files.
+  //   It's better to associate each swift file with the unit that recorded it
+  //   as the main one.
+  // Keeping the code in case we want to revisit.
+#if 0
+  auto *module = primarySourceFile->getParentModule();
+  collectFileDependencies(fileDependencies, dependencyTracker, module, fileMgr);
+#endif
+
+  return recordSourceFileUnit(primarySourceFile, indexUnitToken,
+                              indexStorePath, indexSystemModules,
+                              isDebugCompilation, targetTriple,
+                              fileDependencies.getArrayRef(),
+                              clangCI, diags);
+}
+
+bool index::indexAndRecord(ModuleDecl *module,
+                           ArrayRef<std::string> indexUnitTokens,
+                           StringRef moduleUnitToken,
+                           StringRef indexStorePath,
+                           bool indexSystemModules,
+                           bool isDebugCompilation,
+                           StringRef targetTriple,
+                           const DependencyTracker &dependencyTracker) {
+  auto &astContext = module->getASTContext();
+  auto &clangCI = astContext.getClangModuleLoader()->getClangInstance();
+  auto &diags = astContext.Diags;
+
+  std::string error;
+  if (IndexUnitWriter::initIndexDirectory(indexStorePath, error)) {
+    diags.diagnose(SourceLoc(), diag::error_create_index_dir, error);
+    return true;
+  }
+
+  // Add the current module's source files to the dependencies.
+  llvm::SetVector<const clang::FileEntry *> fileDependencies;
+  // FIXME: This is not desirable because:
+  // 1. It picks shim header files as file dependencies
+  // 2. Having all the other swift files of the module as file dependencies ends
+  //   up making all of them associated with all the other files as main files.
+  //   It's better to associate each swift file with the unit that recorded it
+  //   as the main one.
+  // Keeping the code in case we want to revisit.
+#if 0
+  collectFileDependencies(fileDependencies, dependencyTracker, module, fileMgr);
+#endif
+
+  // Write a unit for each source file.
+  unsigned unitIndex = 0;
+  for (auto *F : module->getFiles()) {
+    if (auto *SF = dyn_cast<SourceFile>(F)) {
+      if (unitIndex == indexUnitTokens.size()) {
+        diags.diagnose(SourceLoc(), diag::error_index_inputs_more_than_outputs);
+        return true;
+      }
+      if (recordSourceFileUnit(SF, indexUnitTokens[unitIndex],
+                               indexStorePath, indexSystemModules,
+                               isDebugCompilation, targetTriple,
+                               fileDependencies.getArrayRef(),
+                               clangCI, diags))
+        return true;
+      unitIndex += 1;
+    }
+  }
+
+  // In the case where inputs are swift modules, like in the merge-module step,
+  // ignore the inputs; associated unit files for the modules' source inputs
+  // should have been generated at swift module creation time.
+
+  return false;
+}
diff --git a/test/ClangImporter/Inputs/SwiftPrivateAttr.txt b/test/ClangImporter/Inputs/SwiftPrivateAttr.txt
index 6ea47fa..590c5e9 100644
--- a/test/ClangImporter/Inputs/SwiftPrivateAttr.txt
+++ b/test/ClangImporter/Inputs/SwiftPrivateAttr.txt
@@ -107,7 +107,7 @@
   static var __PrivA: NSOptions { get }
   static var B: NSOptions { get }
 }
-class __PrivCFType : _CFObject {
+class __PrivCFType {
 }
 @available(swift, obsoleted: 3, renamed: "__PrivCFType")
 typealias __PrivCFTypeRef = __PrivCFType
diff --git a/test/ClangImporter/Inputs/custom-modules/Protocols.h b/test/ClangImporter/Inputs/custom-modules/Protocols.h
index 43ad828..552adbd 100644
--- a/test/ClangImporter/Inputs/custom-modules/Protocols.h
+++ b/test/ClangImporter/Inputs/custom-modules/Protocols.h
@@ -9,3 +9,12 @@
 Class <FooProto, AnotherProto> _Nonnull processComboType(Class <FooProto, AnotherProto> _Nonnull);
 Class <AnotherProto, FooProto> _Nonnull processComboType2(Class <AnotherProto, FooProto> _Nonnull);
 
+
+@protocol SubProto <FooProto>
+@end
+
+@interface ProtocolTestingBase
+@end
+
+@interface SubProtoImpl: ProtocolTestingBase <SubProto>
+@end
diff --git a/test/ClangImporter/protocol-conformance-in-extension.swift b/test/ClangImporter/protocol-conformance-in-extension.swift
new file mode 100644
index 0000000..69a4c83
--- /dev/null
+++ b/test/ClangImporter/protocol-conformance-in-extension.swift
@@ -0,0 +1,21 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t/a~partial.swiftmodule -I %S/Inputs/custom-modules -module-name TEST -primary-file %s
+// RUN: %target-swift-frontend -emit-module -o %t/test.swiftmodule -I %S/Inputs/custom-modules -module-name TEST %t/a~partial.swiftmodule
+
+// REQUIRES: objc_interop
+
+import TestProtocols
+
+// The protocol in the extension has to refine something that the base class
+// conforms to to trigger the error in rdar://problem/32346184.
+protocol SomeSwiftProto: Equatable {}
+extension ProtocolTestingBase: Equatable {
+  public static func ==(left: ProtocolTestingBase, right: ProtocolTestingBase) -> Bool {
+    return left === right
+  }
+}
+
+// The extension going through the typealias also makes a difference.
+typealias SpecialObject = SubProtoImpl
+extension SpecialObject: SomeSwiftProto {
+}
diff --git a/test/Driver/bridging-pch.swift b/test/Driver/bridging-pch.swift
index bb3ac15..dbb4a28 100644
--- a/test/Driver/bridging-pch.swift
+++ b/test/Driver/bridging-pch.swift
@@ -32,6 +32,12 @@
 // PERSISTENT-YESPCHACT: 2: input, "{{.*}}bridging-pch.swift", swift
 // PERSISTENT-YESPCHACT: 3: compile, {2, 1}, none
 
+// RUN: %swiftc_driver -c -driver-print-actions -embed-bitcode -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch %s 2>&1 | %FileCheck %s -check-prefix=PERSISTENT-YESPCHACTBC
+// PERSISTENT-YESPCHACTBC: 0: input, "{{.*}}Inputs/bridging-header.h", objc-header
+// PERSISTENT-YESPCHACTBC: 1: generate-pch, {0}, none
+// PERSISTENT-YESPCHACTBC: 2: input, "{{.*}}bridging-pch.swift", swift
+// PERSISTENT-YESPCHACTBC: 3: compile, {2, 1}, llvm-bc
+
 // RUN: %swiftc_driver -typecheck -disable-bridging-pch -driver-print-actions -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch %s 2>&1 | %FileCheck %s -check-prefix=NOPCHACT
 
 // RUN: %swiftc_driver -typecheck -driver-print-jobs -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch -disable-bridging-pch %s 2>&1 | %FileCheck %s -check-prefix=PERSISTENT-DISABLED-YESPCHJOB
diff --git a/test/Driver/options-repl.swift b/test/Driver/options-repl.swift
index 7967fdb..d980ae8 100644
--- a/test/Driver/options-repl.swift
+++ b/test/Driver/options-repl.swift
@@ -16,7 +16,7 @@
 
 
 // RUN: %swift_driver -lldb-repl -### | %FileCheck -check-prefix=LLDB %s
-// RUN: %swift_driver -lldb-repl -DA,B,C -DD -L /path/to/libraries -L /path/to/more/libraries -F /path/to/frameworks -lsomelib -framework SomeFramework -sdk / -I "this folder" -module-name Test -target %target-triple -### | %FileCheck -check-prefix=LLDB-OPTS %s
+// RUN: %swift_driver -lldb-repl -D A -DB -D C -DD -L /path/to/libraries -L /path/to/more/libraries -F /path/to/frameworks -lsomelib -framework SomeFramework -sdk / -I "this folder" -module-name Test -target %target-triple -### | %FileCheck -check-prefix=LLDB-OPTS %s
 
 // LLDB: lldb{{"?}} {{"?}}--repl=
 // LLDB-NOT: -module-name
@@ -24,7 +24,7 @@
 
 // LLDB-OPTS: lldb{{"?}} "--repl=
 // LLDB-OPTS-DAG: -target {{[^ ]+}}
-// LLDB-OPTS-DAG: -D A,B,C -D D
+// LLDB-OPTS-DAG: -D A -D B -D C -D D
 // LLDB-OPTS-DAG: -sdk /
 // LLDB-OPTS-DAG: -L /path/to/libraries
 // LLDB-OPTS-DAG: -L /path/to/more/libraries
diff --git a/test/Frontend/unknown-arguments.swift b/test/Frontend/unknown-arguments.swift
index d80a2a7..e8f8553 100644
--- a/test/Frontend/unknown-arguments.swift
+++ b/test/Frontend/unknown-arguments.swift
@@ -6,3 +6,9 @@
 // RUN: not %swiftc_driver -c %s -o %t.o -Xfrontend -fake-frontend-arg -Xfrontend fakevalue 2>&1 | %FileCheck -check-prefix=XFRONTEND %s
 
 // XFRONTEND: <unknown>:0: error: unknown argument: '-fake-frontend-arg'
+
+// RUN: not %swiftc_driver -D Correct -DAlsoCorrect -D@#%! -D Swift=Cool -D-D -c %s -o %t.o 2>&1 | %FileCheck -check-prefix=INVALID-COND %s
+// INVALID-COND: <unknown>:0: error: conditional compilation flags must be valid Swift identifiers (rather than '@#%!')
+// INVALID-COND-NEXT: <unknown>:0: warning: conditional compilation flags do not have values in Swift; they are either present or absent (rather than 'Swift=Cool')
+// INVALID-COND-NEXT: <unknown>:0: error: conditional compilation flags must be valid Swift identifiers (rather than '-D')
+
diff --git a/test/Index/Store/Inputs/ClangModuleA.h b/test/Index/Store/Inputs/ClangModuleA.h
new file mode 100644
index 0000000..ea06ce2
--- /dev/null
+++ b/test/Index/Store/Inputs/ClangModuleA.h
@@ -0,0 +1 @@
+void funcA(void);
diff --git a/test/Index/Store/Inputs/ClangModuleB.h b/test/Index/Store/Inputs/ClangModuleB.h
new file mode 100644
index 0000000..ce316e2
--- /dev/null
+++ b/test/Index/Store/Inputs/ClangModuleB.h
@@ -0,0 +1,2 @@
+@import ClangModuleA;
+void funcB(void);
diff --git a/test/Index/Store/Inputs/ClangModuleCSub1.h b/test/Index/Store/Inputs/ClangModuleCSub1.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Index/Store/Inputs/ClangModuleCSub1.h
diff --git a/test/Index/Store/Inputs/ClangModuleCSub2.h b/test/Index/Store/Inputs/ClangModuleCSub2.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Index/Store/Inputs/ClangModuleCSub2.h
diff --git a/test/Index/Store/Inputs/SwiftModuleA.swift b/test/Index/Store/Inputs/SwiftModuleA.swift
new file mode 100644
index 0000000..59e7758
--- /dev/null
+++ b/test/Index/Store/Inputs/SwiftModuleA.swift
@@ -0,0 +1 @@
+public func funcSwiftA() {}
diff --git a/test/Index/Store/Inputs/SwiftModuleB.swift b/test/Index/Store/Inputs/SwiftModuleB.swift
new file mode 100644
index 0000000..b12db68
--- /dev/null
+++ b/test/Index/Store/Inputs/SwiftModuleB.swift
@@ -0,0 +1,2 @@
+import SwiftModuleA
+public func funcSwiftB() { funcSwiftA() }
diff --git a/test/Index/Store/Inputs/bridge-head.h b/test/Index/Store/Inputs/bridge-head.h
new file mode 100644
index 0000000..b25d652
--- /dev/null
+++ b/test/Index/Store/Inputs/bridge-head.h
@@ -0,0 +1 @@
+#include "bridge-include.h"
diff --git a/test/Index/Store/Inputs/bridge-include.h b/test/Index/Store/Inputs/bridge-include.h
new file mode 100644
index 0000000..55a0722
--- /dev/null
+++ b/test/Index/Store/Inputs/bridge-include.h
@@ -0,0 +1,2 @@
+int includedFunc(int a);
+int MY_CONST = 2;
\ No newline at end of file
diff --git a/test/Index/Store/Inputs/module.modulemap b/test/Index/Store/Inputs/module.modulemap
new file mode 100644
index 0000000..a25324f
--- /dev/null
+++ b/test/Index/Store/Inputs/module.modulemap
@@ -0,0 +1,20 @@
+module ClangModuleA {
+  header "ClangModuleA.h"
+  export *
+}
+module ClangModuleB {
+  header "ClangModuleB.h"
+  export *
+}
+
+module ClangModuleC {
+  module Sub1 {
+    header "ClangModuleCSub1.h"
+    export *
+  }
+
+  module Sub2 {
+    header "ClangModuleCSub2.h"
+    export *
+  }
+}
diff --git a/test/Index/Store/driver-index.swift b/test/Index/Store/driver-index.swift
new file mode 100644
index 0000000..b8007d0
--- /dev/null
+++ b/test/Index/Store/driver-index.swift
@@ -0,0 +1,2 @@
+// RUN: %swiftc_driver -driver-print-jobs -index-file -index-file-path %s %S/Inputs/SwiftModuleA.swift %s -o %t.output_for_index -index-store-path %t.index_store -module-name driver_index 2>&1 | %FileCheck %s
+// CHECK: {{.*}}swift -frontend -typecheck {{.*}}-primary-file {{.*}}driver-index.swift {{.*}}SwiftModuleA.swift {{.*}}driver-index.swift {{.*}}-o {{.*}}.output_for_index {{.*}}-index-store-path {{.*}}.index_store -index-system-modules
diff --git a/test/Index/Store/output-failure.swift b/test/Index/Store/output-failure.swift
new file mode 100644
index 0000000..24167e3
--- /dev/null
+++ b/test/Index/Store/output-failure.swift
@@ -0,0 +1,41 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir %t/idx
+
+// Before indexing, do a dry-run to ensure any clang modules are cached. We
+// want to isolate the error that comes from swift's indexing support, not
+// any failures indexing a clang module.
+// RUN: %target-swift-frontend %s -typecheck
+
+// RUN: chmod -w %t/idx
+// RUN: not %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o 2> %t/dir.txt || chmod +w %t/idx
+// This is not combined with the previous chmod because of pipefail mode.
+// RUN: chmod +w %t/idx
+// RUN: %FileCheck %s -check-prefix=DIR_ERR < %t/dir.txt
+// DIR_ERR: error: creating index directory
+
+// RUN: %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o
+// test -s %t/idx/*/units/oof.o*
+
+// RUN: chmod -w %t/idx/*/units
+// RUN: not %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o 2> %t/file.txt || chmod +w %t/idx/*/units
+// This is not combined with the previous chmod because of pipefail mode.
+// RUN: chmod +w %t/idx/*/units
+// RUN: %FileCheck %s -check-prefix=FILE_ERR < %t/file.txt
+// FILE_ERR: error: writing index unit file
+
+// RUN: rm -rf %t/idx/*/records/*
+// RUN: chmod -x %t/idx/*/records
+// RUN: not %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o 2> %t/record.txt || chmod +x %t/idx/*/records
+// This is not combined with the previous chmod because of pipefail mode.
+// RUN: chmod +x %t/idx/*/records
+// RUN: %FileCheck %s -check-prefix=RECORD_ERR < %t/record.txt
+// RECORD_ERR: error: writing index record file
+
+// RUN: rm -rf %t/idx/*/records/*
+// RUN: chmod -w %t/idx/*/records
+// RUN: not %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o 2> %t/record2.txt || chmod +w %t/idx/*/records
+// This is not combined with the previous chmod because of pipefail mode.
+// RUN: chmod +w %t/idx/*/records
+// RUN: %FileCheck %s -check-prefix=RECORD_ERR < %t/record2.txt
+
+func foo() {}
diff --git a/test/Index/Store/record-comments.swift b/test/Index/Store/record-comments.swift
new file mode 100644
index 0000000..5d356f1
--- /dev/null
+++ b/test/Index/Store/record-comments.swift
@@ -0,0 +1,19 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t.o -typecheck %s
+// RUN: c-index-test core -print-record %t/idx | %FileCheck %s
+
+// XFAIL: linux
+
+// CHECK: record-comments.swift
+// CHECK: ------------
+// CHECK: comment-tag/Swift | <no-name> | t:this_is_a_tag | <no-cgname> | Def -
+// CHECK: comment-tag/Swift | <no-name> | t:and_another | <no-cgname> | Def -
+// CHECK: ------------
+
+/// Hello
+/// - Tag: this_is_a_tag
+/// - Tag: and_another
+func foo() {}
+// CHECK: [[@LINE-3]]:5 | comment-tag/Swift | t:this_is_a_tag | Def | rel: 0
+// CHECK: [[@LINE-3]]:5 | comment-tag/Swift | t:and_another | Def | rel: 0
+// CHECK: [[@LINE-3]]:6 | function/Swift |
diff --git a/test/Index/Store/record-dependency.swift b/test/Index/Store/record-dependency.swift
new file mode 100644
index 0000000..6c3777b
--- /dev/null
+++ b/test/Index/Store/record-dependency.swift
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t/file.o -typecheck %s
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+// CHECK: DEPEND START
+// CHECK: Record | user | {{.*}}record-dependency.swift | record-dependency.swift-
+// CHECK: DEPEND END
+
+// RUN: echo 'func bar() {}' > %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx2 -emit-module -module-name main -emit-module-path %t/main.swiftmodule %s %t/s2.swift -o %t/file.o -o %t/s2.o
+// RUN: c-index-test core -print-unit %t/idx2 | %FileCheck %s -check-prefix=TWO_RECORDS
+// TWO_RECORDS: file.o-
+// TWO_RECORDS: DEPEND START
+// TWO_RECORDS: Record | user | {{.*}}record-dependency.swift | record-dependency.swift-
+// TWO_RECORDS: DEPEND END
+// TWO_RECORDS: s2.o-
+// TWO_RECORDS: DEPEND START
+// TWO_RECORDS: Record | user | {{.*}}s2.swift | s2.swift-
+// TWO_RECORDS: DEPEND END
+
+// XFAIL: linux
+
+func foo() {}
diff --git a/test/Index/Store/record-empty.swift b/test/Index/Store/record-empty.swift
new file mode 100644
index 0000000..c7bdd9e
--- /dev/null
+++ b/test/Index/Store/record-empty.swift
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t/file.o -typecheck -primary-file %s
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t/file.o -typecheck %s
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+// CHECK-NOT: Record{{.*}}record-empty
+
+// XFAIL: linux
diff --git a/test/Index/Store/record-hashing.swift b/test/Index/Store/record-hashing.swift
new file mode 100644
index 0000000..665d4a3
--- /dev/null
+++ b/test/Index/Store/record-hashing.swift
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: echo "func foo() {}" > %t/theinput.swift
+
+// RUN: %target-swift-frontend -index-store-path %t/idx -typecheck %t/theinput.swift -o %t/s.o
+// RUN: ls %t/idx/*/records/* | grep "theinput.swift" | count 1
+// RUN: cp -r %t/idx %t/idx-orig
+
+// RUN: touch %t/theinput.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -typecheck %t/theinput.swift -o %t/s.o
+// RUN: diff -r -u %t/idx/*/records %t/idx-orig/*/records
+// No change in record.
+
+// RUN: echo '// Comment.' >> %t/theinput.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -typecheck %t/theinput.swift -o %t/s.o
+// RUN: diff -r -u %t/idx/*/records %t/idx-orig/*/records
+// No change in record.
+
+// RUN: echo 'func goo() {}' >> %t/theinput.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -typecheck %t/theinput.swift -o %t/s.o
+// RUN: not diff -r -u %t/idx/*/records %t/idx-orig/*/records
+// RUN: ls %t/idx/*/records/* | grep "theinput.swift" | count 2
+// Changed!  Wrote a new record.
diff --git a/test/Index/Store/record-sourcefile.swift b/test/Index/Store/record-sourcefile.swift
new file mode 100644
index 0000000..129f7cc
--- /dev/null
+++ b/test/Index/Store/record-sourcefile.swift
@@ -0,0 +1,155 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx1 -o %t/file.o -typecheck %s
+// RUN: %target-swift-frontend -index-store-path %t/idx2 -o %t/file.o -typecheck -primary-file %s
+// RUN: c-index-test core -print-record %t/idx1 | %FileCheck %s
+// RUN: c-index-test core -print-record %t/idx2 | %FileCheck %s
+
+// XFAIL: linux
+
+// CHECK: record-sourcefile.swift
+// CHECK: ------------
+// CHECK: struct/Swift | S1 | s:4file2S1V | <no-cgname> | Def,Ref,RelCont -
+// CHECK: instance-method/acc-get/Swift | getter:property | s:4file2S1V8propertySifg | <no-cgname> | Def,Ref,Call,Impl,RelChild,RelRec,RelCall,RelAcc,RelCont - 
+// CHECK: instance-property/Swift | property | [[property_USR:s:4file2S1V8propertySiv]] | <no-cgname> | Def,Ref,Read,RelChild,RelCont -
+// CHECK: static-method/acc-get/Swift | getter:staticProperty | s:4file2S1V14staticPropertySifg | <no-cgname> | Def,Ref,Call,Impl,RelChild,RelRec,RelCall,RelAcc,RelCont -
+// CHECK: static-property/Swift | staticProperty | s:{{.*}} | <no-cgname> | Def,Ref,Read,RelChild,RelCont -
+// CHECK: instance-property/Swift | computedPropertyGetSet | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: struct/Swift | Int | s:Si | <no-cgname> | Ref -
+// CHECK: instance-method/acc-get/Swift | getter:computedPropertyGetSet | s:4file2S1V22computedPropertyGetSetSifg | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-method/acc-set/Swift | setter:computedPropertyGetSet | s:4file2S1V22computedPropertyGetSetSifs | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-property/Swift | computedPropertyWillDid | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: instance-method/acc-willset/Swift | willSet:computedPropertyWillDid | s:4file2S1V23computedPropertyWillDidSifw | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-method/acc-didset/Swift | didSet:computedPropertyWillDid | s:4file2S1V23computedPropertyWillDidSifW | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-property/Swift | computedPropertyAddressor | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: instance-method/acc-addr/Swift | <no-name> | s:{{.*}} | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-method/acc-mutaddr/Swift | <no-name> | s:{{.*}} | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-method/Swift | method() | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: static-method/Swift | staticMethod() | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: instance-property/subscript/Swift | subscript(_:) | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: instance-method/acc-get/Swift | getter:subscript(_:) | s:{{.*}} | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: protocol/Swift | P1 | s:{{.*}} | <no-cgname> | Def -
+// CHECK: type-alias/associated-type/Swift | AT | s:{{.*}} | <no-cgname> | Def,Ref,RelChild -
+// CHECK: type-alias/Swift | TA | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: class/Swift | C1 | s:{{.*}} | <no-cgname> | Def,Ref,RelBase,RelCont -
+// CHECK: instance-method/Swift | method() | s:{{.*}} | <no-cgname> | Def,Ref,Call,Dyn,RelChild,RelRec,RelCall,RelCont -
+// CHECK: class/Swift | C2 | s:{{.*}} | <no-cgname> | Def -
+// CHECK: instance-method/Swift | method() | s:{{.*}} | <no-cgname> | Def,Dyn,RelChild,RelOver -
+// CHECK: function/Swift | takeC1(x:) | s:{{.*}} | <no-cgname> | Def -
+// CHECK: instance-method(test)/Swift | testFoo() | s:{{.*}} | <no-cgname> | Def,Dyn,RelChild -
+// CHECK: ------------
+
+// CHECK: [[@LINE+1]]:8 | struct/Swift | [[S1_USR:s:.*]] | Def | rel: 0
+struct S1 {
+// CHECK: [[@LINE+2]]:7 | instance-property/Swift | [[property_USR]] | Def,RelChild | rel: 1
+// CHECK-NEXT:  RelChild | [[S1_USR]]
+  let property = 1
+// CHECK: [[@LINE+2]]:14 | static-property/Swift | [[staticProperty_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  static let staticProperty = 2
+
+// CHECK: [[@LINE+3]]:7 | instance-property/Swift | [[computedPropertyGetSet_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+// CHECK: [[@LINE+1]]:31 | struct/Swift | s:Si | Ref | rel: 0
+  var computedPropertyGetSet: Int {
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-get/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyGetSet_USR]]
+    get { return 1 }
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-set/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyGetSet_USR]]
+    set { }
+  }
+
+// CHECK: [[@LINE+2]]:7 | instance-property/Swift | [[computedPropertyWillDid_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  var computedPropertyWillDid: Int {
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-willset/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyWillDid_USR]]
+    willSet { }
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-didset/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyWillDid_USR]]
+    didSet { }
+  }
+
+// CHECK: [[@LINE+2]]:7 | instance-property/Swift | [[computedPropertyAddressor_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  var computedPropertyAddressor: Int {
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-addr/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyAddressor_USR]]
+    unsafeAddress { }
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-mutaddr/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyAddressor_USR]]
+    unsafeMutableAddress { }
+  }
+
+// CHECK: [[@LINE+2]]:8 | instance-method/Swift | [[method_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  func method() {
+    _ = self
+// CHECK: [[@LINE+4]]:9 | instance-method/acc-get/Swift | s:{{.*}} | Ref,Call,Impl,RelRec,RelCall,RelCont | rel: 2
+// CHECK-NEXT: RelCall,RelCont | [[method_USR]]
+// CHECK-NEXT: RelRec | [[S1_USR]]
+// CHECK: [[@LINE+1]]:9 | instance-property/Swift | s:{{.*}} | Ref,Read,RelCont | rel: 1
+    _ = property
+  }
+
+// CHECK: [[@LINE+2]]:15 | static-method/Swift | [[staticMethod_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  static func staticMethod() {
+// CHECK: [[@LINE+5]]:9 | struct/Swift | s:{{.*}} | Ref,RelCont | rel: 1
+// CHECK: [[@LINE+4]]:12 | static-method/acc-get/Swift | s:{{.*}} | Ref,Call,Impl,RelRec,RelCall,RelCont | rel: 2
+// CHECK-NEXT: RelCall,RelCont | [[staticMethod_USR]]
+// CHECK-NEXT: RelRec | [[S1_USR]]
+// CHECK: [[@LINE+1]]:12 | static-property/Swift | s:{{.*}} | Ref,Read,RelCont | rel: 1
+    _ = S1.staticProperty
+  }
+
+// CHECK: [[@LINE+4]]:3 | instance-property/subscript/Swift | [[S1_subscript_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+// CHECK: [[@LINE+2]]:28 | instance-method/acc-get/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[S1_subscript_USR]]
+  subscript(x: Int) -> Int { return 1 }
+}
+
+// CHECK: [[@LINE+1]]:10 | protocol/Swift | [[P1_USR:s:.*]] | Def | rel: 0
+protocol P1 {
+// CHECK: [[@LINE+2]]:18 | type-alias/associated-type/Swift | s:{{.*}} | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[P1_USR]]
+  associatedtype AT
+// CHECK: [[@LINE+3]]:13 | type-alias/Swift | s:{{.*}} | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[P1_USR]]
+// CHECK: [[@LINE+1]]:18 | type-alias/associated-type/Swift | s:{{.*}} | Ref | rel: 0
+  typealias TA = AT
+}
+
+// CHECK: [[@LINE+1]]:7 | class/Swift | [[C1_USR:s:.*]] | Def | rel: 0
+class C1 {
+// CHECK: [[@LINE+2]]:8 | instance-method/Swift | [[C1_foo_USR:s:.*]] | Def,Dyn,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[C1_USR]]
+  func method() {}
+}
+// CHECK: [[@LINE+3]]:7 | class/Swift | [[C2_USR:s:.*]] | Def | rel: 0
+// CHECK: [[@LINE+2]]:12 | class/Swift | [[C1_USR]] | Ref,RelBase | rel: 1
+// CHECK-NEXT: RelBase | [[C2_USR]]
+class C2 : C1 {
+// CHECK: [[@LINE+3]]:17 | instance-method/Swift | s:{{.*}} | Def,Dyn,RelChild,RelOver | rel: 2
+// CHECK-NEXT: RelOver | [[C1_foo_USR]]
+// CHECK-NEXT: RelChild | [[C2_USR]]
+  override func method() {}
+}
+
+// CHECK: [[@LINE+2]]:6 | function/Swift | [[takeC1_USR:s:.*]] | Def | rel: 0
+// CHECK: [[@LINE+1]]:16 | class/Swift | s:{{.*}} | Ref,RelCont | rel: 1
+func takeC1(x: C1) {
+// CHECK: [[@LINE+3]]:5 | instance-method/Swift | s:{{.*}} | Ref,Call,Dyn,RelRec,RelCall,RelCont | rel: 2
+// CHECK-NEXT: RelCall,RelCont | [[takeC1_USR]]
+// CHECK-NEXT: RelRec | [[C1_USR]]
+  x.method()
+}
+
+func test1() {}
+class XCTestCase {}
+class MyTestCase: XCTestCase {
+// CHECK: [[@LINE+2]]:8 | instance-method(test)/Swift | s:{{.*}} | Def,Dyn,RelChild | rel: 1
+// CHECK-NEXT: RelChild | s:4file10MyTestCaseC
+  func testFoo() { test1() }
+}
diff --git a/test/Index/Store/record-with-compile-error.swift b/test/Index/Store/record-with-compile-error.swift
new file mode 100644
index 0000000..0cb017d
--- /dev/null
+++ b/test/Index/Store/record-with-compile-error.swift
@@ -0,0 +1,12 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t/file.o -typecheck %s -verify
+// RUN: c-index-test core -print-record %t/idx | %FileCheck %s
+
+// CHECK: function/Swift | test1() | [[TEST1_FUNC:.*]] | <no-cgname> | Def
+// CHECK: [[@LINE+1]]:6 | function/Swift | [[TEST1_FUNC]]
+func test1() {
+  unresolved() // expected-error {{use of unresolved identifier}}
+}
diff --git a/test/Index/Store/unit-from-compile.swift b/test/Index/Store/unit-from-compile.swift
new file mode 100644
index 0000000..2ddfb6e
--- /dev/null
+++ b/test/Index/Store/unit-from-compile.swift
@@ -0,0 +1,24 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: %target-swift-frontend -c -index-store-path %t/idx %s -o %t/file1.o -module-name some_module_test
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+// RUN: %target-swift-frontend -c -index-store-path %t/idx_opt %s -o %t/file1.o -module-name some_module_test -O
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=OPT
+
+// CHECK: file1.o
+// CHECK: provider: swift
+// CHECK: is-system: 0
+// CHECK: is-module: 0
+// CHECK: module-name: some_module_test
+// CHECK: has-main: 1
+// CHECK: main-path: {{.*}}/unit-from-compile.swift
+// CHECK: out-file: {{.*}}/file1.o
+// CHECK: is-debug: 1
+
+// CHECK: DEPEND START
+// CHECK: Unit | system | {{.*}}/Swift.swiftmodule |
+// CHECK: DEPEND END (1)
+
+// OPT: is-debug: 1
diff --git a/test/Index/Store/unit-multiple-sourcefiles.swift b/test/Index/Store/unit-multiple-sourcefiles.swift
new file mode 100644
index 0000000..a35350b
--- /dev/null
+++ b/test/Index/Store/unit-multiple-sourcefiles.swift
@@ -0,0 +1,33 @@
+// XFAIL: linux
+
+//===--- Building source files separately with a module merge at the end
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: touch %t/s1.swift %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -primary-file %t/s1.swift %t/s2.swift -o %t/s1.o -c -module-name main -emit-module -emit-module-path %t/s1.swiftmodule
+// RUN: %target-swift-frontend -index-store-path %t/idx %t/s1.swift -primary-file %t/s2.swift -o %t/s2.o -c -module-name main -emit-module -emit-module-path %t/s2.swiftmodule
+// RUN: %target-swift-frontend -index-store-path %t/idx %t/s1.swiftmodule %t/s2.swiftmodule -emit-module -o %t/main.swiftmodule -module-name main
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+
+//===--- Building source files together (e.g. WMO)
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: touch %t/s1.swift %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx %t/s1.swift %t/s2.swift -o %t/s1.o -o %t/s2.o -c -module-name main -emit-module -emit-module-path %t/main.swiftmodule
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+
+// CHECK-NOT: main.swiftmodule-{{[A-Z0-9]*}}
+
+// CHECK: s1.o-{{[A-Z0-9]*}}
+// CHECK: --------
+// CHECK: out-file: {{.*}}s1.o
+// CHECK: DEPEND START
+// CHECK: Unit | system | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
+
+// CHECK: s2.o-{{[A-Z0-9]*}}
+// CHECK: --------
+// CHECK: out-file: {{.*}}s2.o
+// CHECK: DEPEND START
+// CHECK: Unit | system | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
diff --git a/test/Index/Store/unit-one-file-multi-file-invocation.swift b/test/Index/Store/unit-one-file-multi-file-invocation.swift
new file mode 100644
index 0000000..65d08c0
--- /dev/null
+++ b/test/Index/Store/unit-one-file-multi-file-invocation.swift
@@ -0,0 +1,23 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: %swiftc_driver -index-file -index-file-path %s %s %S/Inputs/SwiftModuleA.swift -module-name unit_one_test -o %t.output_for_index -index-store-path %t/idx
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=UNIT
+
+// UNIT-NOT: SwiftShims
+
+// UNIT: [[SWIFT:Swift.swiftmodule-[A-Z0-9]*]]
+// UNIT: DEPEND START
+// UNIT: Record | system | Swift.Math.Floating | {{.*}}Swift.swiftmodule | Swift.swiftmodule_Math_Floating-{{.*}}
+// UNIT: Record | system | Swift.String | {{.*}}Swift.swiftmodule | Swift.swiftmodule_String-{{.*}}
+// UNIT: DEPEND END
+
+// UNIT: unit-one-file-multi-file-invocation{{.*}}.output_for_index
+// UNIT: DEPEND START
+// UNIT: Unit | system |{{.*}}/Swift.swiftmodule | [[SWIFT]]
+// UNIT: Record | user |{{.*}}/unit-one-file-multi-file-invocation.swift |
+// UNIT: DEPEND END (2)
+
+func test1() {
+  funcSwiftA()
+}
diff --git a/test/Index/Store/unit-one-sourcefile.swift b/test/Index/Store/unit-one-sourcefile.swift
new file mode 100644
index 0000000..d0acc59
--- /dev/null
+++ b/test/Index/Store/unit-one-sourcefile.swift
@@ -0,0 +1,29 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx %s -o %t/file1.o -typecheck
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE1
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: touch %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -primary-file %s %t/s2.swift -o %t/file1.o -typecheck
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE1
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: touch %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx %s -primary-file %t/s2.swift -o %t/file2.o -typecheck
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE2
+
+// FILE1: file1.o-{{[A-Z0-9]*}}
+// FILE1: --------
+// FILE1: out-file: {{.*}}file1.o
+// FILE1: DEPEND START
+// FILE1: Unit | system | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// FILE1: DEPEND END
+
+// FILE2: file2.o-{{[A-Z0-9]*}}
+// FILE2: --------
+// FILE2: out-file: {{.*}}file2.o
+// FILE2: DEPEND START
+// FILE2: Unit | system | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// FILE2: DEPEND END
diff --git a/test/Index/Store/unit-pcm-dependency.swift b/test/Index/Store/unit-pcm-dependency.swift
new file mode 100644
index 0000000..c9721ba
--- /dev/null
+++ b/test/Index/Store/unit-pcm-dependency.swift
@@ -0,0 +1,79 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -primary-file %s -o %t/s1.o -I %S/Inputs -typecheck -module-cache-path %t/mcp
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE1
+
+// If the module cache already exists, the pcm gets indexed.
+// RUN: rm -rf %t/idx
+// RUN: %target-swift-frontend -index-store-path %t/idx -primary-file %s -o %t/s1.o -I %S/Inputs -typecheck -module-cache-path %t/mcp
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE1
+
+// FIXME: index the bridging header!
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: echo 'import ClangModuleA' > %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx %s %t/s2.swift -o %t/s1.o -o %t/s2.o -I %S/Inputs -c -emit-module -module-name main -emit-module-path %t/main.swiftmodule -module-cache-path %t/mcp
+// RUN: c-index-test core -print-unit %t/idx > %t/both.txt
+// RUN: %FileCheck %s -check-prefix=FILE1 < %t/both.txt
+// RUN: %FileCheck %s -check-prefix=FILE2 < %t/both.txt
+
+
+// XFAIL: linux
+
+import ClangModuleB
+import ClangModuleC.Sub1
+import ClangModuleC.Sub2
+
+func test() {
+  funcA()
+  funcB()
+}
+
+// FILE1: ClangModuleA-
+// FILE1: --------
+// FILE1: is-system: 0
+// FILE1: has-main: 0
+// FILE1: DEPEND START
+// FILE1: Record | user | {{.*}}ClangModuleA.h | ClangModuleA.h-
+// FILE1: DEPEND END
+
+// FILE1: ClangModuleB-
+// FILE1: --------
+// FILE1: is-system: 0
+// FILE1: has-main: 0
+// FILE1: DEPEND START
+// FILE1: Unit | user | ClangModuleA | {{.*}}ClangModuleA-{{.*}}.pcm | ClangModuleA-{{.*}}.pcm-
+// FILE1: Record | user | {{.*}}ClangModuleB.h | ClangModuleB.h-
+// FILE1: DEPEND END
+
+// FILE1: s1.o-
+// FILE1: --------
+// FILE1: has-main: 1
+// FILE1: DEPEND START
+// FILE1-NOT: ClangModuleA.h
+// FILE1-NOT: Unit |{{.*}}ClangModuleA
+// FILE1: Unit | system | Swift | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// FILE1-NOT: Unit |{{.*}}ClangModuleA
+// FILE1: Unit | user | ClangModuleB | {{.*}}ClangModuleB-{{[A-Z0-9]*}}.pcm | ClangModuleB-{{[A-Z0-9]*}}.pcm-
+// FILE1: Unit | user | ClangModuleC | {{.*}}ClangModuleC-{{[A-Z0-9]*}}.pcm | ClangModuleC-{{[A-Z0-9]*}}.pcm-
+// FILE1-NOT: Unit |{{.*}}ClangModuleA
+// FILE1: Record | user | {{.*}}unit-pcm-dependency.swift | unit-pcm-dependency.swift-
+// FILE1-NOT: Unit |{{.*}}ClangModuleA
+// FILE1: DEPEND END (4)
+
+// FILE2-NOT: main.swiftmodule-
+
+// FILE2: s2.o-
+// FILE2: --------
+// FILE2: has-main: 1
+// FILE2: out-file: {{.*}}s2.o
+// FILE2: DEPEND START
+// FILE2-NOT: ClangModuleB.h
+// FILE2-NOT: Unit |{{.*}}ClangModuleB
+// FILE2-NOT: Record
+// FILE2: Unit | system | Swift | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// FILE2-NOT: Unit |{{.*}}ClangModuleB
+// FILE2-NOT: Record
+// FILE2: Unit | user | ClangModuleA | {{.*}}ClangModuleA-{{[A-Z0-9]*}}.pcm | ClangModuleA-{{[A-Z0-9]*}}.pcm-
+// FILE2-NOT: Unit |{{.*}}ClangModuleB
+// FILE2-NOT: Record
+// FILE2: DEPEND END
diff --git a/test/Index/Store/unit-swiftmodule-dependency.swift b/test/Index/Store/unit-swiftmodule-dependency.swift
new file mode 100644
index 0000000..df54f92
--- /dev/null
+++ b/test/Index/Store/unit-swiftmodule-dependency.swift
@@ -0,0 +1,57 @@
+// RUN: rm -rf %t && mkdir %t
+
+// RUN: %target-swift-frontend -index-store-path %t/idx %S/Inputs/SwiftModuleA.swift -emit-module -o %t/SwiftModuleA.swiftmodule
+// RUN: %target-swift-frontend -index-store-path %t/idx %S/Inputs/SwiftModuleB.swift -emit-module -o %t/SwiftModuleB.swiftmodule -I %t
+
+// RUN: echo 'import SwiftModuleA' > %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx %s %t/s2.swift -c -o %t/s1.o -o %t/s2.o -I %t -emit-module -module-name main -emit-module-path %t/main.swiftmodule
+
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+
+// XFAIL: linux
+
+import SwiftModuleA
+import SwiftModuleB
+
+func test() {
+  funcSwiftA()
+  funcSwiftB()
+}
+
+// CHECK: [[MODA:SwiftModuleA.swiftmodule-[A-Z0-9]*]]
+// CHECK: --------
+// CHECK: has-main: 1
+// CHECK: out-file: {{.*}}/SwiftModuleA.swiftmodule
+// CHECK: DEPEND START
+// CHECK: Unit | system | Swift | {{.*}}/Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
+
+// CHECK: [[MODB:SwiftModuleB.swiftmodule-[A-Z0-9]*]]
+// CHECK: --------
+// CHECK: has-main: 1
+// CHECK: out-file: {{.*}}/SwiftModuleB.swiftmodule
+// CHECK: DEPEND START
+// CHECK: Unit | system | Swift | {{.*}}/Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: Unit | user | SwiftModuleA | {{.*}}/SwiftModuleA.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
+
+// CHECK-NOT: main.swiftmodule-
+
+// CHECK: s1.o-
+// CHECK: --------
+// CHECK: has-main: 1
+// CHECK: out-file: {{.*}}/s1.o
+// CHECK: DEPEND START
+// CHECK: Unit | system | Swift | {{.*}}/Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: Unit | user | SwiftModuleA | {{.*}}/SwiftModuleA.swiftmodule | | {{[0-9]*$}}
+// CHECK: Unit | user | SwiftModuleB | {{.*}}/SwiftModuleB.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
+
+// CHECK: s2.o-
+// CHECK: --------
+// CHECK: has-main: 1
+// CHECK: out-file: {{.*}}/s2.o
+// CHECK: DEPEND START
+// CHECK: Unit | system | Swift | {{.*}}/Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: Unit | user | SwiftModuleA | {{.*}}/SwiftModuleA.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
diff --git a/test/Index/Store/unit-with-bridging-header.swift b/test/Index/Store/unit-with-bridging-header.swift
new file mode 100644
index 0000000..f335802
--- /dev/null
+++ b/test/Index/Store/unit-with-bridging-header.swift
@@ -0,0 +1,49 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-pch -index-store-path %t/idx -o %t/bridge-head.pch %S/Inputs/bridge-head.h
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -import-objc-header %t/bridge-head.pch -primary-file %s -o %t/s1.o -index-store-path %t/idx
+// RUN: c-index-test core -print-record %t/idx | %FileCheck %s --check-prefix=PCH-RECORD
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s --check-prefix=PCH-UNIT
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -import-objc-header %S/Inputs/bridge-head.h -primary-file %s -o %t/s1.o -index-store-path %t/idx2
+// RUN: c-index-test core -print-unit %t/idx2 | %FileCheck --check-prefix=TEXTUAL-UNIT %s
+
+// PCH-RECORD: bridge-include.h
+// PCH-RECORD: ------------
+// PCH-RECORD: function/C | includedFunc | {{.*}} | <no-cgname> | Decl - 
+// PCH-RECORD: variable/C | MY_CONST | {{.*}} | <no-cgname> | Def - 
+// PCH-RECORD: ------------
+// PCH-RECORD: 1:5 | function/C | {{.*}} | Decl | rel: 0
+// PCH-RECORD: 2:5 | variable/C | {{.*}} | Def | rel: 0
+
+// PCH-UNIT: bridge-head.pch-
+// PCH-UNIT: --------
+// PCH-UNIT: has-main: 0
+// PCH-UNIT: DEPEND START
+// PCH-UNIT: Record | user | {{.*}}bridge-include.h | bridge-include.h-
+// PCH-UNIT: File | user | {{.*}}bridge-head.h |
+// PCH-UNIT: File | user | {{.*}}module.modulemap |
+// PCH-UNIT: DEPEND END (3)
+// PCH-UNIT: INCLUDE START
+// PCH-UNIT: {{.*}}bridge-head.h:1 | {{.*}}bridge-include.h
+// PCH-UNIT: INCLUDE END (1)
+
+// PCH-UNIT: s1.o-
+// PCH-UNIT: --------
+// PCH-UNIT: has-main: 1
+// PCH-UNIT: DEPEND START
+// PCH-UNIT: Unit | system | {{.*}}Swift.swiftmodule |
+// PCH-UNIT: Unit | user | {{.*}}bridge-head.pch | bridge-head.pch-
+// PCH-UNIT: Record | user | {{.*}}unit-with-bridging-header.swift | unit-with-bridging-header.swift-
+// PCH-UNIT: DEPEND END (3)
+
+// TEXTUAL-UNIT: s1.o-
+// TEXTUAL-UNIT: --------
+// TEXTUAL-UNIT: has-main: 1
+// TEXTUAL-UNIT: DEPEND START
+// TEXTUAL-UNIT: Unit | system | {{.*}}Swift.swiftmodule |
+// TEXTUAL-UNIT: Record | user | {{.*}}unit-with-bridging-header.swift | unit-with-bridging-header.swift-
+// TEXTUAL-UNIT: DEPEND END (2)
+
+func test() {}