[cfe-commits] r45263 - in /cfe/trunk: AST/ASTContext.cpp AST/Decl.cpp Sema/SemaDeclObjC.cpp include/clang/AST/DeclObjC.h test/Sema/objc-comptypes-1.m

Fariborz Jahanian fjahanian at apple.com
Thu Dec 20 11:24:12 PST 2007


Author: fjahanian
Date: Thu Dec 20 13:24:10 2007
New Revision: 45263

URL: http://llvm.org/viewvc/llvm-project?rev=45263&view=rev
Log:
Patch to do type-checking for objctive-c's object types.
More is yet to come.

Added:
    cfe/trunk/test/Sema/objc-comptypes-1.m
Modified:
    cfe/trunk/AST/ASTContext.cpp
    cfe/trunk/AST/Decl.cpp
    cfe/trunk/Sema/SemaDeclObjC.cpp
    cfe/trunk/include/clang/AST/DeclObjC.h

Modified: cfe/trunk/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/ASTContext.cpp?rev=45263&r1=45262&r2=45263&view=diff

==============================================================================
--- cfe/trunk/AST/ASTContext.cpp (original)
+++ cfe/trunk/AST/ASTContext.cpp Thu Dec 20 13:24:10 2007
@@ -1273,19 +1273,21 @@
   // match id<P..> with an 'id' type in all cases.
   if (const PointerType *PT = lhs->getAsPointerType()) {
     QualType PointeeTy = PT->getPointeeType();
-    if (isObjcIdType(PointeeTy))
+    if (isObjcIdType(PointeeTy) || PointeeTy->isVoidType())
       return true;
         
   }
   else if (const PointerType *PT = rhs->getAsPointerType()) {
     QualType PointeeTy = PT->getPointeeType();
-    if (isObjcIdType(PointeeTy))
+    if (isObjcIdType(PointeeTy) || PointeeTy->isVoidType())
       return true;
     
   }
   
   ObjcQualifiedInterfaceType *lhsQI = 0;
   ObjcQualifiedInterfaceType *rhsQI = 0;
+  ObjcInterfaceDecl *lhsID = 0;
+  ObjcInterfaceDecl *rhsID = 0;
   ObjcQualifiedIdType *lhsQID = dyn_cast<ObjcQualifiedIdType>(lhs);
   ObjcQualifiedIdType *rhsQID = dyn_cast<ObjcQualifiedIdType>(rhs);
   
@@ -1296,8 +1298,14 @@
       rhsQI = 
         dyn_cast<ObjcQualifiedInterfaceType>(
           rtype.getCanonicalType().getTypePtr());
+      if (!rhsQI) {
+        ObjcInterfaceType *IT = dyn_cast<ObjcInterfaceType>(
+                                  rtype.getCanonicalType().getTypePtr());
+        if (IT)
+          rhsID = IT->getDecl();
+      }
     }
-    if (!rhsQI && !rhsQID)
+    if (!rhsQI && !rhsQID && !rhsID)
       return false;
     
     for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) {
@@ -1309,10 +1317,14 @@
         numRhsProtocols = rhsQI->getNumProtocols();
         rhsProtoList = rhsQI->getReferencedProtocols();
       }
-      else {
+      else if (rhsQID) {
         numRhsProtocols = rhsQID->getNumProtocols();
         rhsProtoList = rhsQID->getReferencedProtocols();
       }
+      else {
+        numRhsProtocols = rhsID->getNumIntfRefProtocols();
+        rhsProtoList = rhsID->getReferencedProtocols();
+      }
       for (unsigned j = 0; j < numRhsProtocols; j++) {
         ObjcProtocolDecl *rhsProto = rhsProtoList[j];
         if (lhsProto == rhsProto) {
@@ -1331,19 +1343,31 @@
       lhsQI = 
       dyn_cast<ObjcQualifiedInterfaceType>(
         ltype.getCanonicalType().getTypePtr());
+      if (!lhsQI) {
+        ObjcInterfaceType *IT = dyn_cast<ObjcInterfaceType>(
+                                  ltype.getCanonicalType().getTypePtr());
+        if (IT)
+          lhsID = IT->getDecl();
+      }
     }
-    if (!lhsQI && !lhsQID)
+    if (!lhsQI && !lhsQID && !lhsID)
       return false;
+    
     unsigned numLhsProtocols;
     ObjcProtocolDecl **lhsProtoList;
     if (lhsQI) {
       numLhsProtocols = lhsQI->getNumProtocols();
       lhsProtoList = lhsQI->getReferencedProtocols();
     }
-    else {
+    else if (lhsQID) {
       numLhsProtocols = lhsQID->getNumProtocols();
       lhsProtoList = lhsQID->getReferencedProtocols();
     }
+    else {
+      numLhsProtocols = lhsID->getNumIntfRefProtocols();
+      lhsProtoList = lhsID->getReferencedProtocols();
+    }
+    
     for (unsigned i =0; i < numLhsProtocols; i++) {
       bool match = false;
       ObjcProtocolDecl *lhsProto = lhsProtoList[i];

Modified: cfe/trunk/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Decl.cpp?rev=45263&r1=45262&r2=45263&view=diff

==============================================================================
--- cfe/trunk/AST/Decl.cpp (original)
+++ cfe/trunk/AST/Decl.cpp Thu Dec 20 13:24:10 2007
@@ -516,7 +516,7 @@
   if (getNumReferencedProtocols() > 0) {
     ObjcProtocolDecl **RefPDecl = getReferencedProtocols();
     
-    for (int i = 0; i < getNumReferencedProtocols(); i++) {
+    for (unsigned i = 0; i < getNumReferencedProtocols(); i++) {
       if ((MethodDecl = RefPDecl[i]->getInstanceMethod(Sel)))
         return MethodDecl;
     }
@@ -535,7 +535,7 @@
   if (getNumReferencedProtocols() > 0) {
     ObjcProtocolDecl **RefPDecl = getReferencedProtocols();
     
-    for (int i = 0; i < getNumReferencedProtocols(); i++) {
+    for(unsigned i = 0; i < getNumReferencedProtocols(); i++) {
       if ((MethodDecl = RefPDecl[i]->getClassMethod(Sel)))
         return MethodDecl;
     }

Modified: cfe/trunk/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDeclObjC.cpp?rev=45263&r1=45262&r2=45263&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/Sema/SemaDeclObjC.cpp Thu Dec 20 13:24:10 2007
@@ -135,7 +135,7 @@
         Diag(ClassLoc, diag::warn_undef_protocolref,
              ProtocolNames[i]->getName(),
              ClassName->getName());
-      IDecl->setIntfRefProtocols((int)i, RefPDecl);
+      IDecl->setIntfRefProtocols(i, RefPDecl);
     }
     IDecl->setLocEnd(EndProtoLoc);
   }
@@ -216,7 +216,7 @@
         Diag(ProtocolLoc, diag::warn_undef_protocolref,
              ProtoRefNames[i]->getName(),
              ProtocolName->getName());
-      PDecl->setReferencedProtocols((int)i, RefPDecl);
+      PDecl->setReferencedProtocols(i, RefPDecl);
     }
     PDecl->setLocEnd(EndProtoLoc);
   }
@@ -300,7 +300,7 @@
              ProtoRefNames[i]->getName(),
              CategoryName->getName());
       }
-      CDecl->setCatReferencedProtocols((int)i, RefPDecl);
+      CDecl->setCatReferencedProtocols(i, RefPDecl);
     }
     CDecl->setLocEnd(EndProtoLoc);
   }
@@ -481,7 +481,7 @@
   }
   // Check on this protocols's referenced protocols, recursively
   ObjcProtocolDecl** RefPDecl = PDecl->getReferencedProtocols();
-  for (int i = 0; i < PDecl->getNumReferencedProtocols(); i++)
+  for (unsigned i = 0; i < PDecl->getNumReferencedProtocols(); i++)
     CheckProtocolMethodDefs(RefPDecl[i], IncompleteImpl, InsMap, ClsMap);
 }
 
@@ -521,7 +521,7 @@
   // Check the protocol list for unimplemented methods in the @implementation
   // class.
   ObjcProtocolDecl** protocols = IDecl->getReferencedProtocols();
-  for (int i = 0; i < IDecl->getNumIntfRefProtocols(); i++)
+  for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++)
     CheckProtocolMethodDefs(protocols[i], IncompleteImpl, InsMap, ClsMap);
 
   if (IncompleteImpl)
@@ -567,7 +567,7 @@
   // Check the protocol list for unimplemented methods in the @implementation
   // class.
   ObjcProtocolDecl** protocols = CatClassDecl->getReferencedProtocols();
-  for (int i = 0; i < CatClassDecl->getNumReferencedProtocols(); i++) {
+  for (unsigned i = 0; i < CatClassDecl->getNumReferencedProtocols(); i++) {
     ObjcProtocolDecl* PDecl = protocols[i];
     CheckProtocolMethodDefs(PDecl, IncompleteImpl, InsMap, ClsMap);
   }

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=45263&r1=45262&r2=45263&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Thu Dec 20 13:24:10 2007
@@ -186,7 +186,7 @@
   
   /// Protocols referenced in interface header declaration
   ObjcProtocolDecl **ReferencedProtocols;  // Null if none
-  int NumReferencedProtocols;  // -1 if none
+  unsigned NumReferencedProtocols;  // 0 if none
   
   /// Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
   ObjcIvarDecl **Ivars;   // Null if not defined.
@@ -217,7 +217,7 @@
                     IdentifierInfo *Id, bool FD = false, 
                     bool isInternal = false)
     : TypeDecl(ObjcInterface, atLoc, Id, 0), SuperClass(0),
-      ReferencedProtocols(0), NumReferencedProtocols(-1), Ivars(0), 
+      ReferencedProtocols(0), NumReferencedProtocols(0), Ivars(0), 
       NumIvars(-1),
       InstanceMethods(0), NumInstanceMethods(-1), 
       ClassMethods(0), NumClassMethods(-1),
@@ -239,7 +239,7 @@
   ObjcProtocolDecl **getReferencedProtocols() const { 
     return ReferencedProtocols; 
   }
-  int getNumIntfRefProtocols() const { return NumReferencedProtocols; }
+  unsigned getNumIntfRefProtocols() const { return NumReferencedProtocols; }
   
   int getNumInstanceVariables() const { return NumIvars; }
   
@@ -273,7 +273,7 @@
   bool isForwardDecl() const { return ForwardDecl; }
   void setForwardDecl(bool val) { ForwardDecl = val; }
   
-  void setIntfRefProtocols(int idx, ObjcProtocolDecl *OID) {
+  void setIntfRefProtocols(unsigned idx, ObjcProtocolDecl *OID) {
     assert((idx < NumReferencedProtocols) && "index out of range");
     ReferencedProtocols[idx] = OID;
   }
@@ -394,7 +394,7 @@
 class ObjcProtocolDecl : public NamedDecl {
   /// referenced protocols
   ObjcProtocolDecl **ReferencedProtocols;  // Null if none
-  int NumReferencedProtocols;  // -1 if none
+  unsigned NumReferencedProtocols;  // 0 if none
   
   /// protocol instance methods
   ObjcMethodDecl **InstanceMethods;  // Null if not defined
@@ -412,7 +412,7 @@
   ObjcProtocolDecl(SourceLocation L, unsigned numRefProtos,
                    IdentifierInfo *Id, bool FD = false)
     : NamedDecl(ObjcProtocol, L, Id), 
-      ReferencedProtocols(0), NumReferencedProtocols(-1),
+      ReferencedProtocols(0), NumReferencedProtocols(0),
       InstanceMethods(0), NumInstanceMethods(-1), 
       ClassMethods(0), NumClassMethods(-1),
       isForwardProtoDecl(FD) {
@@ -430,7 +430,7 @@
                   ObjcMethodDecl **clsMethods, unsigned numClsMembers,
                   SourceLocation AtEndLoc);
   
-  void setReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
+  void setReferencedProtocols(unsigned idx, ObjcProtocolDecl *OID) {
     assert((idx < NumReferencedProtocols) && "index out of range");
     ReferencedProtocols[idx] = OID;
   }
@@ -438,7 +438,7 @@
   ObjcProtocolDecl** getReferencedProtocols() const { 
     return ReferencedProtocols; 
   }
-  int getNumReferencedProtocols() const { return NumReferencedProtocols; }
+  unsigned getNumReferencedProtocols() const { return NumReferencedProtocols; }
   int getNumInstanceMethods() const { return NumInstanceMethods; }
   int getNumClassMethods() const { return NumClassMethods; }
 
@@ -587,7 +587,7 @@
   
   /// referenced protocols in this category
   ObjcProtocolDecl **ReferencedProtocols;  // Null if none
-  int NumReferencedProtocols;  // -1 if none
+  unsigned NumReferencedProtocols;  // 0 if none
   
   /// category instance methods
   ObjcMethodDecl **InstanceMethods;  // Null if not defined
@@ -605,7 +605,7 @@
 public:
   ObjcCategoryDecl(SourceLocation L, unsigned numRefProtocol,IdentifierInfo *Id)
     : NamedDecl(ObjcCategory, L, Id),
-      ClassInterface(0), ReferencedProtocols(0), NumReferencedProtocols(-1),
+      ClassInterface(0), ReferencedProtocols(0), NumReferencedProtocols(0),
       InstanceMethods(0), NumInstanceMethods(-1),
       ClassMethods(0), NumClassMethods(-1),
       NextClassCategory(0) {
@@ -620,7 +620,7 @@
   ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; }
   void setClassInterface(ObjcInterfaceDecl *IDecl) { ClassInterface = IDecl; }
   
-  void setCatReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
+  void setCatReferencedProtocols(unsigned idx, ObjcProtocolDecl *OID) {
     assert((idx < NumReferencedProtocols) && "index out of range");
     ReferencedProtocols[idx] = OID;
   }
@@ -628,7 +628,7 @@
   ObjcProtocolDecl **getReferencedProtocols() const { 
     return ReferencedProtocols; 
   }
-  int getNumReferencedProtocols() const { return NumReferencedProtocols; }
+  unsigned getNumReferencedProtocols() const { return NumReferencedProtocols; }
   int getNumInstanceMethods() const { return NumInstanceMethods; }
   int getNumClassMethods() const { return NumClassMethods; }
 

Added: cfe/trunk/test/Sema/objc-comptypes-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/objc-comptypes-1.m?rev=45263&view=auto

==============================================================================
--- cfe/trunk/test/Sema/objc-comptypes-1.m (added)
+++ cfe/trunk/test/Sema/objc-comptypes-1.m Thu Dec 20 13:24:10 2007
@@ -0,0 +1,82 @@
+// RUN: clang -fsyntax-only -verify %s
+
+#include <objc/objc.h>
+
+extern void foo();
+
+ at protocol MyProtocol
+- (void) foo;
+ at end
+
+ at interface MyClass
+ at end
+
+ at interface MyOtherClass <MyProtocol>
+- (void) foo;
+ at end
+
+int main()
+{
+  id obj = nil;
+  id<MyProtocol> obj_p = nil;
+  MyClass *obj_c = nil;
+  MyOtherClass *obj_cp = nil;
+  Class obj_C = Nil;
+
+  /* Assigning to an 'id' variable should never
+     generate a warning.  */
+  obj = obj_p;  /* Ok  */
+  obj = obj_c;  /* Ok  */
+  obj = obj_cp; /* Ok  */
+  obj = obj_C;  /* Ok  */
+  
+  /* Assigning to a 'MyClass *' variable should always generate a
+     warning, unless done from an 'id'.  */
+  obj_c = obj;    /* Ok */
+  obj_c = obj_C;  // expected-warning {{incompatible pointer types assigning 'Class' to 'MyClass *'}}
+
+  /* Assigning to an 'id<MyProtocol>' variable should generate a
+     warning if done from a 'MyClass *' (which doesn't implement
+     MyProtocol), but not from an 'id' or from a 'MyOtherClass *'
+     (which implements MyProtocol).  */
+  obj_p = obj;    /* Ok */
+  obj_p = obj_c;  // expected-error {{incompatible types assigning 'MyClass *' to 'id<MyProtocol>'}}
+  obj_p = obj_cp; /* Ok  */
+  obj_p = obj_C;  // expected-error {{incompatible types assigning 'Class' to 'id<MyProtocol>'}}
+
+  /* Assigning to a 'MyOtherClass *' variable should always generate
+     a warning, unless done from an 'id' or an 'id<MyProtocol>' (since
+     MyOtherClass implements MyProtocol).  */
+  obj_cp = obj;    /* Ok */
+  obj_cp = obj_p;  /* Ok */
+  obj_cp = obj_C;  // expected-warning {{incompatible pointer types assigning 'Class' to 'MyOtherClass *'}}
+
+  /* Any comparison involving an 'id' must be without warnings.  */
+  if (obj == obj_p) foo() ;  /* Ok  */ /*Bogus warning here in 2.95.4*/
+  if (obj_p == obj) foo() ;  /* Ok  */
+  if (obj == obj_c) foo() ;  /* Ok  */
+  if (obj_c == obj) foo() ;  /* Ok  */
+  if (obj == obj_cp) foo() ; /* Ok  */
+  if (obj_cp == obj) foo() ; /* Ok  */
+  if (obj == obj_C) foo() ;  /* Ok  */
+  if (obj_C == obj) foo() ;  /* Ok  */
+
+  /* Any comparison between 'MyClass *' and anything which is not an 'id'
+     must generate a warning.  */
+  if (obj_p == obj_c) foo() ; // expected-error {{invalid operands to binary expression ('id<MyProtocol>' and 'MyClass *')}}
+  if (obj_c == obj_C) foo() ;  // expected-warning {{comparison of distinct pointer types ('MyClass *' and 'Class')}}
+  if (obj_C == obj_c) foo() ;  // expected-warning {{comparison of distinct pointer types ('Class' and 'MyClass *')}} 
+
+  /* Any comparison between 'MyOtherClass *' (which implements
+     MyProtocol) and an 'id' implementing MyProtocol are Ok.  */
+  if (obj_cp == obj_p) foo() ; /* Ok */
+  if (obj_p == obj_cp) foo() ; /* Ok */
+
+
+  if (obj_p == obj_C) foo() ; // expected-error {{invalid operands to binary expression ('id<MyProtocol>' and 'Class')}} 
+  if (obj_C == obj_p) foo() ; // expected-error {{invalid operands to binary expression ('Class' and 'id<MyProtocol>')}} 
+  if (obj_cp == obj_C) foo() ; // expected-warning {{comparison of distinct pointer types ('MyOtherClass *' and 'Class')}} 
+  if (obj_C == obj_cp) foo() ; // expected-warning {{comparison of distinct pointer types ('Class' and 'MyOtherClass *')}}
+
+  return 0;
+}





More information about the cfe-commits mailing list