[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