Substantially alter the design of the Objective C type AST by introducing
ObjCObjectType, which is basically just a pair of
  one of {primitive-id, primitive-Class, user-defined @class}
with
  a list of protocols.
An ObjCObjectPointerType is therefore just a pointer which always points to
one of these types (possibly sugared).  ObjCInterfaceType is now just a kind
of ObjCObjectType which happens to not carry any protocols.

Alter a rather large number of use sites to use ObjCObjectType instead of
ObjCInterfaceType.  Store an ObjCInterfaceType as a pointer on the decl rather
than hashing them in a FoldingSet.  Remove some number of methods that are no
longer used, at least after this patch.

By simplifying ObjCObjectPointerType, we are now able to easily remove and apply
pointers to Objective-C types, which is crucial for a certain kind of ObjC++
metaprogramming common in WebKit.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103870 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index b9aa611..5e365de 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -87,8 +87,9 @@
   }
   // Create the built-in typedef for 'id'.
   if (Context.getObjCIdType().isNull()) {
-    QualType IdT = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy);
-    TypeSourceInfo *IdInfo = Context.getTrivialTypeSourceInfo(IdT);
+    QualType T = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, 0, 0);
+    T = Context.getObjCObjectPointerType(T);
+    TypeSourceInfo *IdInfo = Context.getTrivialTypeSourceInfo(T);
     TypedefDecl *IdTypedef
       = TypedefDecl::Create(Context, CurContext, SourceLocation(),
                             &Context.Idents.get("id"), IdInfo);
@@ -98,9 +99,9 @@
   }
   // Create the built-in typedef for 'Class'.
   if (Context.getObjCClassType().isNull()) {
-    QualType ClassType
-      = Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy);
-    TypeSourceInfo *ClassInfo = Context.getTrivialTypeSourceInfo(ClassType);
+    QualType T = Context.getObjCObjectType(Context.ObjCBuiltinClassTy, 0, 0);
+    T = Context.getObjCObjectPointerType(T);
+    TypeSourceInfo *ClassInfo = Context.getTrivialTypeSourceInfo(T);
     TypedefDecl *ClassTypedef
       = TypedefDecl::Create(Context, CurContext, SourceLocation(),
                             &Context.Idents.get("Class"), ClassInfo);
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 77bf919..036ae7e 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -2047,14 +2047,14 @@
          I != E; ++I)
       AddObjCProperties(*I, true, CurContext, Results);
   } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
-             (!IsArrow && BaseType->isObjCInterfaceType())) {
+             (!IsArrow && BaseType->isObjCObjectType())) {
     // Objective-C instance variable access.
     ObjCInterfaceDecl *Class = 0;
     if (const ObjCObjectPointerType *ObjCPtr
                                     = BaseType->getAs<ObjCObjectPointerType>())
       Class = ObjCPtr->getInterfaceDecl();
     else
-      Class = BaseType->getAs<ObjCInterfaceType>()->getDecl();
+      Class = BaseType->getAs<ObjCObjectType>()->getInterface();
     
     // Add all ivars from this class and its superclasses.
     if (Class) {
@@ -2911,9 +2911,9 @@
   ObjCInterfaceDecl *IFace = 0;
   switch (Msg->getReceiverKind()) {
   case ObjCMessageExpr::Class:
-    if (const ObjCInterfaceType *IFaceType
-                           = Msg->getClassReceiver()->getAs<ObjCInterfaceType>())
-      IFace = IFaceType->getDecl();
+    if (const ObjCObjectType *ObjType
+                           = Msg->getClassReceiver()->getAs<ObjCObjectType>())
+      IFace = ObjType->getInterface();
     break;
 
   case ObjCMessageExpr::Instance: {
@@ -2994,9 +2994,9 @@
     if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
       // "super" names an interface. Use it.
     } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
-      if (const ObjCInterfaceType *Iface
-            = Context.getTypeDeclType(TD)->getAs<ObjCInterfaceType>())
-        CDecl = Iface->getDecl();
+      if (const ObjCObjectType *Iface
+            = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
+        CDecl = Iface->getInterface();
     } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
       // "super" names an unresolved type; we can't be more specific.
     } else {
@@ -3030,8 +3030,8 @@
   if (Receiver) {
     QualType T = GetTypeFromParser(Receiver, 0);
     if (!T.isNull()) 
-      if (const ObjCInterfaceType *Interface = T->getAs<ObjCInterfaceType>())
-        CDecl = Interface->getDecl();
+      if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
+        CDecl = Interface->getInterface();
   }
 
   // Add all of the factory methods in this Objective-C class, its protocols,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index fb31003..5ea7af7 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2719,7 +2719,7 @@
 
   QualType T = NewVD->getType();
 
-  if (T->isObjCInterfaceType()) {
+  if (T->isObjCObjectType()) {
     Diag(NewVD->getLocation(), diag::err_statically_allocated_object);
     return NewVD->setInvalidDecl();
   }
@@ -2937,7 +2937,7 @@
     D.setInvalidType();
 
   // Do not allow returning a objc interface by-value.
-  if (R->getAs<FunctionType>()->getResultType()->isObjCInterfaceType()) {
+  if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) {
     Diag(D.getIdentifierLoc(),
          diag::err_object_cannot_be_passed_returned_by_value) << 0
       << R->getAs<FunctionType>()->getResultType();
@@ -4330,7 +4330,7 @@
 
   // Parameter declarators cannot be interface types. All ObjC objects are
   // passed by reference.
-  if (T->isObjCInterfaceType()) {
+  if (T->isObjCObjectType()) {
     Diag(NameLoc,
          diag::err_object_cannot_be_passed_returned_by_value) << 1 << T;
     New->setInvalidDecl();
@@ -6146,7 +6146,7 @@
       }
       if (Record && FDTTy->getDecl()->hasObjectMember())
         Record->setHasObjectMember(true);
-    } else if (FDTy->isObjCInterfaceType()) {
+    } else if (FDTy->isObjCObjectType()) {
       /// A field cannot be an Objective-c object
       Diag(FD->getLocation(), diag::err_statically_allocated_object);
       FD->setInvalidDecl();
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 9ed9692..b166d87 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -142,8 +142,8 @@
         // typedef. If we do, get the underlying class type.
         if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
           QualType T = TDecl->getUnderlyingType();
-          if (T->isObjCInterfaceType()) {
-            if (NamedDecl *IDecl = T->getAs<ObjCInterfaceType>()->getDecl())
+          if (T->isObjCObjectType()) {
+            if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface())
               SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
           }
         }
@@ -210,8 +210,8 @@
                                        LookupOrdinaryName, ForRedeclaration);
   if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(CDeclU)) {
     QualType T = TDecl->getUnderlyingType();
-    if (T->isObjCInterfaceType()) {
-      if (NamedDecl *IDecl = T->getAs<ObjCInterfaceType>()->getDecl()) {
+    if (T->isObjCObjectType()) {
+      if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
         ClassName = IDecl->getIdentifier();
         CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
                                   LookupOrdinaryName, ForRedeclaration);
@@ -1024,15 +1024,15 @@
       //
       // FIXME: Make an extension?
       TypedefDecl *TDD = dyn_cast<TypedefDecl>(PrevDecl);
-      if (!TDD || !isa<ObjCInterfaceType>(TDD->getUnderlyingType())) {
+      if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) {
         Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i];
         Diag(PrevDecl->getLocation(), diag::note_previous_definition);
-      } else if (TDD) {
+      } else {
         // a forward class declaration matching a typedef name of a class refers
         // to the underlying class.
-        if (ObjCInterfaceType * OI =
-              dyn_cast<ObjCInterfaceType>(TDD->getUnderlyingType()))
-          PrevDecl = OI->getDecl();
+        if (const ObjCObjectType *OI =
+              TDD->getUnderlyingType()->getAs<ObjCObjectType>())
+          PrevDecl = OI->getInterface();
       }
     }
     ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
@@ -1532,7 +1532,7 @@
 
     // Methods cannot return interface types. All ObjC objects are
     // passed by reference.
-    if (resultDeclType->isObjCInterfaceType()) {
+    if (resultDeclType->isObjCObjectType()) {
       Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value)
         << 0 << resultDeclType;
       return DeclPtrTy();
@@ -1570,7 +1570,7 @@
                             ArgInfo[i].Name, ArgType, DI,
                             VarDecl::None, VarDecl::None, 0);
 
-    if (ArgType->isObjCInterfaceType()) {
+    if (ArgType->isObjCObjectType()) {
       Diag(ArgInfo[i].NameLoc,
            diag::err_object_cannot_be_passed_returned_by_value)
         << 1 << ArgType;
@@ -1594,7 +1594,7 @@
     else
       // Perform the default array/function conversions (C99 6.7.5.3p[7,8]).
       ArgType = adjustParameterType(ArgType);
-    if (ArgType->isObjCInterfaceType()) {
+    if (ArgType->isObjCObjectType()) {
       Diag(Param->getLocation(),
            diag::err_object_cannot_be_passed_returned_by_value)
       << 1 << ArgType;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 13f44b9..60c7163 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -294,7 +294,7 @@
 bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) {
   DefaultArgumentPromotion(Expr);
 
-  if (Expr->getType()->isObjCInterfaceType() &&
+  if (Expr->getType()->isObjCObjectType() &&
       DiagRuntimeBehavior(Expr->getLocStart(),
         PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
           << Expr->getType() << CT))
@@ -2040,7 +2040,7 @@
     return true;
 
   // Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode.
-  if (LangOpts.ObjCNonFragileABI && exprType->isObjCInterfaceType()) {
+  if (LangOpts.ObjCNonFragileABI && exprType->isObjCObjectType()) {
     Diag(OpLoc, diag::err_sizeof_nonfragile_interface)
       << exprType << isSizeof << ExprRange;
     return true;
@@ -2316,7 +2316,7 @@
     return ExprError();
 
   // Diagnose bad cases where we step over interface counts.
-  if (ResultType->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) {
+  if (ResultType->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
     Diag(LLoc, diag::err_subscript_nonfragile_interface)
       << ResultType << BaseExpr->getSourceRange();
     return ExprError();
@@ -2924,7 +2924,7 @@
       // Handle the following exceptional case PObj->isa.
       if (const ObjCObjectPointerType *OPT =
           BaseType->getAs<ObjCObjectPointerType>()) {
-        if (OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) &&
+        if (OPT->getObjectType()->isObjCId() &&
             MemberName.getAsIdentifierInfo()->isStr("isa"))
           return Owned(new (Context) ObjCIsaExpr(BaseExpr, true, MemberLoc,
                                                  Context.getObjCClassType()));
@@ -3048,8 +3048,7 @@
     }
   }
 
-  // Handle field access to simple records.  This also handles access
-  // to fields of the ObjC 'id' struct.
+  // Handle field access to simple records.
   if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
     if (LookupMemberExprInRecord(*this, R, BaseExpr->getSourceRange(),
                                  RTy, OpLoc, SS))
@@ -3060,14 +3059,14 @@
   // Handle access to Objective-C instance variables, such as "Obj->ivar" and
   // (*Obj).ivar.
   if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
-      (!IsArrow && BaseType->isObjCInterfaceType())) {
+      (!IsArrow && BaseType->isObjCObjectType())) {
     const ObjCObjectPointerType *OPT = BaseType->getAs<ObjCObjectPointerType>();
-    const ObjCInterfaceType *IFaceT =
-      OPT ? OPT->getInterfaceType() : BaseType->getAs<ObjCInterfaceType>();
-    if (IFaceT) {
+    ObjCInterfaceDecl *IDecl =
+      OPT ? OPT->getInterfaceDecl()
+          : BaseType->getAs<ObjCObjectType>()->getInterface();
+    if (IDecl) {
       IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
 
-      ObjCInterfaceDecl *IDecl = IFaceT->getDecl();
       ObjCInterfaceDecl *ClassDeclared;
       ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
 
@@ -3180,7 +3179,8 @@
 
   // Handle the following exceptional case (*Obj).isa.
   if (!IsArrow &&
-      BaseType->isSpecificBuiltinType(BuiltinType::ObjCId) &&
+      BaseType->isObjCObjectType() &&
+      BaseType->getAs<ObjCObjectType>()->isObjCId() &&
       MemberName.getAsIdentifierInfo()->isStr("isa"))
     return Owned(new (Context) ObjCIsaExpr(BaseExpr, false, MemberLoc,
                                            Context.getObjCClassType()));
@@ -5064,7 +5064,7 @@
           return QualType();
       }
       // Diagnose bad cases where we step over interface counts.
-      if (PointeeTy->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) {
+      if (PointeeTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
         Diag(Loc, diag::err_arithmetic_nonfragile_interface)
           << PointeeTy << PExp->getSourceRange();
         return QualType();
@@ -5140,7 +5140,7 @@
       return QualType();
 
     // Diagnose bad cases where we step over interface counts.
-    if (lpointee->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) {
+    if (lpointee->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
       Diag(Loc, diag::err_arithmetic_nonfragile_interface)
         << lpointee << lex->getSourceRange();
       return QualType();
@@ -5907,7 +5907,7 @@
                              << ResType))
       return QualType();
     // Diagnose bad cases where we step over interface counts.
-    else if (PointeeTy->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) {
+    else if (PointeeTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
       Diag(OpLoc, diag::err_arithmetic_nonfragile_interface)
         << PointeeTy << Op->getSourceRange();
       return QualType();
@@ -7021,7 +7021,7 @@
     QualType RetTy = T.getTypePtr()->getAs<FunctionType>()->getResultType();
 
     // Do not allow returning a objc interface by-value.
-    if (RetTy->isObjCInterfaceType()) {
+    if (RetTy->isObjCObjectType()) {
       Diag(ParamInfo.getSourceRange().getBegin(),
            diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
       return;
@@ -7093,7 +7093,7 @@
   QualType RetTy = T->getAs<FunctionType>()->getResultType();
 
   // Do not allow returning a objc interface by-value.
-  if (RetTy->isObjCInterfaceType()) {
+  if (RetTy->isObjCObjectType()) {
     Diag(ParamInfo.getSourceRange().getBegin(),
          diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
   } else if (!RetTy->isDependentType())
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index eb60011..fd4feed 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -722,10 +722,8 @@
 
   // Find the class to which we are sending this message.
   ObjCInterfaceDecl *Class = 0;
-  if (const ObjCInterfaceType *ClassType
-                                 = ReceiverType->getAs<ObjCInterfaceType>())
-    Class = ClassType->getDecl();
-  else {
+  const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>();
+  if (!ClassType || !(Class = ClassType->getInterface())) {
     Diag(Loc, diag::err_invalid_receiver_class_message)
       << ReceiverType;
     return ExprError();
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 06d202d..c6a8b35 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -624,7 +624,7 @@
   } else if (DeclType->isReferenceType()) {
     CheckReferenceType(Entity, IList, DeclType, Index,
                        StructuredList, StructuredIndex);
-  } else if (DeclType->isObjCInterfaceType()) {
+  } else if (DeclType->isObjCObjectType()) {
     SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class)
       << DeclType;
     hadError = true;
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 002c39b..69a3382 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -199,19 +199,16 @@
   // gc'able conforms to NSCopying protocol
   if (getLangOptions().getGCMode() != LangOptions::NonGC &&
       isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign))
-    if (T->isObjCObjectPointerType()) {
-      QualType InterfaceTy = T->getPointeeType();
-      if (const ObjCInterfaceType *OIT =
-          InterfaceTy->getAs<ObjCInterfaceType>()) {
-        ObjCInterfaceDecl *IDecl = OIT->getDecl();
-        if (IDecl)
-          if (ObjCProtocolDecl* PNSCopying =
-              LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc))
-            if (IDecl->ClassImplementsProtocol(PNSCopying, true))
-              Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
-      }
+    if (const ObjCObjectPointerType *ObjPtrTy =
+          T->getAs<ObjCObjectPointerType>()) {
+      ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
+      if (IDecl)
+        if (ObjCProtocolDecl* PNSCopying =
+            LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc))
+          if (IDecl->ClassImplementsProtocol(PNSCopying, true))
+            Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
     }
-  if (T->isObjCInterfaceType())
+  if (T->isObjCObjectType())
     Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object);
 
   DeclContext *DC = cast<DeclContext>(CDecl);
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 04495e5..bf4e7f7 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1543,16 +1543,12 @@
                PTFr->getPointeeType()->isObjCQualifiedClassType()))
             continue;
       }
-      else if (ToType->isObjCObjectPointerType() &&
-               FromType->isObjCObjectPointerType()) {
-        QualType ToInterfaceTy = ToType->getPointeeType();
-        QualType FromInterfaceTy = FromType->getPointeeType();
-        if (const ObjCInterfaceType *OITTo =
-            ToInterfaceTy->getAs<ObjCInterfaceType>())
-          if (const ObjCInterfaceType *OITFr =
-              FromInterfaceTy->getAs<ObjCInterfaceType>())
-            if (OITTo->getDecl() == OITFr->getDecl())
-              continue;
+      else if (const ObjCObjectPointerType *PTTo =
+                 ToType->getAs<ObjCObjectPointerType>()) {
+        if (const ObjCObjectPointerType *PTFr = 
+              FromType->getAs<ObjCObjectPointerType>())
+          if (PTTo->getInterfaceDecl() == PTFr->getInterfaceDecl())
+            continue;
       }
       return false;  
     }
@@ -2141,8 +2137,8 @@
 
     // Objective-C++: If one interface is more specific than the
     // other, it is the better one.
-    const ObjCInterfaceType* FromIface1 = FromPointee1->getAs<ObjCInterfaceType>();
-    const ObjCInterfaceType* FromIface2 = FromPointee2->getAs<ObjCInterfaceType>();
+    const ObjCObjectType* FromIface1 = FromPointee1->getAs<ObjCObjectType>();
+    const ObjCObjectType* FromIface2 = FromPointee2->getAs<ObjCObjectType>();
     if (FromIface1 && FromIface1) {
       if (Context.canAssignObjCInterfaces(FromIface2, FromIface1))
         return ImplicitConversionSequence::Better;
@@ -2348,10 +2344,10 @@
     QualType ToPointee2
       = ToType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
 
-    const ObjCInterfaceType* FromIface1 = FromPointee1->getAs<ObjCInterfaceType>();
-    const ObjCInterfaceType* FromIface2 = FromPointee2->getAs<ObjCInterfaceType>();
-    const ObjCInterfaceType* ToIface1 = ToPointee1->getAs<ObjCInterfaceType>();
-    const ObjCInterfaceType* ToIface2 = ToPointee2->getAs<ObjCInterfaceType>();
+    const ObjCObjectType* FromIface1 = FromPointee1->getAs<ObjCObjectType>();
+    const ObjCObjectType* FromIface2 = FromPointee2->getAs<ObjCObjectType>();
+    const ObjCObjectType* ToIface1 = ToPointee1->getAs<ObjCObjectType>();
+    const ObjCObjectType* ToIface2 = ToPointee2->getAs<ObjCObjectType>();
 
     //   -- conversion of C* to B* is better than conversion of C* to A*,
     if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
@@ -2935,8 +2931,8 @@
 /// TryContextuallyConvertToObjCId - Attempt to contextually convert the
 /// expression From to 'id'.
 ImplicitConversionSequence Sema::TryContextuallyConvertToObjCId(Expr *From) {
-  QualType Ty = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy);
-    return TryImplicitConversion(From, Ty,
+  QualType Ty = Context.getObjCIdType();
+  return TryImplicitConversion(From, Ty,
                                  // FIXME: Are these flags correct?
                                  /*SuppressUserConversions=*/false,
                                  /*AllowExplicit=*/true,
@@ -2946,7 +2942,7 @@
 /// PerformContextuallyConvertToObjCId - Perform a contextual conversion
 /// of the expression From to 'id'.
 bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) {
-  QualType Ty = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy);
+  QualType Ty = Context.getObjCIdType();
   ImplicitConversionSequence ICS = TryContextuallyConvertToObjCId(From);
   if (!ICS.isBad())
     return PerformImplicitConversion(From, Ty, ICS, AA_Converting);
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index d904907..3200288 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -30,7 +30,7 @@
 Sema::OwningStmtResult Sema::ActOnExprStmt(FullExprArg expr) {
   Expr *E = expr->takeAs<Expr>();
   assert(E && "ActOnExprStmt(): missing expression");
-  if (E->getType()->isObjCInterfaceType()) {
+  if (E->getType()->isObjCObjectType()) {
     if (LangOpts.ObjCNonFragileABI)
       Diag(E->getLocEnd(), diag::err_indirection_requires_nonfragile_object)
              << E->getType();
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 733d0e9..88ceeca 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2652,6 +2652,7 @@
   case Type::Record:
   case Type::Enum:
   case Type::ObjCInterface:
+  case Type::ObjCObject:
   case Type::ObjCObjectPointer:
   case Type::UnresolvedUsing:
 #define TYPE(Class, Base)
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index d926b9b..e021663 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -162,9 +162,10 @@
   case DeclSpec::TST_unspecified:
     // "<proto1,proto2>" is an objc qualified ID with a missing id.
     if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
-      Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy,
-                                                (ObjCProtocolDecl**)PQ,
-                                                DS.getNumProtocolQualifiers());
+      Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
+                                         (ObjCProtocolDecl**)PQ,
+                                         DS.getNumProtocolQualifiers());
+      Result = Context.getObjCObjectPointerType(Result);
       break;
     }
     
@@ -299,28 +300,28 @@
     Result = TheSema.GetTypeFromParser(DS.getTypeRep());
 
     if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
-      if (const ObjCInterfaceType *
-            Interface = Result->getAs<ObjCInterfaceType>()) {
-        // It would be nice if protocol qualifiers were only stored with the
-        // ObjCObjectPointerType. Unfortunately, this isn't possible due
-        // to the following typedef idiom (which is uncommon, but allowed):
-        //
-        // typedef Foo<P> T;
-        // static void func() {
-        //   Foo<P> *yy;
-        //   T *zz;
-        // }
-        Result = Context.getObjCInterfaceType(Interface->getDecl(),
-                                              (ObjCProtocolDecl**)PQ,
-                                              DS.getNumProtocolQualifiers());
-      } else if (Result->isObjCIdType())
+      if (const ObjCObjectType *ObjT = Result->getAs<ObjCObjectType>()) {
+        // Silently drop any existing protocol qualifiers.
+        // TODO: determine whether that's the right thing to do.
+        if (ObjT->getNumProtocols())
+          Result = ObjT->getBaseType();
+
+        if (DS.getNumProtocolQualifiers())
+          Result = Context.getObjCObjectType(Result,
+                                             (ObjCProtocolDecl**) PQ,
+                                             DS.getNumProtocolQualifiers());
+      } else if (Result->isObjCIdType()) {
         // id<protocol-list>
-        Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy,
-                        (ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers());
-      else if (Result->isObjCClassType()) {
+        Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
+                                           (ObjCProtocolDecl**) PQ,
+                                           DS.getNumProtocolQualifiers());
+        Result = Context.getObjCObjectPointerType(Result);
+      } else if (Result->isObjCClassType()) {
         // Class<protocol-list>
-        Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy,
-                        (ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers());
+        Result = Context.getObjCObjectType(Context.ObjCBuiltinClassTy,
+                                           (ObjCProtocolDecl**) PQ,
+                                           DS.getNumProtocolQualifiers());
+        Result = Context.getObjCObjectPointerType(Result);
       } else {
         TheSema.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
           << DS.getSourceRange();
@@ -503,7 +504,7 @@
     Qs.removeRestrict();
   }
 
-  assert(!T->isObjCInterfaceType() && "Should build ObjCObjectPointerType");
+  assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
 
   // Build the pointer type.
   return Context.getQualifiedType(Context.getPointerType(T), Qs);
@@ -658,7 +659,7 @@
     // array, accept it as a GNU extension: C99 6.7.2.1p2.
     if (EltTy->getDecl()->hasFlexibleArrayMember())
       Diag(Loc, diag::ext_flexible_array_in_array) << T;
-  } else if (T->isObjCInterfaceType()) {
+  } else if (T->isObjCObjectType()) {
     Diag(Loc, diag::err_objc_array_of_interfaces) << T;
     return QualType();
   }
@@ -1055,13 +1056,9 @@
         D.setInvalidType(true);
         // Build the type anyway.
       }
-      if (getLangOptions().ObjC1 && T->isObjCInterfaceType()) {
-        const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>();
-        T = Context.getObjCObjectPointerType(T,
-                                         const_cast<ObjCProtocolDecl **>(
-                                           OIT->qual_begin()),
-                                         OIT->getNumProtocols(),
-                                         DeclType.Ptr.TypeQuals);
+      if (getLangOptions().ObjC1 && T->getAs<ObjCObjectType>()) {
+        T = Context.getObjCObjectPointerType(T);
+        T = Context.getCVRQualifiedType(T, DeclType.Ptr.TypeQuals);
         break;
       }
       T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
@@ -1400,7 +1397,18 @@
     }
     void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
       TL.setNameLoc(DS.getTypeSpecTypeLoc());
+    }
+    void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
+      // Handle the base type, which might not have been written explicitly.
+      if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
+        TL.setHasBaseTypeAsWritten(false);
+        TL.getBaseLoc().initialize(SourceLocation());
+      } else {
+        TL.setHasBaseTypeAsWritten(true);
+        Visit(TL.getBaseLoc());
+      }
 
+      // Protocol qualifiers.
       if (DS.getProtocolQualifiers()) {
         assert(TL.getNumProtocols() > 0);
         assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
@@ -1415,34 +1423,8 @@
       }
     }
     void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
-      assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
-
       TL.setStarLoc(SourceLocation());
-
-      if (DS.getProtocolQualifiers()) {
-        assert(TL.getNumProtocols() > 0);
-        assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
-        TL.setHasProtocolsAsWritten(true);
-        TL.setLAngleLoc(DS.getProtocolLAngleLoc());
-        TL.setRAngleLoc(DS.getSourceRange().getEnd());
-        for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
-          TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
-
-      } else {
-        assert(TL.getNumProtocols() == 0);
-        TL.setHasProtocolsAsWritten(false);
-        TL.setLAngleLoc(SourceLocation());
-        TL.setRAngleLoc(SourceLocation());
-      }
-
-      // This might not have been written with an inner type.
-      if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
-        TL.setHasBaseTypeAsWritten(false);
-        TL.getBaseTypeLoc().initialize(SourceLocation());
-      } else {
-        TL.setHasBaseTypeAsWritten(true);
-        Visit(TL.getBaseTypeLoc());
-      }
+      Visit(TL.getPointeeLoc());
     }
     void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
       TypeSourceInfo *TInfo = 0;
@@ -1515,10 +1497,6 @@
     void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
       assert(Chunk.Kind == DeclaratorChunk::Pointer);
       TL.setStarLoc(Chunk.Loc);
-      TL.setHasBaseTypeAsWritten(true);
-      TL.setHasProtocolsAsWritten(false);
-      TL.setLAngleLoc(SourceLocation());
-      TL.setRAngleLoc(SourceLocation());
     }
     void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
       assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 3515261..7f756ec 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -2445,31 +2445,15 @@
     return QualType();
 
   QualType Result = TL.getType();
-  if (PointeeType->isObjCInterfaceType() ||
-      PointeeType->isSpecificBuiltinType(BuiltinType::ObjCId)) {
+  if (PointeeType->getAs<ObjCObjectType>()) {
     // A dependent pointer type 'T *' has is being transformed such
     // that an Objective-C class type is being replaced for 'T'. The
     // resulting pointer type is an ObjCObjectPointerType, not a
     // PointerType.
-    ObjCProtocolDecl **Protocols = 0;
-    unsigned NumProtocols = 0;
-
-    if (const ObjCInterfaceType *IFace
-          = PointeeType->getAs<ObjCInterfaceType>()) {
-      Protocols = const_cast<ObjCProtocolDecl**>(IFace->qual_begin());
-      NumProtocols = IFace->getNumProtocols();
-    }
-
-    Result = SemaRef.Context.getObjCObjectPointerType(PointeeType,
-                                                      Protocols,
-                                                      NumProtocols);
+    Result = SemaRef.Context.getObjCObjectPointerType(PointeeType);
     
-    ObjCObjectPointerTypeLoc NewT = TLB.push<ObjCObjectPointerTypeLoc>(Result);   
-    NewT.setStarLoc(TL.getSigilLoc());       
-    NewT.setHasProtocolsAsWritten(false);
-    NewT.setLAngleLoc(SourceLocation());
-    NewT.setRAngleLoc(SourceLocation());
-    NewT.setHasBaseTypeAsWritten(true);
+    ObjCObjectPointerTypeLoc NewT = TLB.push<ObjCObjectPointerTypeLoc>(Result);
+    NewT.setStarLoc(TL.getStarLoc());
     return Result;
   }
                                                             
@@ -3327,6 +3311,17 @@
                                                    ObjCInterfaceTypeLoc TL,
                                                    QualType ObjectType) {
   // ObjCInterfaceType is never dependent.
+  TLB.pushFullCopy(TL);
+  return TL.getType();
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformObjCObjectType(TypeLocBuilder &TLB,
+                                                ObjCObjectTypeLoc TL,
+                                                QualType ObjectType) {
+  // ObjCObjectType is never dependent.
+  TLB.pushFullCopy(TL);
   return TL.getType();
 }
 
@@ -3336,6 +3331,7 @@
                                                ObjCObjectPointerTypeLoc TL,
                                                        QualType ObjectType) {
   // ObjCObjectPointerType is never dependent.
+  TLB.pushFullCopy(TL);
   return TL.getType();
 }