Read/write the C++ parts of DeclRefExpr and MemberExpr for PCH.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107872 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp
index d330eec..2f99d7c 100644
--- a/lib/Frontend/PCHReaderStmt.cpp
+++ b/lib/Frontend/PCHReaderStmt.cpp
@@ -374,10 +374,24 @@
 
 void PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
   VisitExpr(E);
+
+  bool HasQualifier = Record[Idx++];
+  unsigned NumTemplateArgs = Record[Idx++];
+  
+  E->DecoratedD.setInt((HasQualifier? DeclRefExpr::HasQualifierFlag : 0) |
+      (NumTemplateArgs ? DeclRefExpr::HasExplicitTemplateArgumentListFlag : 0));
+  
+  if (HasQualifier) {
+    E->getNameQualifier()->NNS = Reader.ReadNestedNameSpecifier(Record, Idx);
+    E->getNameQualifier()->Range = Reader.ReadSourceRange(Record, Idx);
+  }
+
+  if (NumTemplateArgs)
+    ReadExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList(),
+                                     NumTemplateArgs);
+
   E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  // FIXME: read qualifier
-  // FIXME: read explicit template arguments
+  E->setLocation(Reader.ReadSourceLocation(Record, Idx));
 }
 
 void PCHStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
@@ -519,11 +533,9 @@
 }
 
 void PCHStmtReader::VisitMemberExpr(MemberExpr *E) {
-  VisitExpr(E);
-  E->setBase(Reader.ReadSubExpr());
-  E->setMemberDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
-  E->setMemberLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setArrow(Record[Idx++]);
+  // Don't call VisitExpr, this is fully initialized at creation.
+  assert(E->getStmtClass() == Stmt::MemberExprClass &&
+         "It's a subclass, we must advance Idx!");
 }
 
 void PCHStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) {
@@ -1321,7 +1333,9 @@
       break;
 
     case pch::EXPR_DECL_REF:
-      S = new (Context) DeclRefExpr(Empty);
+      S = DeclRefExpr::CreateEmpty(*Context,
+                         /*HasQualifier=*/Record[PCHStmtReader::NumExprFields],
+                  /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields + 1]);
       break;
 
     case pch::EXPR_INTEGER_LITERAL:
@@ -1375,9 +1389,43 @@
       S = new (Context) CallExpr(*Context, Stmt::CallExprClass, Empty);
       break;
 
-    case pch::EXPR_MEMBER:
-      S = new (Context) MemberExpr(Empty);
+    case pch::EXPR_MEMBER: {
+      // We load everything here and fully initialize it at creation.
+      // That way we can use MemberExpr::Create and don't have to duplicate its
+      // logic with a MemberExpr::CreateEmpty.
+
+      assert(Idx == 0);
+      NestedNameSpecifier *NNS = 0;
+      SourceRange QualifierRange;
+      if (Record[Idx++]) { // HasQualifier.
+        NNS = ReadNestedNameSpecifier(Record, Idx);
+        QualifierRange = ReadSourceRange(Record, Idx);
+      }
+
+      TemplateArgumentListInfo ArgInfo;
+      unsigned NumTemplateArgs = Record[Idx++];
+      if (NumTemplateArgs) {
+        ArgInfo.setLAngleLoc(ReadSourceLocation(Record, Idx));
+        ArgInfo.setRAngleLoc(ReadSourceLocation(Record, Idx));
+        for (unsigned i = 0; i != NumTemplateArgs; ++i)
+          ArgInfo.addArgument(ReadTemplateArgumentLoc(Record, Idx));
+      }
+      
+      NamedDecl *FoundD = cast_or_null<NamedDecl>(GetDecl(Record[Idx++]));
+      AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
+      DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS);
+
+      QualType T = GetType(Record[Idx++]);
+      Expr *Base = ReadSubExpr();
+      ValueDecl *MemberD = cast<ValueDecl>(GetDecl(Record[Idx++]));
+      SourceLocation MemberLoc = ReadSourceLocation(Record, Idx);
+      bool IsArrow = Record[Idx++];
+
+      S = MemberExpr::Create(*Context, Base, IsArrow, NNS, QualifierRange,
+                             MemberD, FoundDecl, MemberLoc,
+                             NumTemplateArgs ? &ArgInfo : 0, T);
       break;
+    }
 
     case pch::EXPR_BINARY_OPERATOR:
       S = new (Context) BinaryOperator(Empty);
diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp
index 00cebf1..ea46474 100644
--- a/lib/Frontend/PCHWriterStmt.cpp
+++ b/lib/Frontend/PCHWriterStmt.cpp
@@ -359,10 +359,23 @@
 
 void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
   VisitExpr(E);
+
+  Record.push_back(E->hasQualifier());
+  unsigned NumTemplateArgs = E->getNumTemplateArgs();
+  assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgumentList() &&
+         "Template args list with no args ?");
+  Record.push_back(NumTemplateArgs);
+
+  if (E->hasQualifier()) {
+    Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
+    Writer.AddSourceRange(E->getQualifierRange(), Record);
+  }
+
+  if (NumTemplateArgs)
+    AddExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList());
+
   Writer.AddDeclRef(E->getDecl(), Record);
   Writer.AddSourceLocation(E->getLocation(), Record);
-  // FIXME: write qualifier
-  // FIXME: write explicit template arguments
   Code = pch::EXPR_DECL_REF;
 }
 
@@ -507,13 +520,34 @@
 }
 
 void PCHStmtWriter::VisitMemberExpr(MemberExpr *E) {
-  VisitExpr(E);
+  // Don't call VisitExpr, we'll write everything here.
+
+  Record.push_back(E->hasQualifier());
+  if (E->hasQualifier()) {
+    Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
+    Writer.AddSourceRange(E->getQualifierRange(), Record);
+  }
+
+  unsigned NumTemplateArgs = E->getNumTemplateArgs();
+  assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgumentList() &&
+         "Template args list with no args ?");
+  Record.push_back(NumTemplateArgs);
+  if (NumTemplateArgs) {
+    Writer.AddSourceLocation(E->getLAngleLoc(), Record);
+    Writer.AddSourceLocation(E->getRAngleLoc(), Record);
+    for (unsigned i=0; i != NumTemplateArgs; ++i)
+      Writer.AddTemplateArgumentLoc(E->getTemplateArgs()[i], Record);
+  }
+  
+  DeclAccessPair FoundDecl = E->getFoundDecl();
+  Writer.AddDeclRef(FoundDecl.getDecl(), Record);
+  Record.push_back(FoundDecl.getAccess());
+
+  Writer.AddTypeRef(E->getType(), Record);
   Writer.AddStmt(E->getBase());
   Writer.AddDeclRef(E->getMemberDecl(), Record);
   Writer.AddSourceLocation(E->getMemberLoc(), Record);
   Record.push_back(E->isArrow());
-  // FIXME: C++ nested-name-specifier
-  // FIXME: C++ template argument list
   Code = pch::EXPR_MEMBER;
 }