Add support for declaring pointers to members.
Add serialization support for ReferenceType.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62934 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index ecae793..21db14a 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -287,9 +287,9 @@
           !T->isIncompleteOrObjectType()) {
         Diag(DeclType.Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
           << T;
-        DeclType.Ptr.TypeQuals &= QualType::Restrict;
-      }        
-        
+        DeclType.Ptr.TypeQuals &= ~QualType::Restrict;
+      }
+
       // Apply the pointer typequals to the pointer object.
       T = Context.getPointerType(T).getQualifiedType(DeclType.Ptr.TypeQuals);
       break;
@@ -424,7 +424,7 @@
       }
       break;
     }
-    case DeclaratorChunk::Function:
+    case DeclaratorChunk::Function: {
       // If the function declarator has a prototype (i.e. it is not () and
       // does not have a K&R-style identifier list), then the arguments are part
       // of the type, otherwise the argument list is ().
@@ -518,7 +518,54 @@
       }
       break;
     }
-    
+    case DeclaratorChunk::MemberPointer:
+      // The scope spec must refer to a class, or be dependent.
+      DeclContext *DC = static_cast<DeclContext*>(
+        DeclType.Mem.Scope().getScopeRep());
+      QualType ClsType;
+      // FIXME: Extend for dependent types when it's actually supported.
+      // See ActOnCXXNestedNameSpecifier.
+      if (CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC)) {
+        ClsType = Context.getTagDeclType(RD);
+      } else {
+        if (DC) {
+          Diag(DeclType.Mem.Scope().getBeginLoc(),
+               diag::err_illegal_decl_mempointer_in_nonclass)
+            << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
+            << DeclType.Mem.Scope().getRange();
+        }
+        D.setInvalidType(true);
+        ClsType = Context.IntTy;
+      }
+
+      // C++ 8.3.3p3: A pointer to member shall not pointer to ... a member
+      //   with reference type, or "cv void."
+      if (T->isReferenceType()) {
+        Diag(DeclType.Loc, diag::err_illegal_decl_pointer_to_reference)
+          << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
+        D.setInvalidType(true);
+        T = Context.IntTy;
+      }
+      if (T->isVoidType()) {
+        Diag(DeclType.Loc, diag::err_illegal_decl_mempointer_to_void)
+          << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
+        T = Context.IntTy;
+      }
+
+      // Enforce C99 6.7.3p2: "Types other than pointer types derived from
+      // object or incomplete types shall not be restrict-qualified."
+      if ((DeclType.Mem.TypeQuals & QualType::Restrict) &&
+          !T->isIncompleteOrObjectType()) {
+        Diag(DeclType.Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
+          << T;
+        DeclType.Mem.TypeQuals &= ~QualType::Restrict;
+      }
+
+      T = Context.getMemberPointerType(T, ClsType.getTypePtr());
+
+      break;
+    }
+
     // See if there are any attributes on this declarator chunk.
     if (const AttributeList *AL = DeclType.getAttrs())
       ProcessTypeAttributeList(T, AL);