diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 41ef74ee0ab4f408fd05894d27a06b1943c96b04..cce6916b4e37c685e55e7ea471fcc947d28434cd 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -452,7 +452,11 @@ namespace clang {
       
       /// \brief Record code for an array of all of the (sub)modules that were
       /// imported by the AST file.
-      IMPORTED_MODULES
+      IMPORTED_MODULES,
+      
+      /// \brief Record code for the array describing the first/last local
+      /// redeclarations of each entity.
+      LOCAL_REDECLARATIONS
     };
 
     /// \brief Record types used within a source manager block.
@@ -1190,6 +1194,33 @@ namespace clang {
       CTOR_INITIALIZER_INDIRECT_MEMBER
     };
 
+    /// \brief Describes the redeclarations of a declaration.
+    struct LocalRedeclarationsInfo {
+      DeclID FirstID;      // The ID of the first declaration
+      DeclID FirstLocalID; // The ID of the first local declaration
+      DeclID LastLocalID;  // The ID of the last local declaration
+      
+      friend bool operator<(const LocalRedeclarationsInfo &X,
+                            const LocalRedeclarationsInfo &Y) {
+        return X.FirstID < Y.FirstID;
+      }
+      
+      friend bool operator>(const LocalRedeclarationsInfo &X,
+                            const LocalRedeclarationsInfo &Y) {
+        return X.FirstID > Y.FirstID;
+      }
+      
+      friend bool operator<=(const LocalRedeclarationsInfo &X,
+                             const LocalRedeclarationsInfo &Y) {
+        return X.FirstID <= Y.FirstID;
+      }
+      
+      friend bool operator>=(const LocalRedeclarationsInfo &X,
+                             const LocalRedeclarationsInfo &Y) {
+        return X.FirstID >= Y.FirstID;
+      }
+    };
+
     /// @}
   }
 } // end namespace clang
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 0947dfc4eb758a4655bf6295ee70f16f17751496..10ed5dceea5fe82a7a5b2d926e1f3ca36e28fbbf 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -674,6 +674,17 @@ private:
   /// deeply nested calls when there are many redeclarations.
   std::deque<std::pair<Decl *, serialization::DeclID> > PendingPreviousDecls;
 
+  /// \brief The list of redeclaration chains that still need to be 
+  /// reconstructed.
+  ///
+  /// Each element is the global declaration ID of the first declaration in
+  /// the chain. Elements in this vector should be unique; use 
+  /// PendingDeclChainsKnown to ensure uniqueness.
+  llvm::SmallVector<serialization::DeclID, 16> PendingDeclChains;
+
+  /// \brief Keeps track of the elements added to PendingDeclChains.
+  llvm::SmallSet<serialization::DeclID, 16> PendingDeclChainsKnown;
+
   /// \brief We delay loading the chain of objc categories after recursive
   /// loading of declarations is finished.
   std::vector<std::pair<ObjCInterfaceDecl *, serialization::DeclID> >
@@ -759,6 +770,7 @@ private:
   RecordLocation DeclCursorForID(serialization::DeclID ID,
                                  unsigned &RawLocation);
   void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D);
+  void loadPendingDeclChain(serialization::GlobalDeclID ID);
   void loadObjCChainedCategories(serialization::GlobalDeclID ID,
                                  ObjCInterfaceDecl *D);
 
@@ -1028,6 +1040,15 @@ public:
     return cast_or_null<T>(GetLocalDecl(F, LocalID));
   }
 
+  /// \brief Map a global declaration ID into the declaration ID used to 
+  /// refer to this declaration within the given module fule.
+  ///
+  /// \returns the global ID of the given declaration as known in the given
+  /// module file.
+  serialization::DeclID 
+  mapGlobalIDToModuleFileGlobalID(ModuleFile &M,
+                                  serialization::DeclID GlobalID);
+  
   /// \brief Reads a declaration ID from the given position in a record in the
   /// given module.
   ///
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index ab0d1ef3d9fec0d7a4bd4fdc5df67b22989533a0..fd581bc4521ff6f382de696a6630998be0a99991 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -312,7 +312,11 @@ private:
   /// serialized again. In this case, it is registered here, so that the reader
   /// knows to read the updated version.
   SmallVector<ReplacedDeclInfo, 16> ReplacedDecls;
-
+                    
+  /// \brief The list of local redeclarations of entities that were
+  /// first declared non-locally.
+  SmallVector<serialization::LocalRedeclarationsInfo, 2> LocalRedeclarations;
+                  
   /// \brief Statements that we've encountered while serializing a
   /// declaration or type.
   SmallVector<Stmt *, 16> StmtsToEmit;
diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h
index 16d9779e04deb32b158809293c6d0d9bc9272e61..cbac5cd148fd83ba0fbbb686a0db2d3059f65891 100644
--- a/include/clang/Serialization/Module.h
+++ b/include/clang/Serialization/Module.h
@@ -260,6 +260,15 @@ public:
   /// \brief Remapping table for declaration IDs in this module.
   ContinuousRangeMap<uint32_t, int, 2> DeclRemap;
 
+  /// \brief Mapping from the module files that this module file depends on
+  /// to the base declaration ID for that module as it is understood within this
+  /// module.
+  ///
+  /// This is effectively a reverse global-to-local mapping for declaration
+  /// IDs, so that we can interpret a true global ID (for this translation unit)
+  /// as a local ID (for this module file).
+  llvm::DenseMap<ModuleFile *, serialization::DeclID> GlobalToLocalDeclIDs;
+
   /// \brief The number of C++ base specifier sets in this AST file.
   unsigned LocalNumCXXBaseSpecifiers;
 
@@ -286,6 +295,13 @@ public:
   /// \brief Array of file-level DeclIDs sorted by file.
   const serialization::DeclID *FileSortedDecls;
 
+  /// \brief Array of redeclaration information within this module file,
+  /// sorted by the first declaration ID.
+  const serialization::LocalRedeclarationsInfo *RedeclarationsInfo;
+
+  /// \brief The number of redeclaration info entries in RedeclarationsInfo.
+  unsigned LocalNumRedeclarationsInfos;
+  
   // === Types ===
 
   /// \brief The number of types in this AST file.
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index a1713ee6850179f53f21ae167332feb254248430..bc1cb3fca63bd9db1b4f6493aa52c11f288fe65d 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1063,6 +1063,8 @@ static NamedDecl *getPreviousDeclaration(NamedDecl *D) {
     return FD->getPreviousDeclaration();
   if (RedeclarableTemplateDecl *RTD = dyn_cast<RedeclarableTemplateDecl>(D))
     return RTD->getPreviousDeclaration();
+  if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+    return TD->getPreviousDeclaration();
   if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
     return ID->getPreviousDeclaration();
   
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 3af04c2bc8addc1825a624c106e6c80abf0650fe..64414c91675b53635227852a1adf9291a6870048 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1846,6 +1846,10 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
         F.DeclRemap.insert(std::make_pair(LocalBaseDeclID, 
                                           F.BaseDeclID - LocalBaseDeclID));
         
+        // Introduce the global -> local mapping for declarations within this
+        // module.
+        F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID;
+        
         DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);
       }
       break;
@@ -2125,6 +2129,9 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
         
         TypeRemap.insert(std::make_pair(TypeIndexOffset, 
                                     OM->BaseTypeIndex - TypeIndexOffset));
+
+        // Global -> local mappings.
+        F.GlobalToLocalDeclIDs[OM] = DeclIDOffset;
       }
       break;
     }
@@ -2396,7 +2403,17 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
         }
       }
       break;
+    }
+        
+    case LOCAL_REDECLARATIONS: {
+      if (F.LocalNumRedeclarationsInfos != 0) {
+        Error("duplicate LOCAL_REDECLARATIONS record in AST file");
+        return Failure;
+      }
       
+      F.LocalNumRedeclarationsInfos = Record[0];
+      F.RedeclarationsInfo = (const LocalRedeclarationsInfo *)BlobStart;
+      break;
     }
     }
   }
@@ -4568,6 +4585,23 @@ Decl *ASTReader::GetDecl(DeclID ID) {
   return DeclsLoaded[Index];
 }
 
+DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M, 
+                                                  DeclID GlobalID) {
+  if (GlobalID < NUM_PREDEF_DECL_IDS)
+    return GlobalID;
+  
+  GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID);
+  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
+  ModuleFile *Owner = I->second;
+
+  llvm::DenseMap<ModuleFile *, serialization::DeclID>::iterator Pos
+    = M.GlobalToLocalDeclIDs.find(Owner);
+  if (Pos == M.GlobalToLocalDeclIDs.end())
+    return 0;
+      
+  return GlobalID - Owner->BaseDeclID + Pos->second;
+}
+
 serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F, 
                                             const RecordData &Record,
                                             unsigned &Idx) {
@@ -6027,6 +6061,7 @@ void ASTReader::ClearSwitchCaseIDs() {
 void ASTReader::finishPendingActions() {
   while (!PendingIdentifierInfos.empty() ||
          !PendingPreviousDecls.empty() ||
+         !PendingDeclChains.empty() ||
          !PendingChainedObjCCategories.empty()) {
 
     // If any identifiers with corresponding top-level declarations have
@@ -6044,6 +6079,12 @@ void ASTReader::finishPendingActions() {
       PendingPreviousDecls.pop_front();
     }
   
+    // Load pending declaration chains.
+    for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
+      loadPendingDeclChain(PendingDeclChains[I]);
+    }
+    PendingDeclChains.clear();
+
     for (std::vector<std::pair<ObjCInterfaceDecl *,
                                serialization::DeclID> >::iterator
            I = PendingChainedObjCCategories.begin(),
@@ -6082,6 +6123,7 @@ void ASTReader::FinishedDeserializing() {
     }
 
     finishPendingActions();
+    PendingDeclChainsKnown.clear();
 
     assert(PendingForwardRefs.size() == 0 &&
            "Some forward refs did not get linked to the definition!");
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 5e5f1cb6fe6505e700b55fed5bfa6bca74083ccd..69f309aef0d0b99c4be2d626cad087ccb6c9cb53 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -114,6 +114,7 @@ namespace clang {
         TypeIDForTypeDecl(0) { }
 
     static void attachPreviousDecl(Decl *D, Decl *previous);
+    static void attachLatestDecl(Decl *D, Decl *latest);
 
     void Visit(Decl *D);
 
@@ -307,11 +308,13 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
 }
 
 void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
+  VisitRedeclarable(TD);
   VisitTypeDecl(TD);
   TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
 }
 
 void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) {
+  VisitRedeclarable(TD);
   VisitTypeDecl(TD);
   TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
 }
@@ -1398,73 +1401,39 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) {
 
 template <typename T>
 void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
-  enum RedeclKind { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
+  enum RedeclKind { FirstInFile, PointsToPrevious };
   RedeclKind Kind = (RedeclKind)Record[Idx++];
+  
+  // Read the first declaration ID, and note that we need to reconstruct
+  // the redeclaration chain once we hit the top level.
+  DeclID FirstDeclID = ReadDeclID(Record, Idx);
+  if (Reader.PendingDeclChainsKnown.insert(FirstDeclID))
+    Reader.PendingDeclChains.push_back(FirstDeclID);
+
+  T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
+
   switch (Kind) {
-  default:
-    llvm_unreachable("Out of sync with ASTDeclWriter::VisitRedeclarable or"
-                     " messed up reading");
-  case NoRedeclaration:
+  case FirstInFile:
+    if (FirstDecl != D)
+      D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(FirstDecl);
     break;
+      
   case PointsToPrevious: {
     DeclID PreviousDeclID = ReadDeclID(Record, Idx);
-    DeclID FirstDeclID = ReadDeclID(Record, Idx);
+    
     // We delay loading of the redeclaration chain to avoid deeply nested calls.
     // We temporarily set the first (canonical) declaration as the previous one
     // which is the one that matters and mark the real previous DeclID to be
     // loaded & attached later on.
-    T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
     D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(FirstDecl);
-    if (PreviousDeclID != FirstDeclID)
-      Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D),
-                                                           PreviousDeclID));
-
-    // If the first declaration in the chain is in an inconsistent
-    // state where it thinks that it is the only declaration, fix its
-    // redeclaration link now to point at this declaration, so that we have a 
-    // proper redeclaration chain.
-    if (FirstDecl->RedeclLink.getPointer() == FirstDecl) {
-      FirstDecl->RedeclLink
-        = typename Redeclarable<T>::LatestDeclLink(static_cast<T*>(D));
-    }
-    break;
-  }
-  case PointsToLatest: {
-    T *LatestDecl = ReadDeclAs<T>(Record, Idx);
-    D->RedeclLink = typename Redeclarable<T>::LatestDeclLink(LatestDecl);
     
-    // If the latest declaration in the chain is in an inconsistent
-    // state where it thinks that it is the only declaration, fix its
-    // redeclaration link now to point at this declaration, so that we have a 
-    // proper redeclaration chain.
-    if (LatestDecl->RedeclLink.getPointer() == LatestDecl) {
-      LatestDecl->RedeclLink
-        = typename Redeclarable<T>::PreviousDeclLink(static_cast<T*>(D));
-    }
+    // Make a note that we need to wire up this declaration to its
+    // previous declaration, later.
+    Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D),
+                                                         PreviousDeclID));
     break;
   }
   }
-
-  assert(!(Kind == PointsToPrevious &&
-           Reader.FirstLatestDeclIDs.find(ThisDeclID) !=
-               Reader.FirstLatestDeclIDs.end()) &&
-         "This decl is not first, it should not be in the map");
-  if (Kind == PointsToPrevious)
-    return;
-
-  // This decl is a first one and the latest declaration that it points to is in
-  // the same AST file. However, if this actually needs to point to a
-  // redeclaration in another AST file, we need to update it by checking the
-  // FirstLatestDeclIDs map which tracks this kind of decls.
-  assert(Reader.GetDecl(ThisDeclID) == static_cast<T*>(D) &&
-         "Invalid ThisDeclID ?");
-  ASTReader::FirstLatestDeclIDMap::iterator I
-      = Reader.FirstLatestDeclIDs.find(ThisDeclID);
-  if (I != Reader.FirstLatestDeclIDs.end()) {
-    Decl *NewLatest = Reader.GetDecl(I->second);
-    D->RedeclLink
-        = typename Redeclarable<T>::LatestDeclLink(cast_or_null<T>(NewLatest));
-  }
 }
 
 //===----------------------------------------------------------------------===//
@@ -1564,7 +1533,9 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
     FD->RedeclLink.setPointer(cast<FunctionDecl>(previous));
   } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
     VD->RedeclLink.setPointer(cast<VarDecl>(previous));
-  } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(previous)) {
+  } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+    TD->RedeclLink.setPointer(cast<TypedefNameDecl>(previous));
+  } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
     ID->RedeclLink.setPointer(cast<ObjCInterfaceDecl>(previous));
   } else {
     RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
@@ -1572,6 +1543,31 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
   }
 }
 
+void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
+  assert(D && Latest);
+  if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+    TD->RedeclLink
+      = Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest));
+  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    FD->RedeclLink 
+      = Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest));
+  } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    VD->RedeclLink
+      = Redeclarable<VarDecl>::LatestDeclLink(cast<VarDecl>(Latest));
+  } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+    TD->RedeclLink
+      = Redeclarable<TypedefNameDecl>::LatestDeclLink(
+                                                cast<TypedefNameDecl>(Latest));
+  } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
+    ID->RedeclLink
+      = Redeclarable<ObjCInterfaceDecl>::LatestDeclLink(
+                                              cast<ObjCInterfaceDecl>(Latest));
+  } else {
+    RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
+    TD->getCommonPtr()->Latest = cast<RedeclarableTemplateDecl>(Latest);
+  }
+}
+
 void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) {
   Decl *previous = GetDecl(ID);
   ASTDeclReader::attachPreviousDecl(D, previous);
@@ -1903,6 +1899,152 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) {
   }
 }
 
+namespace {
+  struct CompareLocalRedeclarationsInfoToID {
+    bool operator()(const LocalRedeclarationsInfo &X, DeclID Y) {
+      return X.FirstID < Y;
+    }
+
+    bool operator()(DeclID X, const LocalRedeclarationsInfo &Y) {
+      return X < Y.FirstID;
+    }
+
+    bool operator()(const LocalRedeclarationsInfo &X, 
+                    const LocalRedeclarationsInfo &Y) {
+      return X.FirstID < Y.FirstID;
+    }
+    bool operator()(DeclID X, DeclID Y) {
+      return X < Y;
+    }
+  };
+  
+  class RedeclChainVisitor {
+    ASTReader &Reader;
+    DeclID GlobalFirstID;
+    llvm::SmallVector<std::pair<Decl *, Decl *>, 4> Chains;
+    
+  public:
+    RedeclChainVisitor(ASTReader &Reader, DeclID GlobalFirstID)
+      : Reader(Reader), GlobalFirstID(GlobalFirstID) { }
+    
+    static bool visit(ModuleFile &M, bool Preorder, void *UserData) {
+      if (Preorder)
+        return false;
+      
+      return static_cast<RedeclChainVisitor *>(UserData)->visit(M);
+    }
+    
+    bool visit(ModuleFile &M) {
+      // Map global ID of the first declaration down to the local ID
+      // used in this module file.
+      DeclID FirstID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalFirstID);
+      if (!FirstID)
+        return false;
+      
+      // Perform a binary search to find the local redeclarations for this
+      // declaration (if any).
+      const LocalRedeclarationsInfo *Result
+        = std::lower_bound(M.RedeclarationsInfo,
+                           M.RedeclarationsInfo + M.LocalNumRedeclarationsInfos, 
+                           FirstID, CompareLocalRedeclarationsInfoToID());
+      if (Result == M.RedeclarationsInfo + M.LocalNumRedeclarationsInfos ||
+          Result->FirstID != FirstID)
+        return false;
+
+      // Dig out the starting/ending declarations.
+      Decl *FirstLocalDecl = Reader.GetLocalDecl(M, Result->FirstLocalID);
+      Decl *LastLocalDecl = Reader.GetLocalDecl(M, Result->LastLocalID);
+      if (!FirstLocalDecl || !LastLocalDecl)
+        return false;
+      
+      // Append this redeclaration chain to the list.
+      Chains.push_back(std::make_pair(FirstLocalDecl, LastLocalDecl));
+      return false;
+    }
+    
+    ArrayRef<std::pair<Decl *, Decl *> > getChains() const {
+      return Chains;
+    }
+    
+    void addParsed(Decl *FirstParsedDecl, Decl *LastParsedDecl) {
+      Chains.push_back(std::make_pair(FirstParsedDecl, LastParsedDecl));
+    }
+  };
+}
+
+/// \brief Retrieve the previous declaration to D.
+static Decl *getPreviousDecl(Decl *D) {
+  if (TagDecl *TD = dyn_cast<TagDecl>(D))
+    return TD->getPreviousDeclaration();
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+    return FD->getPreviousDeclaration();
+  if (VarDecl *VD = dyn_cast<VarDecl>(D))
+    return VD->getPreviousDeclaration();
+  if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+    return TD->getPreviousDeclaration();
+  if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
+    return ID->getPreviousDeclaration();
+  
+  return cast<RedeclarableTemplateDecl>(D)->getPreviousDeclaration();
+}
+
+/// \brief Retrieve the most recent declaration of D.
+static Decl *getMostRecentDecl(Decl *D) {
+  if (TagDecl *TD = dyn_cast<TagDecl>(D))
+    return TD->getMostRecentDeclaration();
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+    return FD->getMostRecentDeclaration();
+  if (VarDecl *VD = dyn_cast<VarDecl>(D))
+    return VD->getMostRecentDeclaration();
+  if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+    return TD->getMostRecentDeclaration();
+  if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
+    return ID->getMostRecentDeclaration();
+  
+  return cast<RedeclarableTemplateDecl>(D)->getMostRecentDeclaration();
+}
+
+void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) {
+  // Build up the list of redeclaration chains.
+  RedeclChainVisitor Visitor(*this, ID);
+  ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visit, &Visitor);
+  
+  // Retrieve the chains.
+  ArrayRef<std::pair<Decl *, Decl *> > Chains = Visitor.getChains();
+  if (Chains.empty())
+    return;
+  
+  // FIXME: Splice local (not from AST file) declarations into the list,
+  // rather than always re-ordering them.
+  Decl *CanonDecl = GetDecl(ID);  
+  
+  // Capture all of the parsed declarations and put them at the end.
+  Decl *MostRecent = getMostRecentDecl(CanonDecl);
+  Decl *FirstParsed = MostRecent;
+  if (CanonDecl != MostRecent && !MostRecent->isFromASTFile()) {
+    Decl *Current = MostRecent;
+    while (Decl *Prev = getPreviousDecl(Current)) {
+      if (Prev->isFromASTFile()) {
+        Current = Prev;
+        continue;
+      }
+      
+      // Chain all of the parsed declarations together.
+      ASTDeclReader::attachPreviousDecl(FirstParsed, Prev);
+      FirstParsed = Prev;
+      Current = Prev;
+    }
+    
+    Visitor.addParsed(FirstParsed, MostRecent);
+  }
+  
+  // Hook up the separate chains.
+  Chains = Visitor.getChains();
+  for (unsigned I = 1, N = Chains.size(); I != N; ++I)
+    ASTDeclReader::attachPreviousDecl(Chains[I].first, Chains[I-1].second);    
+  ASTDeclReader::attachLatestDecl(CanonDecl, Chains.back().second);
+}
+
 namespace {
   /// \brief Given an ObjC interface, goes through the modules and links to the
   /// interface all the categories for it.
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index b3f76f749457c6e9e953f9734aa2ceb320c72c94..bb2b1cb5b082d5dde64809fc79fc9383ee524152 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -798,7 +798,8 @@ void ASTWriter::WriteBlockInfoBlock() {
   RECORD(KNOWN_NAMESPACES);
   RECORD(MODULE_OFFSET_MAP);
   RECORD(SOURCE_MANAGER_LINE_TABLE);
-  
+  RECORD(LOCAL_REDECLARATIONS);
+         
   // SourceManager Block.
   BLOCK(SOURCE_MANAGER_BLOCK);
   RECORD(SM_SLOC_FILE_ENTRY);
@@ -3411,6 +3412,25 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
   WriteDeclReplacementsBlock();
   WriteChainedObjCCategories();
 
+  if (!LocalRedeclarations.empty()) {
+    // Sort the local redeclarations info by the first declaration ID,
+    // since the reader will be perforing binary searches on this information.
+    llvm::array_pod_sort(LocalRedeclarations.begin(),LocalRedeclarations.end());
+    
+    llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+    Abbrev->Add(BitCodeAbbrevOp(LOCAL_REDECLARATIONS));
+    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries
+    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+    unsigned AbbrevID = Stream.EmitAbbrev(Abbrev);
+
+    Record.clear();
+    Record.push_back(LOCAL_REDECLARATIONS);
+    Record.push_back(LocalRedeclarations.size());
+    Stream.EmitRecordWithBlob(AbbrevID, Record, 
+      reinterpret_cast<char*>(LocalRedeclarations.data()),
+      LocalRedeclarations.size() * sizeof(LocalRedeclarationsInfo));
+  }
+  
   // Some simple statistics
   Record.clear();
   Record.push_back(NumStatements);
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 9b74aaeae457e575d845cd43cee02823db7521e8..6c6428d55a806e94217785f334a43883b7f91489 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -125,6 +125,30 @@ namespace clang {
   };
 }
 
+static bool isFirstDeclInFile(Decl *D) {
+  // FIXME: There must be a better way to abstract Redeclarable<T> into a 
+  // more-general "redeclarable type".
+  if (TagDecl *Tag = dyn_cast<TagDecl>(D))
+    return !Tag->getPreviousDeclaration() ||
+           Tag->getPreviousDeclaration()->isFromASTFile();
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+    return !FD->getPreviousDeclaration() ||
+           FD->getPreviousDeclaration()->isFromASTFile();
+  if (VarDecl *VD = dyn_cast<VarDecl>(D))
+    return !VD->getPreviousDeclaration() ||
+           VD->getPreviousDeclaration()->isFromASTFile();
+  if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+    return !TD->getPreviousDeclaration() ||
+           TD->getPreviousDeclaration()->isFromASTFile();
+  if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
+    return !ID->getPreviousDeclaration() ||
+            ID->getPreviousDeclaration()->isFromASTFile();
+  
+  RedeclarableTemplateDecl *RTD = cast<RedeclarableTemplateDecl>(D);
+  return !RTD->getPreviousDeclaration() ||
+          RTD->getPreviousDeclaration()->isFromASTFile();  
+}
+
 void ASTDeclWriter::Visit(Decl *D) {
   DeclVisitor<ASTDeclWriter>::Visit(D);
 
@@ -177,13 +201,14 @@ void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) {
 }
 
 void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
+  VisitRedeclarable(D);
   VisitTypeDecl(D);
   Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
 
   if (!D->hasAttrs() &&
       !D->isImplicit() &&
       !D->isUsed(false) &&
-      D->RedeclLink.getNext() == D &&
+      isFirstDeclInFile(D) &&
       !D->isInvalidDecl() &&
       !D->isReferenced() &&
       !D->isTopLevelDeclInObjCContainer() &&
@@ -196,6 +221,7 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
 }
 
 void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) {
+  VisitRedeclarable(D);
   VisitTypeDecl(D);
   Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
   Code = serialization::DECL_TYPEALIAS;
@@ -234,7 +260,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
       !D->isImplicit() &&
       !D->isUsed(false) &&
       !D->hasExtInfo() &&
-      D->RedeclLink.getNext() == D &&
+      isFirstDeclInFile(D) &&
       !D->isInvalidDecl() &&
       !D->isReferenced() &&
       !D->isTopLevelDeclInObjCContainer() &&
@@ -258,7 +284,7 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
       !D->isImplicit() &&
       !D->isUsed(false) &&
       !D->hasExtInfo() &&
-      D->RedeclLink.getNext() == D &&
+      isFirstDeclInFile(D) &&
       !D->isInvalidDecl() &&
       !D->isReferenced() &&
       !D->isTopLevelDeclInObjCContainer() &&
@@ -701,7 +727,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
       !D->isModulePrivate() &&
       D->getDeclName().getNameKind() == DeclarationName::Identifier &&
       !D->hasExtInfo() &&
-      D->RedeclLink.getNext() == D &&
+      isFirstDeclInFile(D) &&
       !D->hasCXXDirectInitializer() &&
       D->getInit() == 0 &&
       !isa<ParmVarDecl>(D) &&
@@ -1267,30 +1293,24 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
 
 template <typename T>
 void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
-  enum { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
-  if (D->RedeclLink.getNext() == D) {
-    Record.push_back(NoRedeclaration);
-  } else {
-    if (D->RedeclLink.NextIsPrevious()) {
-      Record.push_back(PointsToPrevious);
-      Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
-      Writer.AddDeclRef(D->getFirstDeclaration(), Record);
-    } else {
-      Record.push_back(PointsToLatest);
-      Writer.AddDeclRef(D->RedeclLink.getPointer(), Record);
-    }
-  }
-
+  enum { FirstInFile, PointsToPrevious };
   T *First = D->getFirstDeclaration();
-  T *ThisDecl = static_cast<T*>(D);
-  // If this is a most recent redeclaration that is pointed to by a first decl
-  // in a chained PCH, keep track of the association with the map so we can
-  // update the first decl during AST reading.
-  if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl &&
-      First->isFromASTFile() && !ThisDecl->isFromASTFile()) {
-    assert(Writer.FirstLatestDecls.find(First) == Writer.FirstLatestDecls.end()
-           && "The latest is already set");
-    Writer.FirstLatestDecls[First] = ThisDecl;
+  if (!D->getPreviousDeclaration() ||
+      D->getPreviousDeclaration()->isFromASTFile()) {
+    Record.push_back(FirstInFile);
+    Writer.AddDeclRef(First, Record);
+
+    // Capture the set of redeclarations in this file.
+    LocalRedeclarationsInfo LocalInfo = {
+      Writer.GetDeclRef(First),
+      Writer.GetDeclRef(static_cast<T*>(D)),
+      Writer.GetDeclRef(D->getMostRecentDeclaration())
+    };
+    Writer.LocalRedeclarations.push_back(LocalInfo);    
+  } else {
+    Record.push_back(PointsToPrevious);
+    Writer.AddDeclRef(First, Record);
+    Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
   }
 }
 
@@ -1374,7 +1394,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
   Abv = new BitCodeAbbrev();
   Abv->Add(BitCodeAbbrevOp(serialization::DECL_ENUM));
   // Redeclarable
-  Abv->Add(BitCodeAbbrevOp(0));                         // No redeclaration
+  Abv->Add(BitCodeAbbrevOp(0));                       // First in file
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID
   // Decl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1421,7 +1442,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
   Abv = new BitCodeAbbrev();
   Abv->Add(BitCodeAbbrevOp(serialization::DECL_RECORD));
   // Redeclarable
-  Abv->Add(BitCodeAbbrevOp(0));                         // No redeclaration
+  Abv->Add(BitCodeAbbrevOp(0));                       // First in file
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID
   // Decl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1462,7 +1484,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
   Abv = new BitCodeAbbrev();
   Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR));
   // Redeclarable
-  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration
+  Abv->Add(BitCodeAbbrevOp(0));                       // First in file
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID
   // Decl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1511,6 +1534,9 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
   // Abbreviation for DECL_TYPEDEF
   Abv = new BitCodeAbbrev();
   Abv->Add(BitCodeAbbrevOp(serialization::DECL_TYPEDEF));
+  // Redeclarable
+  Abv->Add(BitCodeAbbrevOp(0));                       // First in file
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID
   // Decl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1538,7 +1564,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
   Abv = new BitCodeAbbrev();
   Abv->Add(BitCodeAbbrevOp(serialization::DECL_VAR));
   // Redeclarable
-  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration
+  Abv->Add(BitCodeAbbrevOp(0));                       // First in file
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID
   // Decl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
diff --git a/lib/Serialization/Module.cpp b/lib/Serialization/Module.cpp
index 11e7243cd51ba7fe8e9242ec2bf1b1e6e336f694..1298714dd068e3e635a4c233d7147fa9ef679b8b 100644
--- a/lib/Serialization/Module.cpp
+++ b/lib/Serialization/Module.cpp
@@ -35,7 +35,7 @@ ModuleFile::ModuleFile(ModuleKind Kind)
     SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0),
     DeclOffsets(0), BaseDeclID(0),
     LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0),
-    FileSortedDecls(0),
+    FileSortedDecls(0), RedeclarationsInfo(0), LocalNumRedeclarationsInfos(0),
     LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0), StatCache(0)
 {}
 
diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map
index f7cc7d4b515381ce80632d38b5c273312e2519b6..b101c01567d694db6282262e44ca93683b4e6ab2 100644
--- a/test/Modules/Inputs/module.map
+++ b/test/Modules/Inputs/module.map
@@ -41,4 +41,20 @@ module decldef {
   explicit module Decl { header "decl.h" }
   explicit module Decl2 { header "decl2.h" }
   explicit module Def { header "def.h" }
-}
\ No newline at end of file
+}
+
+module redecl_merge_top { 
+  header "redecl-merge-top.h" 
+}
+module redecl_merge_left { 
+  header "redecl-merge-left.h" 
+  export *
+}
+module redecl_merge_right { 
+  header "redecl-merge-right.h" 
+  export *
+}
+module redecl_merge_bottom { 
+  header "redecl-merge-bottom.h" 
+  export *
+}
diff --git a/test/Modules/Inputs/redecl-merge-bottom.h b/test/Modules/Inputs/redecl-merge-bottom.h
new file mode 100644
index 0000000000000000000000000000000000000000..e45e0dea0477ec1f1d3672533e6dc31b0257e357
--- /dev/null
+++ b/test/Modules/Inputs/redecl-merge-bottom.h
@@ -0,0 +1,4 @@
+__import_module__ redecl_merge_left;
+__import_module__ redecl_merge_right;
+
+@class A;
diff --git a/test/Modules/Inputs/redecl-merge-left.h b/test/Modules/Inputs/redecl-merge-left.h
new file mode 100644
index 0000000000000000000000000000000000000000..085892234818cd04796988109c5d45c4fef7335a
--- /dev/null
+++ b/test/Modules/Inputs/redecl-merge-left.h
@@ -0,0 +1,7 @@
+__import_module__ redecl_merge_top;
+
+@class A;
+
+@class A;
+
+@class A;
diff --git a/test/Modules/Inputs/redecl-merge-right.h b/test/Modules/Inputs/redecl-merge-right.h
new file mode 100644
index 0000000000000000000000000000000000000000..266146c9953e8fff73a29738377314daa056bfe8
--- /dev/null
+++ b/test/Modules/Inputs/redecl-merge-right.h
@@ -0,0 +1,9 @@
+__import_module__ redecl_merge_top;
+
+@interface Super
+@end
+
+@interface A : Super
+- (Super*)init;
+@end
+
diff --git a/test/Modules/Inputs/redecl-merge-top.h b/test/Modules/Inputs/redecl-merge-top.h
new file mode 100644
index 0000000000000000000000000000000000000000..886436cdda8670d59a7aec93dbb4b0055ba7e683
--- /dev/null
+++ b/test/Modules/Inputs/redecl-merge-top.h
@@ -0,0 +1,5 @@
+@class A;
+
+@class A;
+
+@class A;
diff --git a/test/Modules/redecl-merge.m b/test/Modules/redecl-merge.m
new file mode 100644
index 0000000000000000000000000000000000000000..40c6aaf0fffa49a2fbef6f9b5fb0932d8d430637
--- /dev/null
+++ b/test/Modules/redecl-merge.m
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodule-cache-path %t -I %S/Inputs %s -verify
+__import_module__ redecl_merge_left;
+__import_module__ redecl_merge_right;
+
+@implementation A
+- (Super*)init { return self; }
+@end
+
+void f(A *a) {
+  [a init];
+}
+
+@class A;
+
+__import_module__ redecl_merge_bottom;
+
+void g(A *a) {
+  [a init];
+}
diff --git a/test/PCH/chain-cxx.cpp b/test/PCH/chain-cxx.cpp
index af0a23afea9f1b06519b26ff1937a038e0040ff5..c42ee7d39eeb8012bf44fce285062d6a96199388 100644
--- a/test/PCH/chain-cxx.cpp
+++ b/test/PCH/chain-cxx.cpp
@@ -44,6 +44,8 @@ const int TS3<T>::value;
 // Instantiate struct, but not value.
 struct instantiate : TS3<int> {};
 
+// Typedef
+typedef int Integer;
 
 //===----------------------------------------------------------------------===//
 #elif not defined(HEADER2)
@@ -97,6 +99,9 @@ struct B : A { };
 // Instantiate TS3's member.
 static const int ts3m1 = TS3<int>::value;
 
+// Redefinition of typedef
+typedef int Integer;
+
 //===----------------------------------------------------------------------===//
 #else
 //===----------------------------------------------------------------------===//
@@ -122,6 +127,7 @@ void test() {
   TS2int ts2;
 
   B b;
+  Integer i = 17;
 }
 
 // Should have remembered that there is a definition.