Allow deserialization of just the fields of a record, when we want to iterate over them,
instead of deserializing the complete declaration context of the record.

Iterating over the fields of a record is very common (e.g to determine the layout), unfortunately we needlessly deserialize every declaration
that the declaration context of the record contains; this can be bad for large C++ classes that contain a lot of methods.
Fix this by allow deserialization of just the fields when we want to iterate over them.
Progress for rdar://7260160.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116507 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index ece9945..d60a067 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -599,6 +599,24 @@
   }
 }
 
+std::pair<Decl *, Decl *>
+DeclContext::BuildDeclChain(const llvm::SmallVectorImpl<Decl*> &Decls) {
+  // Build up a chain of declarations via the Decl::NextDeclInContext field.
+  Decl *FirstNewDecl = 0;
+  Decl *PrevDecl = 0;
+  for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
+    Decl *D = Decls[I];
+    if (PrevDecl)
+      PrevDecl->NextDeclInContext = D;
+    else
+      FirstNewDecl = D;
+
+    PrevDecl = D;
+  }
+
+  return std::make_pair(FirstNewDecl, PrevDecl);
+}
+
 /// \brief Load the declarations within this lexical storage from an
 /// external source.
 void
@@ -619,26 +637,22 @@
   if (Decls.empty())
     return;
 
-  // Resolve all of the declaration IDs into declarations, building up
-  // a chain of declarations via the Decl::NextDeclInContext field.
-  Decl *FirstNewDecl = 0;
-  Decl *PrevDecl = 0;
-  for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
-    Decl *D = Decls[I];
-    if (PrevDecl)
-      PrevDecl->NextDeclInContext = D;
-    else
-      FirstNewDecl = D;
-
-    PrevDecl = D;
-  }
+  // We may have already loaded just the fields of this record, in which case
+  // don't add the decls, just replace the FirstDecl/LastDecl chain.
+  if (const RecordDecl *RD = dyn_cast<RecordDecl>(this))
+    if (RD->LoadedFieldsFromExternalStorage) {
+      llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls);
+      return;
+    }
 
   // Splice the newly-read declarations into the beginning of the list
   // of declarations.
-  PrevDecl->NextDeclInContext = FirstDecl;
-  FirstDecl = FirstNewDecl;
+  Decl *ExternalFirst, *ExternalLast;
+  llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls);
+  ExternalLast->NextDeclInContext = FirstDecl;
+  FirstDecl = ExternalFirst;
   if (!LastDecl)
-    LastDecl = PrevDecl;
+    LastDecl = ExternalLast;
 }
 
 DeclContext::lookup_result