Support C++ friend declarations for PCH.

This commit 'introduces' a slightly different way to restore the state of the AST object.
It makes PCHDeclReader/PCHDeclWriter friends and gives them access to the private members of the object.
The rationale is to avoid using/modifying the AST interfaces for PCH read/write so that to:

-Avoid complications with objects that have side-effects during creation or when using some setters.
-Not 'pollute' the AST interface with methods only used by the PCH reader/writer
-Allow AST objects to be read-only.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107219 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 42d5069..309cc35 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -25,7 +25,7 @@
 // Declaration serialization
 //===----------------------------------------------------------------------===//
 
-namespace {
+namespace clang {
   class PCHDeclWriter : public DeclVisitor<PCHDeclWriter, void> {
 
     PCHWriter &Writer;
@@ -82,6 +82,7 @@
     void VisitLinkageSpecDecl(LinkageSpecDecl *D);
     void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
     void VisitAccessSpecDecl(AccessSpecDecl *D);
+    void VisitFriendDecl(FriendDecl *D);
     void VisitFriendTemplateDecl(FriendTemplateDecl *D);
     void VisitStaticAssertDecl(StaticAssertDecl *D);
     void VisitBlockDecl(BlockDecl *D);
@@ -636,7 +637,6 @@
 }
 
 void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
-  // assert(false && "cannot write CXXRecordDecl");
   VisitRecordDecl(D);
 
   enum {
@@ -664,6 +664,8 @@
     for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
            E = D->bases_end(); I != E; ++I)
       WriteCXXBaseSpecifier(&*I);
+    
+    Writer.AddDeclRef(D->data().FirstFriend, Record);
   }
   Code = pch::DECL_CXX_RECORD;
 }
@@ -698,6 +700,17 @@
   Code = pch::DECL_ACCESS_SPEC;
 }
 
+void PCHDeclWriter::VisitFriendDecl(FriendDecl *D) {
+  Record.push_back(D->Friend.is<TypeSourceInfo*>());
+  if (D->Friend.is<TypeSourceInfo*>())
+    Writer.AddTypeSourceInfo(D->Friend.get<TypeSourceInfo*>(), Record);
+  else
+    Writer.AddDeclRef(D->Friend.get<NamedDecl*>(), Record);
+  Writer.AddDeclRef(D->NextFriend, Record);
+  Writer.AddSourceLocation(D->FriendLoc, Record);
+  Code = pch::DECL_FRIEND;
+}
+
 void PCHDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
   assert(false && "cannot write FriendTemplateDecl");
 }