More work to integrate newly added ObjCQualifiedClassType into the type system.

This is necessary 'plumbing' to fix <rdar://problem/6497631> Message lookup is sometimes different than gcc's.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65248 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 5dc2c31..cb34c77 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -270,7 +270,7 @@
     TypeName, Tagged, ExtQual,
     TemplateTypeParm, ClassTemplateSpecialization,
     ObjCInterface, ObjCQualifiedInterface,
-    ObjCQualifiedId,
+    ObjCQualifiedId, ObjCQualifiedClass,
     TypeOfExp, TypeOfTyp, // GNU typeof extension.
     BlockPointer,          // C extension
     FixedWidthInt
@@ -1758,7 +1758,7 @@
   llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
     
   ObjCQualifiedClassType(ObjCProtocolDecl **Protos, unsigned NumP)
-    : Type(ObjCQualifiedId, QualType()/*these are always canonical*/,
+    : Type(ObjCQualifiedClass, QualType()/*these are always canonical*/,
            /*Dependent=*/false), 
   Protocols(Protos, Protos+NumP) { }
   friend class ASTContext;  // ASTContext creates these.
@@ -1785,7 +1785,7 @@
                       ObjCProtocolDecl **protocols, unsigned NumProtocols);
     
   static bool classof(const Type *T) { 
-    return T->getTypeClass() == ObjCQualifiedId; 
+    return T->getTypeClass() == ObjCQualifiedClass; 
   }
   static bool classof(const ObjCQualifiedClassType *) { return true; }
     
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index cdd61cd..605f46b 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2408,7 +2408,7 @@
 /// to struct), Interface* (pointer to ObjCInterfaceType) and id<P> (qualified
 /// ID type).
 bool ASTContext::isObjCObjectPointerType(QualType Ty) const {
-  if (Ty->isObjCQualifiedIdType())
+  if (Ty->isObjCQualifiedIdType() || Ty->isObjCQualifiedClassType())
     return true;
   
   // Blocks are objects.
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index ba8b463..065b626 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -693,7 +693,8 @@
          isa<BlockPointerType>(CanonicalType) ||
          isa<MemberPointerType>(CanonicalType) ||
          isa<ComplexType>(CanonicalType) ||
-         isa<ObjCQualifiedIdType>(CanonicalType);
+         isa<ObjCQualifiedIdType>(CanonicalType) ||
+         isa<ObjCQualifiedClassType>(CanonicalType);
 }
 
 /// \brief Determines whether the type is a C++ aggregate type or C
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index a385d8c..47ac79f 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -290,6 +290,7 @@
   }
 
   case Type::ObjCQualifiedId:
+  case Type::ObjCQualifiedClass:
     // Protocols don't influence the LLVM type.
     return ConvertTypeRecursive(Context.getObjCIdType());
 
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index c390f76..b17f7bc 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2734,7 +2734,9 @@
 
   // C99 6.5.16.1p1: the left operand is a pointer and the right is
   // a null pointer constant.
-  if ((lhsType->isPointerType() || lhsType->isObjCQualifiedIdType() ||
+  if ((lhsType->isPointerType() || 
+       lhsType->isObjCQualifiedIdType() || 
+       lhsType->isObjCQualifiedClassType() ||
        lhsType->isBlockPointerType())
       && rExpr->isNullPointerConstant(Context)) {
     ImpCastExprToType(rExpr, lhsType);
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 19dc382..afa0255 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -391,7 +391,8 @@
   // We allow sending a message to a qualified ID ("id<foo>"), which is ok as 
   // long as one of the protocols implements the selector (if not, warn).
   if (ObjCQualifiedIdType *QIT = dyn_cast<ObjCQualifiedIdType>(ReceiverCType)) {
-    // Search protocols
+    // Search protocols for instance methods.
+    ReceiverCType.dump();
     for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
       ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
       if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
@@ -400,6 +401,18 @@
     if (!Method)
       Diag(lbrac, diag::warn_method_not_found_in_protocol)
         << Sel << RExpr->getSourceRange();
+  // Check for GCC extension "Class<foo>".
+  } else if (ObjCQualifiedClassType *QIT = 
+               dyn_cast<ObjCQualifiedClassType>(ReceiverCType)) {
+    // Search protocols for class methods.
+    for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
+      ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
+      if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
+        break;
+    }
+    if (!Method)
+      Diag(lbrac, diag::warn_method_not_found_in_protocol)
+        << Sel << RExpr->getSourceRange();
   } else if (const ObjCInterfaceType *OCIReceiver = 
                 ReceiverCType->getAsPointerToObjCInterfaceType()) {
     // We allow sending a message to a pointer to an interface (an object).