From ea54d9ef72cc3467e13710072245f35464a3440e Mon Sep 17 00:00:00 2001 From: Steve Naroff Date: Mon, 20 Oct 2008 18:19:10 +0000 Subject: [PATCH] Sema::CheckCompareOperands() and ASTContext::mergeTypes(): Change handling of ObjC qualified id types to be consistent with gcc. This changes a handful of test case errors into warnings (diff will tell you which cases have changed). llvm-svn: 57841 --- clang/lib/AST/ASTContext.cpp | 24 ++++++++++++++++++++---- clang/lib/Sema/SemaExpr.cpp | 7 +++++++ clang/test/SemaObjC/comptypes-1.m | 6 ++++-- clang/test/SemaObjC/comptypes-7.m | 4 ++-- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index deb80900bb37..f4266fb90d1d 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2036,14 +2036,30 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { if (LHSClass != RHSClass) { // ID is compatible with all qualified id types. if (LHS->isObjCQualifiedIdType()) { - if (const PointerType *PT = RHS->getAsPointerType()) - if (isObjCIdType(PT->getPointeeType())) + if (const PointerType *PT = RHS->getAsPointerType()) { + QualType pType = PT->getPointeeType(); + if (isObjCIdType(pType)) return LHS; + // FIXME: need to use ObjCQualifiedIdTypesAreCompatible(LHS, RHS, true). + // Unfortunately, this API is part of Sema (which we don't have access + // to. Need to refactor. The following check is insufficient, since we + // need to make sure the class implements the protocol. + if (pType->isObjCInterfaceType()) + return LHS; + } } if (RHS->isObjCQualifiedIdType()) { - if (const PointerType *PT = LHS->getAsPointerType()) - if (isObjCIdType(PT->getPointeeType())) + if (const PointerType *PT = LHS->getAsPointerType()) { + QualType pType = PT->getPointeeType(); + if (isObjCIdType(pType)) return RHS; + // FIXME: need to use ObjCQualifiedIdTypesAreCompatible(LHS, RHS, true). + // Unfortunately, this API is part of Sema (which we don't have access + // to. Need to refactor. The following check is insufficient, since we + // need to make sure the class implements the protocol. + if (pType->isObjCInterfaceType()) + return RHS; + } } // C99 6.7.2.2p4: Each enumerated type shall be compatible with char, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 563718ccc8d5..1f885165cd9d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2061,6 +2061,13 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation loc, } if ((lType->isObjCQualifiedIdType() || rType->isObjCQualifiedIdType())) { + if ((lType->isPointerType() || rType->isPointerType()) && + !Context.typesAreCompatible(lType, rType)) { + Diag(loc, diag::ext_typecheck_comparison_of_distinct_pointers, + lType.getAsString(), rType.getAsString(), + lex->getSourceRange(), rex->getSourceRange()); + return QualType(); + } if (ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) { ImpCastExprToType(rex, lType); return Context.IntTy; diff --git a/clang/test/SemaObjC/comptypes-1.m b/clang/test/SemaObjC/comptypes-1.m index ec0e38052116..f6cd3a266b9a 100644 --- a/clang/test/SemaObjC/comptypes-1.m +++ b/clang/test/SemaObjC/comptypes-1.m @@ -66,6 +66,8 @@ int main() /* Any comparison between 'MyClass *' and anything which is not an 'id' must generate a warning. */ + /* FIXME: GCC considers this a warning ("comparison of distinct pointer types"). */ + /* There is a corresponding FIXME in ASTContext::mergeTypes() */ if (obj_p == obj_c) foo() ; // expected-error {{invalid operands to binary expression ('id' and 'MyClass *')}} if (obj_c == obj_cp) foo() ; // expected-warning {{comparison of distinct pointer types ('MyClass *' and 'MyOtherClass *')}} @@ -80,8 +82,8 @@ int main() if (obj_p == obj_cp) foo() ; /* Ok */ - if (obj_p == obj_C) foo() ; // expected-error {{invalid operands to binary expression ('id' and 'Class')}} - if (obj_C == obj_p) foo() ; // expected-error {{invalid operands to binary expression ('Class' and 'id')}} + if (obj_p == obj_C) foo() ; // expected-warning {{comparison of distinct pointer types ('id' and 'Class')}} + if (obj_C == obj_p) foo() ; // expected-warning {{comparison of distinct pointer types ('Class' and 'id')}} if (obj_cp == obj_C) foo() ; // expected-warning {{comparison of distinct pointer types ('MyOtherClass *' and 'Class')}} if (obj_C == obj_cp) foo() ; // expected-warning {{comparison of distinct pointer types ('Class' and 'MyOtherClass *')}} diff --git a/clang/test/SemaObjC/comptypes-7.m b/clang/test/SemaObjC/comptypes-7.m index ce0391ea07a5..27b832b7369a 100644 --- a/clang/test/SemaObjC/comptypes-7.m +++ b/clang/test/SemaObjC/comptypes-7.m @@ -58,8 +58,8 @@ int main() if (obj_p == i) foo() ; // expected-warning {{comparison between pointer and integer ('id' and 'int')}} if (i == obj_p) foo() ; // expected-warning {{comparison between pointer and integer ('int' and 'id')}} - if (obj_p == j) foo() ; // expected-error {{invalid operands to binary expression ('id' and 'int *')}} - if (j == obj_p) foo() ; // expected-error {{invalid operands to binary expression ('int *' and 'id')}} + if (obj_p == j) foo() ; // expected-warning {{comparison of distinct pointer types ('id' and 'int *')}} + if (j == obj_p) foo() ; // expected-warning {{comparison of distinct pointer types ('int *' and 'id')}} if (obj_C == i) foo() ; // expected-warning {{comparison between pointer and integer ('Class' and 'int')}} if (i == obj_C) foo() ; // expected-warning {{comparison between pointer and integer ('int' and 'Class')}}