aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2008-08-22 00:56:42 +0000
committerEli Friedman <eli.friedman@gmail.com>2008-08-22 00:56:42 +0000
commit3d815e7eb56c25d7ed812eced32e41df43039f9a (patch)
tree25fe2d71c1f33a5920ccf73ffe3641c1734efc06 /lib/Sema/SemaExpr.cpp
parentd8bfe7f25a695ca947effbccdf9ecbe3e018e221 (diff)
Rewrite type compatibility testing to do type merging rather than just
testing compatibility. This is necessary for some constructs, like merging redeclarations. Also, there are some ObjC changes to make sure that typesAreCompatible(a,b) == typesAreCompatible(b,a). I don't have any ObjC code beyond the testsuite, so please tell me if there are any cases where this doesn't behave as expected. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55158 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp33
1 files changed, 31 insertions, 2 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index c7db342ae4..9a544a2e05 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1354,7 +1354,20 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
assert(lhptee->isFunctionType());
return FunctionVoidPointer;
}
-
+
+ // Check for ObjC interfaces
+ const ObjCInterfaceType* LHSIface = lhptee->getAsObjCInterfaceType();
+ const ObjCInterfaceType* RHSIface = rhptee->getAsObjCInterfaceType();
+ if (LHSIface && RHSIface &&
+ Context.canAssignObjCInterfaces(LHSIface, RHSIface))
+ return ConvTy;
+
+ // ID acts sort of like void* for ObjC interfaces
+ if (LHSIface && Context.isObjCIdType(rhptee))
+ return ConvTy;
+ if (RHSIface && Context.isObjCIdType(lhptee))
+ return ConvTy;
+
// C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
// unqualified versions of compatible types, ...
if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
@@ -1701,6 +1714,21 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation loc,
return lex->getType();
}
+static bool areComparableObjCInterfaces(QualType LHS, QualType RHS,
+ ASTContext& Context) {
+ const ObjCInterfaceType* LHSIface = LHS->getAsObjCInterfaceType();
+ const ObjCInterfaceType* RHSIface = RHS->getAsObjCInterfaceType();
+ // ID acts sort of like void* for ObjC interfaces
+ if (LHSIface && Context.isObjCIdType(RHS))
+ return true;
+ if (RHSIface && Context.isObjCIdType(LHS))
+ return true;
+ if (!LHSIface || !RHSIface)
+ return false;
+ return Context.canAssignObjCInterfaces(LHSIface, RHSIface) ||
+ Context.canAssignObjCInterfaces(RHSIface, LHSIface);
+}
+
// C99 6.5.8
QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation loc,
bool isRelational) {
@@ -1756,7 +1784,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation loc,
if (!LHSIsNull && !RHSIsNull && // C99 6.5.9p2
!LCanPointeeTy->isVoidType() && !RCanPointeeTy->isVoidType() &&
!Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(),
- RCanPointeeTy.getUnqualifiedType())) {
+ RCanPointeeTy.getUnqualifiedType()) &&
+ !areComparableObjCInterfaces(LCanPointeeTy, RCanPointeeTy, Context)) {
Diag(loc, diag::ext_typecheck_comparison_of_distinct_pointers,
lType.getAsString(), rType.getAsString(),
lex->getSourceRange(), rex->getSourceRange());