diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 6b7e198d0bf3897c1fa5f626da50d2e5399e95d6..731bb0406b36fa878ca358bd6839183a6d1acc4c 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -927,6 +927,8 @@ def include_pch : Separate<["-"], "include-pch">, Group<clang_i_Group>, Flags<[C
   HelpText<"Include precompiled header file">, MetaVarName<"<file>">;
 def relocatable_pch : Flag<["-", "--"], "relocatable-pch">, Flags<[CC1Option]>,
   HelpText<"Whether to build a relocatable precompiled header">;
+def verify_pch : Flag<["-"], "verify-pch">, Group<Action_Group>, Flags<[CC1Option]>,
+  HelpText<"Load and verify that a pre-compiled header file is not stale">;
 def init : Separate<["-"], "init">;
 def install__name : Separate<["-"], "install_name">;
 def integrated_as : Flag<["-"], "integrated-as">, Flags<[DriverOption]>;
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index fa20ae48e4f099fb282adcb7a700762428251642..64de7a5b197170564f3fe7bd3a93188a1f4b0fec 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -545,6 +545,7 @@ public:
   void createPCHExternalASTSource(StringRef Path,
                                   bool DisablePCHValidation,
                                   bool AllowPCHWithCompilerErrors,
+                                  bool AllowConfigurationMismatch,
                                   void *DeserializationListener);
 
   /// Create an external AST source to read a PCH file.
@@ -554,6 +555,7 @@ public:
   createPCHExternalASTSource(StringRef Path, const std::string &Sysroot,
                              bool DisablePCHValidation,
                              bool AllowPCHWithCompilerErrors,
+                             bool AllowConfigurationMismatch,
                              Preprocessor &PP, ASTContext &Context,
                              void *DeserializationListener, bool Preamble,
                              bool UseGlobalModuleIndex);
diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
index f3d12769f1438baaeb1c990a14939534f47441cf..f5557888ad6a77f1fd8e759442ac4e28869de06b 100644
--- a/include/clang/Frontend/FrontendActions.h
+++ b/include/clang/Frontend/FrontendActions.h
@@ -146,6 +146,17 @@ public:
   virtual bool hasCodeCompletionSupport() const { return false; }
 };
 
+class VerifyPCHAction : public ASTFrontendAction {
+protected:
+  virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+                                         StringRef InFile);
+
+  virtual void ExecuteAction();
+
+public:
+  virtual bool hasCodeCompletionSupport() const { return false; }
+};
+
 /**
  * \brief Frontend action adaptor that merges ASTs together.
  *
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index 818427a4ef6592b707bcf37eca8d0a2a75bacb2a..fc13b193936b1173fc2312dc9cefa1736e44b455 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -43,6 +43,7 @@ namespace frontend {
     GeneratePTH,            ///< Generate pre-tokenized header.
     InitOnly,               ///< Only execute frontend initialization.
     ModuleFileInfo,         ///< Dump information about a module file.
+    VerifyPCH,              ///< Load and verify that a PCH file is usable.
     ParseSyntaxOnly,        ///< Parse and perform semantic analysis.
     PluginAction,           ///< Run a plugin action, \see ActionName.
     PrintDeclContext,       ///< Print DeclContext and their Decls.
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 3cfd17ca027ae9bf7378e2c363941cc1e0f82fa3..00ab7f04926359f007a98d5739b68231fa85e733 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -733,6 +733,10 @@ private:
   /// \brief Whether to accept an AST file with compiler errors.
   bool AllowASTWithCompilerErrors;
 
+  /// \brief Whether to accept an AST file that has a different configuration
+  /// from the current compiler instance.
+  bool AllowConfigurationMismatch;
+
   /// \brief Whether we are allowed to use the global module index.
   bool UseGlobalIndex;
 
@@ -1174,11 +1178,15 @@ public:
   /// AST file the was created out of an AST with compiler errors,
   /// otherwise it will reject it.
   ///
+  /// \param AllowConfigurationMismatch If true, the AST reader will not check
+  /// for configuration differences between the AST file and the invocation.
+  ///
   /// \param UseGlobalIndex If true, the AST reader will try to load and use
   /// the global module index.
   ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot = "",
             bool DisableValidation = false,
             bool AllowASTWithCompilerErrors = false,
+            bool AllowConfigurationMismatch = false,
             bool UseGlobalIndex = true);
 
   ~ASTReader();
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index bd43fbeec19e485ac497b55f162948cab4530007..270c3a701b03f8e0197cde4577e62fdecdbe473d 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -169,6 +169,7 @@ const {
     // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
              (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
+             (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) ||
              (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
              (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||
              (PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
@@ -1316,6 +1317,8 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
       return new CompileJobAction(Input, types::TY_AST);
     } else if (Args.hasArg(options::OPT_module_file_info)) {
       return new CompileJobAction(Input, types::TY_ModuleFile);
+    } else if (Args.hasArg(options::OPT_verify_pch)) {
+      return new CompileJobAction(Input, types::TY_Nothing);
     } else if (IsUsingLTO(Args)) {
       types::ID Output =
         Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 3a8a28775790a3ac10f08c3f8ee62ffe3d1243a8..af8696c42a7bbf6182cf128806ded91d0ba73e59 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -1995,6 +1995,21 @@ static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) {
   return false;
 }
 
+/// Add -x lang to \p CmdArgs for \p Input.
+static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
+                             ArgStringList &CmdArgs) {
+  // When using -verify-pch, we don't want to provide the type
+  // 'precompiled-header' if it was inferred from the file extension
+  if (Args.hasArg(options::OPT_verify_pch) && Input.getType() == types::TY_PCH)
+    return;
+
+  CmdArgs.push_back("-x");
+  if (Args.hasArg(options::OPT_rewrite_objc))
+    CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX));
+  else
+    CmdArgs.push_back(types::getTypeName(Input.getType()));
+}
+
 void Clang::ConstructJob(Compilation &C, const JobAction &JA,
                          const InputInfo &Output,
                          const InputInfoList &Inputs,
@@ -2055,7 +2070,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool.");
 
     if (JA.getType() == types::TY_Nothing) {
-      CmdArgs.push_back("-fsyntax-only");
+      if (Args.hasArg(options::OPT_verify_pch))
+        CmdArgs.push_back("-verify-pch");
+      else
+        CmdArgs.push_back("-fsyntax-only");
     } else if (JA.getType() == types::TY_LLVM_IR ||
                JA.getType() == types::TY_LTO_IR) {
       CmdArgs.push_back("-emit-llvm");
@@ -3742,11 +3760,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   for (InputInfoList::const_iterator
          it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
     const InputInfo &II = *it;
-    CmdArgs.push_back("-x");
-    if (Args.hasArg(options::OPT_rewrite_objc))
-      CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX));
-    else
-      CmdArgs.push_back(types::getTypeName(II.getType()));
+
+    addDashXForInput(Args, II, CmdArgs);
+
     if (II.isFilename())
       CmdArgs.push_back(II.getFilename());
     else
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index d947ae7c03d615c44584708544ba1ec055e8dc85..3538dbc2c0e998f2b4add5c7c3620a8fc4d3a15e 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -174,6 +174,8 @@ types::ID types::lookupTypeForExtension(const char *Ext) {
            .Case("F95", TY_Fortran)
            .Case("mii", TY_PP_ObjCXX)
            .Case("pcm", TY_ModuleFile)
+           .Case("pch", TY_PCH)
+           .Case("gch", TY_PCH)
            .Default(TY_INVALID);
 }
 
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 0d2af334d79acdade20f85aae2e9b3b675a88f13..d8381a824c7d11ace3352299db8bb3eaf6824912 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -292,12 +292,14 @@ void CompilerInstance::createASTContext() {
 void CompilerInstance::createPCHExternalASTSource(StringRef Path,
                                                   bool DisablePCHValidation,
                                                 bool AllowPCHWithCompilerErrors,
+                                                bool AllowConfigurationMismatch,
                                                  void *DeserializationListener){
   OwningPtr<ExternalASTSource> Source;
   bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
   Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
                                           DisablePCHValidation,
                                           AllowPCHWithCompilerErrors,
+                                          AllowConfigurationMismatch,
                                           getPreprocessor(), getASTContext(),
                                           DeserializationListener,
                                           Preamble,
@@ -311,6 +313,7 @@ CompilerInstance::createPCHExternalASTSource(StringRef Path,
                                              const std::string &Sysroot,
                                              bool DisablePCHValidation,
                                              bool AllowPCHWithCompilerErrors,
+                                             bool AllowConfigurationMismatch,
                                              Preprocessor &PP,
                                              ASTContext &Context,
                                              void *DeserializationListener,
@@ -321,6 +324,7 @@ CompilerInstance::createPCHExternalASTSource(StringRef Path,
                              Sysroot.empty() ? "" : Sysroot.c_str(),
                              DisablePCHValidation,
                              AllowPCHWithCompilerErrors,
+                             AllowConfigurationMismatch,
                              UseGlobalModuleIndex));
 
   Reader->setDeserializationListener(
@@ -329,7 +333,9 @@ CompilerInstance::createPCHExternalASTSource(StringRef Path,
                           Preamble ? serialization::MK_Preamble
                                    : serialization::MK_PCH,
                           SourceLocation(),
-                          ASTReader::ARR_None)) {
+                          AllowConfigurationMismatch
+                            ? ASTReader::ARR_ConfigurationMismatch
+                            : ASTReader::ARR_None)) {
   case ASTReader::Success:
     // Set the predefines buffer as suggested by the PCH reader. Typically, the
     // predefines buffer will be empty.
@@ -1158,6 +1164,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
                                     Sysroot.empty() ? "" : Sysroot.c_str(),
                                     PPOpts.DisablePCHValidation,
                                     /*AllowASTWithCompilerErrors=*/false,
+                                    /*AllowConfigurationMismatch=*/false,
                                     getFrontendOpts().UseGlobalModuleIndex);
       if (hasASTConsumer()) {
         ModuleManager->setDeserializationListener(
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 92202b7ee201f20a4e187e6d7b1879dc356ea66c..da58a0386e62c21792fa5bf9e19c98f762b27b4e 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -700,6 +700,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
       Opts.ProgramAction = frontend::ParseSyntaxOnly; break;
     case OPT_module_file_info:
       Opts.ProgramAction = frontend::ModuleFileInfo; break;
+    case OPT_verify_pch:
+      Opts.ProgramAction = frontend::VerifyPCH; break;
     case OPT_print_decl_contexts:
       Opts.ProgramAction = frontend::PrintDeclContext; break;
     case OPT_print_preamble:
@@ -1585,6 +1587,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
   case frontend::GeneratePTH:
   case frontend::ParseSyntaxOnly:
   case frontend::ModuleFileInfo:
+  case frontend::VerifyPCH:
   case frontend::PluginAction:
   case frontend::PrintDeclContext:
   case frontend::RewriteObjC:
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index 0baf3e5e1fb325e7d7518b0a9a11a7fa55c92d9c..13a0787e4270c547cc792075c3764afaead411e0 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -314,6 +314,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
                                 CI.getPreprocessorOpts().ImplicitPCHInclude,
                                 CI.getPreprocessorOpts().DisablePCHValidation,
                             CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
+                            /*AllowConfigurationMismatch*/false,
                                 DeserialListener);
       if (!CI.getASTContext().getExternalSource())
         goto failure;
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 0d78bf032e3e896cff33c44e5a5fceb5c7609621..8b174605ffd88b1512f335e63260ea4013a85fc7 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -320,6 +320,19 @@ ASTConsumer *DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI,
   return new ASTConsumer();
 }
 
+ASTConsumer *VerifyPCHAction::CreateASTConsumer(CompilerInstance &CI,
+                                                StringRef InFile) {
+  return new ASTConsumer();
+}
+
+void VerifyPCHAction::ExecuteAction() {
+  getCompilerInstance().
+    createPCHExternalASTSource(getCurrentFile(), /*DisablePCHValidation*/false,
+                               /*AllowPCHWithCompilerErrors*/false,
+                               /*AllowConfigurationMismatch*/true,
+                               /*DeserializationListener*/0);
+}
+
 namespace {
   /// \brief AST reader listener that dumps module information for a module
   /// file.
diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index e14fb2340e63fed4aa7bee59a77271d87d2f1594..4c2ec441b3f5b50626ace4e9884f726c688f61f1 100644
--- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -65,6 +65,7 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
   case InitOnly:               return new InitOnlyAction();
   case ParseSyntaxOnly:        return new SyntaxOnlyAction();
   case ModuleFileInfo:         return new DumpModuleInfoAction();
+  case VerifyPCH:              return new VerifyPCHAction();
 
   case PluginAction: {
     for (FrontendPluginRegistry::iterator it =
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 3a93804eab74c2965bf79c89dffc18688c1c4dfe..4d2a400888809e3194fe9d338390b7e50cfae11b 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1935,7 +1935,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
       bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
       if (Listener && &F == *ModuleMgr.begin() &&
           ParseLanguageOptions(Record, Complain, *Listener) &&
-          !DisableValidation)
+          !DisableValidation && !AllowConfigurationMismatch)
         return ConfigurationMismatch;
       break;
     }
@@ -1944,7 +1944,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
       bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
       if (Listener && &F == *ModuleMgr.begin() &&
           ParseTargetOptions(Record, Complain, *Listener) &&
-          !DisableValidation)
+          !DisableValidation && !AllowConfigurationMismatch)
         return ConfigurationMismatch;
       break;
     }
@@ -1953,7 +1953,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
       bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
       if (Listener && &F == *ModuleMgr.begin() &&
           ParseDiagnosticOptions(Record, Complain, *Listener) &&
-          !DisableValidation)
+          !DisableValidation && !AllowConfigurationMismatch)
         return ConfigurationMismatch;
       break;
     }
@@ -1962,7 +1962,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
       bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
       if (Listener && &F == *ModuleMgr.begin() &&
           ParseFileSystemOptions(Record, Complain, *Listener) &&
-          !DisableValidation)
+          !DisableValidation && !AllowConfigurationMismatch)
         return ConfigurationMismatch;
       break;
     }
@@ -1971,7 +1971,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
       bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
       if (Listener && &F == *ModuleMgr.begin() &&
           ParseHeaderSearchOptions(Record, Complain, *Listener) &&
-          !DisableValidation)
+          !DisableValidation && !AllowConfigurationMismatch)
         return ConfigurationMismatch;
       break;
     }
@@ -1981,7 +1981,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
       if (Listener && &F == *ModuleMgr.begin() &&
           ParsePreprocessorOptions(Record, Complain, *Listener,
                                    SuggestedPredefines) &&
-          !DisableValidation)
+          !DisableValidation && !AllowConfigurationMismatch)
         return ConfigurationMismatch;
       break;
     }
@@ -7618,13 +7618,16 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
 
 ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
                      StringRef isysroot, bool DisableValidation,
-                     bool AllowASTWithCompilerErrors, bool UseGlobalIndex)
+                     bool AllowASTWithCompilerErrors,
+                     bool AllowConfigurationMismatch,
+                     bool UseGlobalIndex)
   : Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
     SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
     Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context),
     Consumer(0), ModuleMgr(PP.getFileManager()),
     isysroot(isysroot), DisableValidation(DisableValidation),
     AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
+    AllowConfigurationMismatch(AllowConfigurationMismatch),
     UseGlobalIndex(UseGlobalIndex), TriedLoadingGlobalIndex(false),
     CurrentGeneration(0), CurrSwitchCaseStmts(&SwitchCaseStmts),
     NumSLocEntriesRead(0), TotalNumSLocEntries(0), 
diff --git a/test/Driver/verify_pch.m b/test/Driver/verify_pch.m
new file mode 100644
index 0000000000000000000000000000000000000000..c6eca4268bd7945b7824c1aec8da7e59c1bbfd6e
--- /dev/null
+++ b/test/Driver/verify_pch.m
@@ -0,0 +1,12 @@
+// RUN: touch %t.pch
+// RUN: %clang -### -verify-pch %t.pch 2> %t.log.1
+// RUN: FileCheck %s < %t.log.1
+// CHECK: -verify-pch
+
+// Also ensure that the language setting is not affected by the .pch extension
+// CHECK-NOT: "-x" "precompiled-header"
+
+// RUN: %clang -### -verify-pch -x objective-c %t.pch 2> %t.log.2
+// RUN: FileCheck -check-prefix=CHECK2 %s < %t.log.2
+// CHECK2: "-x" "objective-c"
+// CHECK2-NOT: "-x" "precompiled-header"
diff --git a/test/PCH/verify_pch.m b/test/PCH/verify_pch.m
new file mode 100644
index 0000000000000000000000000000000000000000..9870231d7c8c895c8af74ac544b19fec8924618a
--- /dev/null
+++ b/test/PCH/verify_pch.m
@@ -0,0 +1,15 @@
+// Precompile
+// RUN: cp %s %t.h
+// RUN: %clang_cc1 -x objective-c-header -emit-pch -o %t.pch %t.h
+
+// Verify successfully
+// RUN: %clang_cc1 -x objective-c -verify-pch %t.pch
+
+// Incompatible lang options ignored
+// RUN: %clang_cc1 -x objective-c -fno-builtin -verify-pch %t.pch
+
+// Stale dependency
+// RUN: echo ' ' >> %t.h
+// RUN: not %clang_cc1 -x objective-c -verify-pch %t.pch 2> %t.log.2
+// RUN: FileCheck -check-prefix=CHECK-STALE-DEP %s < %t.log.2
+// CHECK-STALE-DEP: file '{{.*}}.h' has been modified since the precompiled header '{{.*}}.pch' was built