Patch to implemented objective-c's dynamic object pointer qualified with
the protocol list (id<P,...> types).



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45121 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp
index 4351b89..92b691e 100644
--- a/AST/ASTContext.cpp
+++ b/AST/ASTContext.cpp
@@ -49,6 +49,7 @@
   
   unsigned NumTagStruct = 0, NumTagUnion = 0, NumTagEnum = 0, NumTagClass = 0;
   unsigned NumObjcInterfaces = 0, NumObjcQualifiedInterfaces = 0;
+  unsigned NumObjcQualifiedIds = 0;
   
   for (unsigned i = 0, e = Types.size(); i != e; ++i) {
     Type *T = Types[i];
@@ -83,6 +84,8 @@
       ++NumObjcInterfaces;
     else if (isa<ObjcQualifiedInterfaceType>(T))
       ++NumObjcQualifiedInterfaces;
+    else if (isa<ObjcQualifiedIdType>(T))
+      ++NumObjcQualifiedIds;
     else {
       QualType(T, 0).dump();
       assert(0 && "Unknown type!");
@@ -106,6 +109,8 @@
   fprintf(stderr, "    %d interface types\n", NumObjcInterfaces);
   fprintf(stderr, "    %d protocol qualified interface types\n",
           NumObjcQualifiedInterfaces);
+  fprintf(stderr, "    %d protocol qualified id types\n",
+          NumObjcQualifiedIds);
   fprintf(stderr, "Total bytes = %d\n", int(NumBuiltin*sizeof(BuiltinType)+
     NumPointer*sizeof(PointerType)+NumArray*sizeof(ArrayType)+
     NumComplex*sizeof(ComplexType)+NumVector*sizeof(VectorType)+
@@ -677,7 +682,7 @@
   if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
   
   QualType Canonical = Decl->getUnderlyingType().getCanonicalType();
-  Decl->TypeForDecl = new TypedefType(Decl, Canonical);
+  Decl->TypeForDecl = new TypedefType(Type::TypeName, Decl, Canonical);
   Types.push_back(Decl->TypeForDecl);
   return QualType(Decl->TypeForDecl, 0);
 }
@@ -713,6 +718,29 @@
   return QualType(QType, 0);
 }
 
+/// getObjcQualifiedIdType - Return a 
+/// getObjcQualifiedIdType type for the given interface decl and
+/// the conforming protocol list.
+QualType ASTContext::getObjcQualifiedIdType(TypedefDecl *Decl,
+                                            ObjcProtocolDecl **Protocols, 
+                                            unsigned NumProtocols) {
+  llvm::FoldingSetNodeID ID;
+  ObjcQualifiedIdType::Profile(ID, Protocols, NumProtocols);
+  
+  void *InsertPos = 0;
+  if (ObjcQualifiedIdType *QT =
+      ObjcQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos))
+    return QualType(QT, 0);
+  
+  // No Match;
+  QualType Canonical = Decl->getUnderlyingType().getCanonicalType();
+  ObjcQualifiedIdType *QType =
+  new ObjcQualifiedIdType(Decl, Canonical, Protocols, NumProtocols);
+  Types.push_back(QType);
+  ObjcQualifiedIdTypes.InsertNode(QType, InsertPos);
+  return QualType(QType, 0);
+}
+
 /// getTypeOfExpr - Unlike many "get<Type>" functions, we can't unique
 /// TypeOfExpr AST's (since expression's are never shared). For example,
 /// multiple declarations that refer to "typeof(x)" all contain different
@@ -1043,7 +1071,13 @@
     }
     
     S += encoding;
-  } else if (const PointerType *PT = T->getAsPointerType()) {
+  }
+  else if (const ObjcQualifiedIdType *QIT = dyn_cast<ObjcQualifiedIdType>(T)) {
+    // Treat id<P...> same as 'id' for encoding purposes.
+    return getObjcEncodingForType(QIT->getDecl()->getUnderlyingType(), S);
+    
+  }
+  else if (const PointerType *PT = T->getAsPointerType()) {
     QualType PointeeTy = PT->getPointeeType();
     if (isObjcIdType(PointeeTy) || PointeeTy->isObjcInterfaceType()) {
       S += '@';
@@ -1221,6 +1255,13 @@
   return true;
 }
 
+// TODO: id<P1,...> vs. id<P,...>
+#if 0
+bool ASTContext::QualifiedIdTypesAreCompatible(QualType lhs, 
+                                                      QualType rhs) {
+}
+#endif
+
 bool ASTContext::vectorTypesAreCompatible(QualType lhs, QualType rhs) {
   const VectorType *lVector = lhs->getAsVectorType();
   const VectorType *rVector = rhs->getAsVectorType();
diff --git a/AST/Type.cpp b/AST/Type.cpp
index b1da04b..63f3589 100644
--- a/AST/Type.cpp
+++ b/AST/Type.cpp
@@ -539,6 +539,17 @@
   Profile(ID, &Protocols[0], getNumProtocols());
 }
 
+void ObjcQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID,
+                                         ObjcProtocolDecl **protocols, 
+                                         unsigned NumProtocols) {
+  for (unsigned i = 0; i != NumProtocols; i++)
+    ID.AddPointer(protocols[i]);
+}
+
+void ObjcQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID) {
+  Profile(ID, &Protocols[0], getNumProtocols());
+}
+
 /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
 /// potentially looking through *all* consequtive typedefs.  This returns the
 /// sum of the type qualifiers, so if you have:
@@ -780,6 +791,22 @@
   InnerString = ObjcQIString + InnerString;
 }
 
+void ObjcQualifiedIdType::getAsStringInternal(
+                                              std::string &InnerString) const {
+  if (!InnerString.empty())    // Prefix the basic type, e.g. 'typedefname X'.
+    InnerString = ' ' + InnerString;
+  std::string ObjcQIString = "id";
+  ObjcQIString += '<';
+  int num = getNumProtocols();
+  for (int i = 0; i < num; i++) {
+    ObjcQIString += getProtocols(i)->getName();
+    if (i < num-1)
+      ObjcQIString += ',';
+  }
+  ObjcQIString += '>';
+  InnerString = ObjcQIString + InnerString;
+}
+
 void TagType::getAsStringInternal(std::string &InnerString) const {
   if (!InnerString.empty())    // Prefix the basic type, e.g. 'typedefname X'.
     InnerString = ' ' + InnerString;
diff --git a/AST/TypeSerialization.cpp b/AST/TypeSerialization.cpp
index 10965c2..a3b99ed 100644
--- a/AST/TypeSerialization.cpp
+++ b/AST/TypeSerialization.cpp
@@ -224,7 +224,7 @@
   std::vector<Type*>& Types = 
     const_cast<std::vector<Type*>&>(Context.getTypes());
   
-  TypedefType* T = new TypedefType(NULL,QualType::ReadVal(D));
+  TypedefType* T = new TypedefType(Type::TypeName, NULL,QualType::ReadVal(D));
   Types.push_back(T);
   
   D.ReadPtr(T->Decl); // May be backpatched.