diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-04-08 18:25:29 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-04-08 18:25:29 +0000 |
commit | b7bc34a83aff8af09f2a78aa6d1dcafe18ad8619 (patch) | |
tree | 8de806a3d2fc84723c0f79e7f669b5ddb3004c2a /lib/AST/ASTContext.cpp | |
parent | f44a1a04a36453527de2285c402fbe9453184121 (diff) |
Warn for any kind of initialization if initializer does not
implement lhs's protocols. // rdar://9091389.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129142 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r-- | lib/AST/ASTContext.cpp | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 01e8f8e396..39229a7b73 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -4981,10 +4981,47 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS, 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(); |