From eebc4750fd66be9e395ab3fc757a067e050a9677 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Thu, 10 Dec 2009 19:47:41 +0000 Subject: [PATCH] Move composite type finding of two objective-c expressions into its own helper method. No change in functionality. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91056 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/Sema.h | 3 + lib/Sema/SemaExpr.cpp | 255 +++++++++++++++++++++++------------------- 2 files changed, 140 insertions(+), 118 deletions(-) diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 22e6b14421..7b030cbe93 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -3638,6 +3638,9 @@ public: Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc); QualType FindCompositePointerType(Expr *&E1, Expr *&E2); // C++ 5.9 + QualType FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, + SourceLocation questionLoc); + /// type checking for vector binary operators. inline QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex); inline QualType CheckVectorCompareOperands(Expr *&lex, Expr *&rx, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 99afbaf605..dbdaf59cba 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3920,41 +3920,14 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, ImpCastExprToType(LHS, RHSTy, CastExpr::CK_Unknown); return RHSTy; } - // Handle things like Class and struct objc_class*. Here we case the result - // to the pseudo-builtin, because that will be implicitly cast back to the - // redefinition type if an attempt is made to access its fields. - if (LHSTy->isObjCClassType() && - (RHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) { - ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); - return LHSTy; - } - if (RHSTy->isObjCClassType() && - (LHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) { - ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast); - return RHSTy; - } - // And the same for struct objc_object* / id - if (LHSTy->isObjCIdType() && - (RHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) { - ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); - return LHSTy; - } - if (RHSTy->isObjCIdType() && - (LHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) { - ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast); - return RHSTy; - } - // And the same for struct objc_selector* / SEL - if (Context.isObjCSelType(LHSTy) && - (RHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) { - ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); - return LHSTy; - } - if (Context.isObjCSelType(RHSTy) && - (LHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) { - ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast); - return RHSTy; - } + + // All objective-c pointer type analysis is done here. + QualType compositeType = FindCompositeObjCPointerType(LHS, RHS, + QuestionLoc); + if (!compositeType.isNull()) + return compositeType; + + // Handle block pointer types. if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) { if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) { @@ -3965,7 +3938,7 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, return destType; } Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); return QualType(); } // We have 2 block pointer types. @@ -3976,11 +3949,11 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // The block pointer types aren't identical, continue checking. QualType lhptee = LHSTy->getAs()->getPointeeType(); QualType rhptee = RHSTy->getAs()->getPointeeType(); - + if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), rhptee.getUnqualifiedType())) { Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); // In this situation, we assume void* type. No especially good // reason, but this is what gcc does, and we do have to pick // to get a consistent AST. @@ -3994,86 +3967,7 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); return LHSTy; } - // Check constraints for Objective-C object pointers types. - if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) { - - if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { - // Two identical object pointer types are always compatible. - return LHSTy; - } - const ObjCObjectPointerType *LHSOPT = LHSTy->getAs(); - const ObjCObjectPointerType *RHSOPT = RHSTy->getAs(); - QualType compositeType = LHSTy; - - // If both operands are interfaces and either operand can be - // assigned to the other, use that type as the composite - // type. This allows - // xxx ? (A*) a : (B*) b - // where B is a subclass of A. - // - // Additionally, as for assignment, if either type is 'id' - // allow silent coercion. Finally, if the types are - // incompatible then make sure to use 'id' as the composite - // type so the result is acceptable for sending messages to. - - // FIXME: Consider unifying with 'areComparableObjCPointerTypes'. - // It could return the composite type. - if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) { - compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy; - } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) { - compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy; - } else if ((LHSTy->isObjCQualifiedIdType() || - RHSTy->isObjCQualifiedIdType()) && - Context.ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) { - // Need to handle "id" explicitly. - // GCC allows qualified id and any Objective-C type to devolve to - // id. Currently localizing to here until clear this should be - // part of ObjCQualifiedIdTypesAreCompatible. - compositeType = Context.getObjCIdType(); - } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) { - compositeType = Context.getObjCIdType(); - } else if (!(compositeType = - Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull()) - ; - else { - Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) - << LHSTy << RHSTy - << LHS->getSourceRange() << RHS->getSourceRange(); - QualType incompatTy = Context.getObjCIdType(); - ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast); - ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast); - return incompatTy; - } - // The object pointer types are compatible. - ImpCastExprToType(LHS, compositeType, CastExpr::CK_BitCast); - ImpCastExprToType(RHS, compositeType, CastExpr::CK_BitCast); - return compositeType; - } - // Check Objective-C object pointer types and 'void *' - if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) { - QualType lhptee = LHSTy->getAs()->getPointeeType(); - QualType rhptee = RHSTy->getAs()->getPointeeType(); - QualType destPointee - = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); - QualType destType = Context.getPointerType(destPointee); - // Add qualifiers if necessary. - ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp); - // Promote to void*. - ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast); - return destType; - } - if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { - QualType lhptee = LHSTy->getAs()->getPointeeType(); - QualType rhptee = RHSTy->getAs()->getPointeeType(); - QualType destPointee - = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); - QualType destType = Context.getPointerType(destPointee); - // Add qualifiers if necessary. - ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp); - // Promote to void*. - ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast); - return destType; - } + // Check constraints for C object pointers types (C99 6.5.15p3,6). if (LHSTy->isPointerType() && RHSTy->isPointerType()) { // get the "pointed to" types @@ -4151,6 +4045,131 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, return QualType(); } +/// FindCompositeObjCPointerType - Helper method to find composite type of +/// two objective-c pointer types of the two input expressions. +QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, + SourceLocation QuestionLoc) { + QualType LHSTy = LHS->getType(); + QualType RHSTy = RHS->getType(); + + // Handle things like Class and struct objc_class*. Here we case the result + // to the pseudo-builtin, because that will be implicitly cast back to the + // redefinition type if an attempt is made to access its fields. + if (LHSTy->isObjCClassType() && + (RHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) { + ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); + return LHSTy; + } + if (RHSTy->isObjCClassType() && + (LHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) { + ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast); + return RHSTy; + } + // And the same for struct objc_object* / id + if (LHSTy->isObjCIdType() && + (RHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) { + ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); + return LHSTy; + } + if (RHSTy->isObjCIdType() && + (LHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) { + ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast); + return RHSTy; + } + // And the same for struct objc_selector* / SEL + if (Context.isObjCSelType(LHSTy) && + (RHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) { + ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); + return LHSTy; + } + if (Context.isObjCSelType(RHSTy) && + (LHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) { + ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast); + return RHSTy; + } + // Check constraints for Objective-C object pointers types. + if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) { + + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { + // Two identical object pointer types are always compatible. + return LHSTy; + } + const ObjCObjectPointerType *LHSOPT = LHSTy->getAs(); + const ObjCObjectPointerType *RHSOPT = RHSTy->getAs(); + QualType compositeType = LHSTy; + + // If both operands are interfaces and either operand can be + // assigned to the other, use that type as the composite + // type. This allows + // xxx ? (A*) a : (B*) b + // where B is a subclass of A. + // + // Additionally, as for assignment, if either type is 'id' + // allow silent coercion. Finally, if the types are + // incompatible then make sure to use 'id' as the composite + // type so the result is acceptable for sending messages to. + + // FIXME: Consider unifying with 'areComparableObjCPointerTypes'. + // It could return the composite type. + if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) { + compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy; + } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) { + compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy; + } else if ((LHSTy->isObjCQualifiedIdType() || + RHSTy->isObjCQualifiedIdType()) && + Context.ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) { + // Need to handle "id" explicitly. + // GCC allows qualified id and any Objective-C type to devolve to + // id. Currently localizing to here until clear this should be + // part of ObjCQualifiedIdTypesAreCompatible. + compositeType = Context.getObjCIdType(); + } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) { + compositeType = Context.getObjCIdType(); + } else if (!(compositeType = + Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull()) + ; + else { + Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy + << LHS->getSourceRange() << RHS->getSourceRange(); + QualType incompatTy = Context.getObjCIdType(); + ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast); + ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast); + return incompatTy; + } + // The object pointer types are compatible. + ImpCastExprToType(LHS, compositeType, CastExpr::CK_BitCast); + ImpCastExprToType(RHS, compositeType, CastExpr::CK_BitCast); + return compositeType; + } + // Check Objective-C object pointer types and 'void *' + if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) { + QualType lhptee = LHSTy->getAs()->getPointeeType(); + QualType rhptee = RHSTy->getAs()->getPointeeType(); + QualType destPointee + = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); + QualType destType = Context.getPointerType(destPointee); + // Add qualifiers if necessary. + ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp); + // Promote to void*. + ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast); + return destType; + } + if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { + QualType lhptee = LHSTy->getAs()->getPointeeType(); + QualType rhptee = RHSTy->getAs()->getPointeeType(); + QualType destPointee + = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); + QualType destType = Context.getPointerType(destPointee); + // Add qualifiers if necessary. + ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp); + // Promote to void*. + ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast); + return destType; + } + return QualType(); +} + /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null /// in the case of a the GNU conditional expr extension. Action::OwningExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,