diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index a773e416670ad96bd544c94170db4593ec81c215..0aa649a84d17f5188ab56cd550eaf0e15edcd519 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -1106,6 +1106,8 @@ private:
 
   void finishPendingActions();
 
+  void pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name);
+
   void addPendingDeclContextInfo(Decl *D,
                                  serialization::GlobalDeclID SemaDC,
                                  serialization::GlobalDeclID LexicalDC) {
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index c06153a61a97474110ec16bc8f9b64eeb1537a2a..20d0404e4e8bd3d6a5f4412a568592bb99424061 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -6005,8 +6005,8 @@ void ASTReader::InitializeSema(Sema &S) {
   // Makes sure any declarations that were deserialized "too early"
   // still get added to the identifier's declaration chains.
   for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
-    NamedDecl *ND = cast<NamedDecl>(PreloadedDecls[I]->getMostRecentDecl());
-    SemaObj->pushExternalDeclIntoScope(ND, PreloadedDecls[I]->getDeclName());
+    pushExternalDeclIntoScope(PreloadedDecls[I],
+                              PreloadedDecls[I]->getDeclName());
   }
   PreloadedDecls.clear();
 
@@ -6420,8 +6420,7 @@ ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II,
       // Introduce this declaration into the translation-unit scope
       // and add it to the declaration chain for this identifier, so
       // that (unqualified) name lookup will find it.
-      NamedDecl *ND = cast<NamedDecl>(D->getMostRecentDecl());
-      SemaObj->pushExternalDeclIntoScope(ND, II);
+      pushExternalDeclIntoScope(D, II);
     } else {
       // Queue this declaration so that it will be added to the
       // translation unit scope and identifier's declaration chain
@@ -7208,8 +7207,7 @@ void ASTReader::finishPendingActions() {
          TLD != TLDEnd; ++TLD) {
       IdentifierInfo *II = TLD->first;
       for (unsigned I = 0, N = TLD->second.size(); I != N; ++I) {
-        NamedDecl *ND = cast<NamedDecl>(TLD->second[I]->getMostRecentDecl());
-        SemaObj->pushExternalDeclIntoScope(ND, II);
+        pushExternalDeclIntoScope(cast<NamedDecl>(TLD->second[I]), II);
       }
     }
 
@@ -7349,6 +7347,21 @@ void ASTReader::FinishedDeserializing() {
   }
 }
 
+void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
+  D = cast<NamedDecl>(D->getMostRecentDecl());
+
+  if (SemaObj->IdResolver.tryAddTopLevelDecl(D, Name) && SemaObj->TUScope) {
+    SemaObj->TUScope->AddDecl(D);
+  } else if (SemaObj->TUScope) {
+    // Adding the decl to IdResolver may have failed because it was already in
+    // (even though it was not added in scope). If it is already in, make sure
+    // it gets in the scope as well.
+    if (std::find(SemaObj->IdResolver.begin(Name),
+                  SemaObj->IdResolver.end(), D) != SemaObj->IdResolver.end())
+      SemaObj->TUScope->AddDecl(D);
+  }
+}
+
 ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
                      StringRef isysroot, bool DisableValidation,
                      bool AllowASTWithCompilerErrors, bool UseGlobalIndex)
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index c5a055072d904f1fc56b6e5107d6d9c60e4fedb7..ba53bdaffb189a4c5ad08162b175451c09829f4a 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -3106,7 +3106,28 @@ public:
     for (SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(),
                                                 DEnd = Decls.rend();
          D != DEnd; ++D)
-      clang::io::Emit32(Out, Writer.getDeclID(*D));
+      clang::io::Emit32(Out, Writer.getDeclID(getMostRecentLocalDecl(*D)));
+  }
+
+  /// \brief Returns the most recent local decl or the given decl if there are
+  /// no local ones. The given decl is assumed to be the most recent one.
+  Decl *getMostRecentLocalDecl(Decl *Orig) {
+    // The only way a "from AST file" decl would be more recent from a local one
+    // is if it came from a module.
+    if (!PP.getLangOpts().Modules)
+      return Orig;
+
+    // Look for a local in the decl chain.
+    for (Decl *D = Orig; D; D = D->getPreviousDecl()) {
+      if (!D->isFromASTFile())
+        return D;
+      // If we come up a decl from a (chained-)PCH stop since we won't find a
+      // local one.
+      if (D->getOwningModuleID() == 0)
+        break;
+    }
+
+    return Orig;
   }
 };
 } // end anonymous namespace
diff --git a/test/Modules/redecls/a.h b/test/Modules/redecls/a.h
new file mode 100644
index 0000000000000000000000000000000000000000..1647f86606a80edbd10451b5dae88fc270716bb8
--- /dev/null
+++ b/test/Modules/redecls/a.h
@@ -0,0 +1,3 @@
+@interface AA
+@end
+@class AA;
diff --git a/test/Modules/redecls/b.h b/test/Modules/redecls/b.h
new file mode 100644
index 0000000000000000000000000000000000000000..d41573ddc78a41e58e69096b84fc2861733e4cfc
--- /dev/null
+++ b/test/Modules/redecls/b.h
@@ -0,0 +1 @@
+@class AA;
diff --git a/test/Modules/redecls/main.m b/test/Modules/redecls/main.m
new file mode 100644
index 0000000000000000000000000000000000000000..9ec02b03f2cce9579412fd73cf759bedaa80717a
--- /dev/null
+++ b/test/Modules/redecls/main.m
@@ -0,0 +1,27 @@
+// RUN: rm -rf %t.mcp
+// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodule-name=a %S/module.map -fmodules-cache-path=%t.mcp
+// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodule-name=b %S/module.map -fmodules-cache-path=%t.mcp
+// RUN: %clang_cc1 -fmodules %s -emit-pch -o %t1.pch -fmodules-cache-path=%t.mcp
+// RUN: %clang_cc1 -fmodules %s -emit-pch -o %t2.pch -include-pch %t1.pch -fmodules-cache-path=%t.mcp
+// RUN: %clang_cc1 -fmodules %s -fsyntax-only -include-pch %t2.pch -fmodules-cache-path=%t.mcp -verify
+
+#ifndef HEADER1
+#define HEADER1
+
+@import a;
+
+#elif !defined(HEADER2)
+#define HEADER2
+
+@class AA;
+@import b;
+
+#else
+
+// rdar://13712705
+@interface SS : AA
+@end
+
+#warning parsed this
+#endif
+// expected-warning@-2{{parsed this}}
diff --git a/test/Modules/redecls/module.map b/test/Modules/redecls/module.map
new file mode 100644
index 0000000000000000000000000000000000000000..a36568207b68cfdd556732d89aa1ed0e8eabd26b
--- /dev/null
+++ b/test/Modules/redecls/module.map
@@ -0,0 +1,2 @@
+module a { header "a.h" }
+module b { header "b.h" }