[cfe-commits] r129142 - in /cfe/trunk: include/clang/AST/DeclObjC.h lib/AST/ASTContext.cpp test/CodeGenObjCXX/references.mm test/SemaObjC/comptypes-4.m test/SemaObjC/unqualified-to-qualified-class-warn.m test/SemaObjCXX/references.mm

Fariborz Jahanian fjahanian at apple.com
Fri Apr 8 11:25:29 PDT 2011


Author: fjahanian
Date: Fri Apr  8 13:25:29 2011
New Revision: 129142

URL: http://llvm.org/viewvc/llvm-project?rev=129142&view=rev
Log:
Warn for any kind of initialization if initializer does not
implement lhs's protocols. // rdar://9091389.
 

Added:
    cfe/trunk/test/SemaObjC/unqualified-to-qualified-class-warn.m
Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/test/CodeGenObjCXX/references.mm
    cfe/trunk/test/SemaObjC/comptypes-4.m
    cfe/trunk/test/SemaObjCXX/references.mm

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=129142&r1=129141&r2=129142&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Fri Apr  8 13:25:29 2011
@@ -629,6 +629,27 @@
     return false;
   }
 
+  /// getImmSubClassOf - Returns Immediate sub-class of the specified interface class
+  /// if 'Super' is a superclass of this class. null if no such super class.
+  /// So in this example if 'this' is 'BClass' and 'Super' is 'AClass' then 'BClass'
+  /// is returned.
+  /// \code
+  /// @interface BClass : AClass <SubFooable>
+  /// @end
+  /// \endcode
+  
+  ObjCInterfaceDecl *getImmSubClassOf(const ObjCInterfaceDecl *Super) {
+    ObjCInterfaceDecl *ImmSubClass = this;
+    ObjCInterfaceDecl *I = this->getSuperClass();
+    while (I != NULL) {
+      if (Super == I)
+        return ImmSubClass;
+      ImmSubClass = I;
+      I = I->getSuperClass();
+    }
+    return NULL;
+  }
+
   ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName,
                                        ObjCInterfaceDecl *&ClassDeclared);
   ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) {

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=129142&r1=129141&r2=129142&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Apr  8 13:25:29 2011
@@ -4981,10 +4981,47 @@
   if (LHS->getNumProtocols() == 0)
     return true;
 
-  // Okay, we know the LHS has protocol qualifiers.  If the RHS doesn't, then it
-  // isn't a superset.
-  if (RHS->getNumProtocols() == 0)
-    return true;  // FIXME: should return false!
+  // Okay, we know the LHS has protocol qualifiers.  If the RHS doesn't, 
+  // more detailed analysis is required.
+  if (RHS->getNumProtocols() == 0) {
+    // OK, if LHS is a superclass of RHS *and*
+    // this superclass is assignment compatible with LHS.
+    // false otherwise.
+    ObjCInterfaceDecl *SuperClass = 
+      RHS->getInterface()->getImmSubClassOf(LHS->getInterface());
+    if (SuperClass) {
+      // OK if conversion of LHS to SuperClass results in narrowing of types
+      // ; i.e., SuperClass may implement at least one of the protocols
+      // in LHS's protocol list. Example, SuperObj<P1> = lhs<P1,P2> is ok.
+      // But not SuperObj<P1,P2,P3> = lhs<P1,P2>.
+      llvm::SmallPtrSet<ObjCProtocolDecl *, 8> SuperClassInheritedProtocols;
+      CollectInheritedProtocols(SuperClass, SuperClassInheritedProtocols);
+      // If super class has no protocols, it is not a match.
+      if (SuperClassInheritedProtocols.empty())
+        return false;
+      
+      for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(),
+           LHSPE = LHS->qual_end();
+           LHSPI != LHSPE; LHSPI++) {
+        bool SuperImplementsProtocol = false;
+        ObjCProtocolDecl *LHSProto = (*LHSPI);
+        
+        for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I =
+             SuperClassInheritedProtocols.begin(),
+             E = SuperClassInheritedProtocols.end(); I != E; ++I) {
+          ObjCProtocolDecl *SuperClassProto = (*I);
+          if (SuperClassProto->lookupProtocolNamed(LHSProto->getIdentifier())) {
+            SuperImplementsProtocol = true;
+            break;
+          }
+        }
+        if (!SuperImplementsProtocol)
+          return false;
+      }
+      return true;
+    }
+    return false;
+  }
 
   for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(),
                                      LHSPE = LHS->qual_end();

Modified: cfe/trunk/test/CodeGenObjCXX/references.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/references.mm?rev=129142&r1=129141&r2=129142&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/references.mm (original)
+++ cfe/trunk/test/CodeGenObjCXX/references.mm Fri Apr  8 13:25:29 2011
@@ -30,7 +30,7 @@
 @protocol P2 @end
 @protocol P3 @end
 @interface foo<P1> {} @end
- at interface bar : foo <P1, P2> {} @end
+ at interface bar : foo <P1, P2, P3> {} @end
 typedef bar baz;
 void f5(foo&);
 void f5b(foo<P1>&);

Modified: cfe/trunk/test/SemaObjC/comptypes-4.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/comptypes-4.m?rev=129142&r1=129141&r2=129142&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/comptypes-4.m (original)
+++ cfe/trunk/test/SemaObjC/comptypes-4.m Fri Apr  8 13:25:29 2011
@@ -12,7 +12,7 @@
   MyClass *obj_cp;
 
   obj_cp = obj_p;  
-  obj_p = obj_cp;
+  obj_p = obj_cp;	// expected-warning {{incompatible pointer types assigning to 'MyClass<MyProtocol> *' from 'MyClass *'}}
 
   if (obj_cp == obj_p)
     foo();

Added: cfe/trunk/test/SemaObjC/unqualified-to-qualified-class-warn.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/unqualified-to-qualified-class-warn.m?rev=129142&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/unqualified-to-qualified-class-warn.m (added)
+++ cfe/trunk/test/SemaObjC/unqualified-to-qualified-class-warn.m Fri Apr  8 13:25:29 2011
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1  -fsyntax-only -verify %s
+// rdar://9091389
+
+ at protocol Fooable
+- (void)foo;
+ at end
+
+ at protocol SubFooable <Fooable>
+ at end
+
+ at interface AClass
+ at end
+
+ at interface BClass : AClass <SubFooable>
+ at end
+
+ at implementation BClass
+- (void)foo {
+}
+ at end
+
+void functionTakingAClassConformingToAProtocol(AClass <Fooable> *instance) { // expected-note {{passing argument to parameter 'instance' here}}
+}
+
+int main () {
+    AClass *aobject = 0;
+    BClass *bobject = 0;
+    functionTakingAClassConformingToAProtocol(aobject);  // expected-warning {{incompatible pointer types passing 'AClass *' to parameter of type 'AClass<Fooable> *'}}
+    functionTakingAClassConformingToAProtocol(bobject); // Shouldn't warn -  does implement Fooable
+    return 0;
+}

Modified: cfe/trunk/test/SemaObjCXX/references.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/references.mm?rev=129142&r1=129141&r2=129142&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/references.mm (original)
+++ cfe/trunk/test/SemaObjCXX/references.mm Fri Apr  8 13:25:29 2011
@@ -37,7 +37,7 @@
 @protocol P2 @end
 @protocol P3 @end
 @interface foo<P1> {} @end
- at interface bar : foo <P1, P2> {} @end
+ at interface bar : foo <P1, P2, P3> {} @end
 typedef bar baz;
 
 struct ToBar {





More information about the cfe-commits mailing list