Prevent nonrecoverable module-out-of-date errors in projects that mix
PCH and clang modules.

This patch introduces a NeededByPCHOrCompilationUsesPCH language
option which causes clang modules imported by PCH which goes into the
module hash, thus isolating them from rebuilds triggered by other
clang modules.  This patch further disables module validation for
modules imported by PCH, since there is no mechanism in clang to
rebuild ou-tof-date modules when they were imported by a PCH.

rdar://problem/30384801
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index 215e462..954deaa 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -254,6 +254,7 @@
 LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST")
 LANGOPT(APINotes, 1, 0, "use external API notes")
 LANGOPT(APINotesModules, 1, 0, "use external API notes")
+LANGOPT(NeededByPCHOrCompilationUsesPCH, 1, 0, "compilation involves pch")
 
 LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan "
                                            "field padding (0: none, 1:least "
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index c9290a5..9805c15 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -1751,7 +1751,7 @@
     if (!AST)
       return nullptr;
   }
-  
+
   if (!ResourceFilesPath.empty()) {
     // Override the resources path.
     CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
@@ -1984,6 +1984,9 @@
   if (ModuleFormat)
     CI->getHeaderSearchOpts().ModuleFormat = ModuleFormat.getValue();
 
+  if (ForSerialization)
+    CI->getLangOpts()->NeededByPCHOrCompilationUsesPCH = true;
+
   // Create the AST unit.
   std::unique_ptr<ASTUnit> AST;
   AST.reset(new ASTUnit(false));
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index b79e118..b391950 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -2460,6 +2460,10 @@
   ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args,
                               Res.getFrontendOpts().ProgramAction);
 
+  if (!Res.getPreprocessorOpts().ImplicitPCHInclude.empty() ||
+      Res.getFrontendOpts().ProgramAction == frontend::GeneratePCH)
+    LangOpts.NeededByPCHOrCompilationUsesPCH = true;
+
   // Turn on -Wspir-compat for SPIR target.
   llvm::Triple T(Res.getTargetOpts().Triple);
   auto Arch = T.getArch();
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index 9eb08a5..da1ab7b 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -297,6 +297,7 @@
                 CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(),
                 SpecificModuleCachePath)) {
           PPOpts.ImplicitPCHInclude = Dir->getName();
+          CI.getLangOpts().NeededByPCHOrCompilationUsesPCH = true;
           Found = true;
           break;
         }
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 9d50f7a..0461a53 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -4045,7 +4045,7 @@
   }
 
   // FIXME: Should we check the signature even if DisableValidation?
-  if (DisableValidation ||
+  if (PP.getLangOpts().NeededByPCHOrCompilationUsesPCH || DisableValidation ||
       (AllowConfigurationMismatch && Result == ConfigurationMismatch))
     return Success;
 
diff --git a/test/Modules/explicit-build.cpp b/test/Modules/explicit-build.cpp
index a6f6a62..087cba5 100644
--- a/test/Modules/explicit-build.cpp
+++ b/test/Modules/explicit-build.cpp
@@ -150,7 +150,7 @@
 // RUN:            -fmodule-file=%t/a.pch \
 // RUN:            %s 2>&1 | FileCheck --check-prefix=CHECK-A-AS-PCH %s
 //
-// CHECK-A-AS-PCH: fatal error: AST file '{{.*}}a.pch' was not built as a module
+// CHECK-A-AS-PCH: error: module file {{.*}}a.pch cannot be loaded due to a configuration mismatch with the current compilation
 
 // -------------------------------
 // Try to import a non-AST file with -fmodule-file=