aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AST/ASTContext.cpp25
-rw-r--r--Sema/SemaExpr.cpp2
-rw-r--r--include/clang/AST/ASTContext.h2
3 files changed, 23 insertions, 6 deletions
diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp
index 417c56570a..5ec5131074 100644
--- a/AST/ASTContext.cpp
+++ b/AST/ASTContext.cpp
@@ -1278,10 +1278,25 @@ bool ASTContext::QualifiedInterfaceTypesAreCompatible(QualType lhs,
return true;
}
+/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the
+/// inheritance hierarchy of 'rProto'.
+static bool ProtocolCompatibleWithProtocol(ObjcProtocolDecl *lProto,
+ ObjcProtocolDecl *rProto) {
+ if (lProto == rProto)
+ return true;
+ ObjcProtocolDecl** RefPDecl = rProto->getReferencedProtocols();
+ for (unsigned i = 0; i < rProto->getNumReferencedProtocols(); i++)
+ if (ProtocolCompatibleWithProtocol(lProto, RefPDecl[i]))
+ return true;
+ return false;
+}
+
/// ObjcQualifiedIdTypesAreCompatible - Compares two types, at least
-/// one of which is a protocol qualified 'id' type.
+/// one of which is a protocol qualified 'id' type. When 'compare'
+/// is true it is for comparison; when false, for assignment/initialization.
bool ASTContext::ObjcQualifiedIdTypesAreCompatible(QualType lhs,
- QualType rhs) {
+ QualType rhs,
+ bool compare) {
// match id<P..> with an 'id' type in all cases.
if (const PointerType *PT = lhs->getAsPointerType()) {
QualType PointeeTy = PT->getPointeeType();
@@ -1339,7 +1354,8 @@ bool ASTContext::ObjcQualifiedIdTypesAreCompatible(QualType lhs,
}
for (unsigned j = 0; j < numRhsProtocols; j++) {
ObjcProtocolDecl *rhsProto = rhsProtoList[j];
- if (lhsProto == rhsProto) {
+ if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
+ compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
match = true;
break;
}
@@ -1385,7 +1401,8 @@ bool ASTContext::ObjcQualifiedIdTypesAreCompatible(QualType lhs,
ObjcProtocolDecl *lhsProto = lhsProtoList[i];
for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) {
ObjcProtocolDecl *rhsProto = rhsQID->getProtocols(j);
- if (lhsProto == rhsProto) {
+ if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
+ compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
match = true;
break;
}
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index e720c2e460..d7a89865ea 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -1400,7 +1400,7 @@ inline QualType Sema::CheckCompareOperands( // C99 6.5.8
return Context.IntTy;
}
if ((lType->isObjcQualifiedIdType() || rType->isObjcQualifiedIdType())
- && Context.ObjcQualifiedIdTypesAreCompatible(lType, rType)) {
+ && Context.ObjcQualifiedIdTypesAreCompatible(lType, rType, true)) {
promoteExprToType(rex, lType);
return Context.IntTy;
}
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 80188e25cf..a96cb5dfdc 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -297,7 +297,7 @@ public:
/// Objective-C specific type checking.
bool interfaceTypesAreCompatible(QualType, QualType);
bool QualifiedInterfaceTypesAreCompatible(QualType, QualType);
- bool ObjcQualifiedIdTypesAreCompatible(QualType, QualType);
+ bool ObjcQualifiedIdTypesAreCompatible(QualType, QualType, bool = false);
bool objcTypesAreCompatible(QualType, QualType);
bool isObjcIdType(QualType T) const {
if (!IdStructType) // ObjC isn't enabled