Handle CXXConstructorDecl, CXXDestructorDecl, and CXXConversionDecl for PCH.

<vector> header can be used correctly through PCH now.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107483 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index cea7ba0..936ca5e 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -40,6 +40,8 @@
                   PCHWriter::RecordData &Record)
       : Writer(Writer), Context(Context), Record(Record) {
     }
+    
+    void Visit(Decl *D);
 
     void VisitDecl(Decl *D);
     void VisitTranslationUnitDecl(TranslationUnitDecl *D);
@@ -112,6 +114,19 @@
   };
 }
 
+void PCHDeclWriter::Visit(Decl *D) {
+  DeclVisitor<PCHDeclWriter>::Visit(D);
+
+  // Handle FunctionDecl's body here and write it after all other Stmts/Exprs
+  // have been written. We want it last because we will not read it back when
+  // retrieving it from the PCH, we'll just lazily set the offset. 
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    Record.push_back(FD->isThisDeclarationADefinition());
+    if (FD->isThisDeclarationADefinition())
+      Writer.AddStmt(FD->getBody());
+  }
+}
+
 void PCHDeclWriter::VisitDecl(Decl *D) {
   Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
   Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
@@ -255,11 +270,8 @@
   }
   }
 
-  // Make sure no Exprs are emitted after the body, because when reading the
-  // function, the body doesn't get read so the cursor doesn't advance. 
-  Record.push_back(D->isThisDeclarationADefinition());
-  if (D->isThisDeclarationADefinition())
-    Writer.AddStmt(D->getBody());
+  // FunctionDecl's body is handled last at PCHWriterDecl::Visit,
+  // after everything else is written.
 
   Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
   Record.push_back(D->getStorageClass()); // FIXME: stable encoding
@@ -691,26 +703,57 @@
 }
 
 void PCHDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
-  // assert(false && "cannot write CXXMethodDecl");
   VisitFunctionDecl(D);
   Code = pch::DECL_CXX_METHOD;
 }
 
 void PCHDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
-  // assert(false && "cannot write CXXConstructorDecl");
   VisitCXXMethodDecl(D);
+
+  Record.push_back(D->IsExplicitSpecified);
+  Record.push_back(D->ImplicitlyDefined);
+  
+  Record.push_back(D->NumBaseOrMemberInitializers);
+  for (unsigned i=0; i != D->NumBaseOrMemberInitializers; ++i) {
+    CXXBaseOrMemberInitializer *Init = D->BaseOrMemberInitializers[i];
+
+    Record.push_back(Init->isBaseInitializer());
+    if (Init->isBaseInitializer()) {
+      Writer.AddTypeSourceInfo(Init->getBaseClassInfo(), Record);
+      Record.push_back(Init->isBaseVirtual());
+    } else {
+      Writer.AddDeclRef(Init->getMember(), Record);
+    }
+    Writer.AddSourceLocation(Init->getMemberLocation(), Record);
+    Writer.AddStmt(Init->getInit());
+    Writer.AddDeclRef(Init->getAnonUnionMember(), Record);
+    Writer.AddSourceLocation(Init->getLParenLoc(), Record);
+    Writer.AddSourceLocation(Init->getRParenLoc(), Record);
+    Record.push_back(Init->isWritten());
+    if (Init->isWritten()) {
+      Record.push_back(Init->getSourceOrder());
+    } else {
+      Record.push_back(Init->getNumArrayIndices());
+      for (unsigned i=0, e=Init->getNumArrayIndices(); i != e; ++i)
+        Writer.AddDeclRef(Init->getArrayIndex(i), Record);
+    }
+  }
+
   Code = pch::DECL_CXX_CONSTRUCTOR;
 }
 
 void PCHDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
-  // assert(false && "cannot write CXXDestructorDecl");
   VisitCXXMethodDecl(D);
+
+  Record.push_back(D->ImplicitlyDefined);
+  Writer.AddDeclRef(D->OperatorDelete, Record);
+
   Code = pch::DECL_CXX_DESTRUCTOR;
 }
 
 void PCHDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) {
-  // assert(false && "cannot write CXXConversionDecl");
   VisitCXXMethodDecl(D);
+  Record.push_back(D->IsExplicitSpecified);
   Code = pch::DECL_CXX_CONVERSION;
 }