This patch includes a conceptually simple, but very intrusive/pervasive change. 

The idea is to segregate Objective-C "object" pointers from general C pointers (utilizing the recently added ObjCObjectPointerType). The fun starts in Sema::GetTypeForDeclarator(), where "SomeInterface *" is now represented by a single AST node (rather than a PointerType whose Pointee is an ObjCInterfaceType). Since a significant amount of code assumed ObjC object pointers where based on C pointers/structs, this patch is very tedious. It should also explain why it is hard to accomplish this in smaller, self-contained patches.

This patch does most of the "heavy lifting" related to moving from PointerType->ObjCObjectPointerType. It doesn't include all potential "cleanups". The good news is additional cleanups can be done later (some are noted in the code). This patch is so large that I didn't want to include any changes that are purely aesthetic.

By making the ObjC types truly built-in, they are much easier to work with (and require fewer "hacks"). For example, there is no need for ASTContext::isObjCIdStructType() or ASTContext::isObjCClassStructType()! We believe this change (and the follow-up cleanups) will pay dividends over time. 

Given the amount of code change, I do expect some fallout from this change (though it does pass all of the clang tests). If you notice any problems, please let us know asap! Thanks.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75314 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 78c3b78..fd368c4 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -22,6 +22,9 @@
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
 
+ObjCInterfaceType *ObjCObjectPointerType::IdInterfaceT;
+ObjCInterfaceType *ObjCObjectPointerType::ClassInterfaceT;
+
 bool QualType::isConstant(ASTContext &Ctx) const {
   if (isConstQualified())
     return true;
@@ -295,6 +298,15 @@
   return dyn_cast_or_null<FunctionProtoType>(getAsFunctionType());
 }
 
+QualType Type::getPointeeType() const {
+  if (const PointerType *PT = getAsPointerType())
+    return PT->getPointeeType();
+  if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType())
+    return OPT->getPointeeType();
+  if (const BlockPointerType *BPT = getAsBlockPointerType())
+    return BPT->getPointeeType();
+  return QualType();
+}
 
 const PointerType *Type::getAsPointerType() const {
   // If this is directly a pointer type, return it.
@@ -609,6 +621,14 @@
   return 0;
 }
 
+const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const {
+  if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+    if (OPT->getInterfaceType())
+      return OPT;
+  }
+  return 0;
+}
+
 const TemplateTypeParmType *Type::getAsTemplateTypeParmType() const {
   // There is no sugar for template type parameters, so just return
   // the canonical type pointer if it is the right class.
@@ -1016,16 +1036,18 @@
 }
 
 void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID,
-                                    const ObjCInterfaceDecl *Decl,
-                                    ObjCProtocolDecl **protocols,
+                                    QualType OIT, ObjCProtocolDecl **protocols,
                                     unsigned NumProtocols) {
-  ID.AddPointer(Decl);
+  ID.AddPointer(OIT.getAsOpaquePtr());
   for (unsigned i = 0; i != NumProtocols; i++)
     ID.AddPointer(protocols[i]);
 }
 
 void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) {
-  Profile(ID, getDecl(), &Protocols[0], getNumProtocols());
+  if (getNumProtocols())
+    Profile(ID, getPointeeType(), &Protocols[0], getNumProtocols());
+  else
+    Profile(ID, getPointeeType(), 0, 0);
 }
 
 void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
@@ -1663,6 +1685,14 @@
     InnerString = MyString + ' ' + InnerString;
 }
 
+bool ObjCInterfaceType::isObjCIdInterface() const {
+  return this == ObjCObjectPointerType::getIdInterface();
+}
+
+bool ObjCInterfaceType::isObjCClassInterface() const {
+  return this == ObjCObjectPointerType::getClassInterface();
+}  
+
 void ObjCInterfaceType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
   if (!InnerString.empty())    // Prefix the basic type, e.g. 'typedefname X'.
     InnerString = ' ' + InnerString;
@@ -1671,15 +1701,7 @@
 
 void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString, 
                                                 const PrintingPolicy &Policy) const {
-  if (!InnerString.empty())    // Prefix the basic type, e.g. 'typedefname X'.
-    InnerString = ' ' + InnerString;
-
-  std::string ObjCQIString;
-  
-  if (getDecl())
-    ObjCQIString = getDecl()->getNameAsString();
-  else
-    ObjCQIString = "id";
+  std::string ObjCQIString = getInterfaceType()->getDecl()->getNameAsString();
 
   if (!qual_empty()) {
     ObjCQIString += '<';
@@ -1690,6 +1712,11 @@
     }
     ObjCQIString += '>';
   }
+  if (!isObjCIdType() && !isObjCQualifiedIdType())
+    ObjCQIString += " *"; // Don't forget the implicit pointer.
+  else if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
+    InnerString = ' ' + InnerString;
+
   InnerString = ObjCQIString + InnerString;
 }