Restructure and simplify Sema::ObjCQualifiedIdTypesAreCompatible,

deleting dead code, making other code more obvious, and fixing a
bug.  This fixes these (bogus) warnings in release mode:

SemaExprObjC.cpp:383: warning: 'RHSProtoE' may be used uninitialized in this function
SemaExprObjC.cpp:383: warning: 'RHSProtoI' may be used uninitialized in this function

llvm-svn: 49984
This commit is contained in:
Chris Lattner 2008-04-20 02:09:31 +00:00
parent 64bbdb17f5
commit 2cc4e23252
1 changed files with 71 additions and 72 deletions

View File

@ -348,6 +348,8 @@ static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
return false;
}
/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an
/// ObjCQualifiedIDType.
bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
bool compare) {
// Allow id<P..> and an 'id' or void* type in all cases.
@ -361,24 +363,30 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
return true;
}
const ObjCQualifiedInterfaceType *lhsQI = 0;
const ObjCQualifiedInterfaceType *rhsQI = 0;
ObjCInterfaceDecl *lhsID = 0;
ObjCInterfaceDecl *rhsID = 0;
const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType();
const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType();
if (lhsQID) {
if (!rhsQID && rhs->isPointerType()) {
if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType();
const ObjCQualifiedInterfaceType *rhsQI = 0;
if (!rhsQID) {
// Not comparing two ObjCQualifiedIdType's?
if (!rhs->isPointerType()) return false;
QualType rtype = rhs->getAsPointerType()->getPointeeType();
rhsQI = rtype->getAsObjCQualifiedInterfaceType();
if (!rhsQI) {
if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType())
rhsID = IT->getDecl();
}
if (rhsQI == 0) {
// If the RHS is an interface pointer ('NSString*'), handle it.
if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) {
ObjCInterfaceDecl *rhsID = IT->getDecl();
for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) {
// when comparing an id<P> on lhs with a static type on rhs,
// see if static class implements all of id's protocols, directly or
// through its super class and categories.
if (!ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true))
return false;
}
return true;
}
}
}
if (!rhsQI && !rhsQID && !rhsID)
return false;
ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE;
if (rhsQI) {
@ -387,6 +395,8 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
} else if (rhsQID) {
RHSProtoI = rhsQID->qual_begin();
RHSProtoE = rhsQID->qual_end();
} else {
return false;
}
for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) {
@ -396,71 +406,60 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
// when comparing an id<P> on lhs with a static type on rhs,
// see if static class implements all of id's protocols, directly or
// through its super class and categories.
if (rhsID) {
if (ClassImplementsProtocol(lhsProto, rhsID, true))
match = true;
} else {
for (; RHSProtoI != RHSProtoE; ++RHSProtoI) {
ObjCProtocolDecl *rhsProto = *RHSProtoI;
if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
match = true;
break;
}
}
}
if (!match)
return false;
}
} else if (rhsQID) {
if (!lhsQID && lhs->isPointerType()) {
QualType ltype = lhs->getAsPointerType()->getPointeeType();
lhsQI = ltype->getAsObjCQualifiedInterfaceType();
if (!lhsQI) {
if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType())
lhsID = IT->getDecl();
}
}
if (!lhsQI && !lhsQID && !lhsID)
return false;
ObjCQualifiedIdType::qual_iterator LHSProtoI, LHSProtoE;
if (lhsQI) {
LHSProtoI = lhsQI->qual_begin();
LHSProtoE = lhsQI->qual_end();
} else if (lhsQID) {
LHSProtoI = lhsQID->qual_begin();
LHSProtoE = lhsQID->qual_end();
}
bool match = false;
// for static type vs. qualified 'id' type, check that class implements
// one of 'id's protocols.
if (lhsID) {
for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) {
ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j);
if (ClassImplementsProtocol(rhsProto, lhsID, compare)) {
for (; RHSProtoI != RHSProtoE; ++RHSProtoI) {
ObjCProtocolDecl *rhsProto = *RHSProtoI;
if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
match = true;
break;
}
}
} else {
for (; LHSProtoI != LHSProtoE; ++LHSProtoI) {
match = false;
ObjCProtocolDecl *lhsProto = *LHSProtoI;
for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) {
ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j);
if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
if (!match)
return false;
}
return true;
}
const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType();
assert(rhsQID && "One of the LHS/RHS should be id<x>");
if (!lhs->isPointerType())
return false;
QualType ltype = lhs->getAsPointerType()->getPointeeType();
if (const ObjCQualifiedInterfaceType *lhsQI =
ltype->getAsObjCQualifiedInterfaceType()) {
ObjCQualifiedIdType::qual_iterator LHSProtoI = lhsQI->qual_begin();
ObjCQualifiedIdType::qual_iterator LHSProtoE = lhsQI->qual_end();
for (; LHSProtoI != LHSProtoE; ++LHSProtoI) {
bool match = false;
ObjCProtocolDecl *lhsProto = *LHSProtoI;
for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) {
ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j);
if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
match = true;
break;
}
match = true;
break;
}
}
if (!match)
return false;
}
if (!match)
return false;
return true;
}
return true;
if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType()) {
// for static type vs. qualified 'id' type, check that class implements
// all of 'id's protocols.
ObjCInterfaceDecl *lhsID = IT->getDecl();
for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) {
ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j);
if (!ClassImplementsProtocol(rhsProto, lhsID, compare))
return false;
}
return true;
}
return false;
}