From: John McCall Date: Mon, 31 Jan 2011 22:28:28 +0000 (+0000) Subject: Slightly reorganize CheckAssignmentConstraints and remove some redundant X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b6cfa24fe6c7a27e9bbaebc0cd28c857d11d6060;p=clang Slightly reorganize CheckAssignmentConstraints and remove some redundant logic. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124615 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 4a0f2299db..3a341561f8 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5557,16 +5557,9 @@ Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs, lhsType = Context.getCanonicalType(lhsType).getUnqualifiedType(); rhsType = Context.getCanonicalType(rhsType).getUnqualifiedType(); + // Common case: no conversion required. if (lhsType == rhsType) { Kind = CK_NoOp; - return Compatible; // Common case: fast path an exact match. - } - - if ((lhsType->isObjCClassType() && - (Context.hasSameType(rhsType, Context.ObjCClassRedefinitionType))) || - (rhsType->isObjCClassType() && - (Context.hasSameType(lhsType, Context.ObjCClassRedefinitionType)))) { - Kind = CK_BitCast; return Compatible; } @@ -5584,6 +5577,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs, } return Incompatible; } + // Allow scalar to ExtVector assignments, and assignments of an ExtVector type // to the same ExtVector type. if (lhsType->isExtVectorType()) { @@ -5602,6 +5596,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs, } } + // Conversions to or from vector type. if (lhsType->isVectorType() || rhsType->isVectorType()) { if (lhsType->isVectorType() && rhsType->isVectorType()) { // Allow assignments of an AltiVec vector type to an equivalent GCC @@ -5623,146 +5618,173 @@ Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs, return Incompatible; } + // Arithmetic conversions. if (lhsType->isArithmeticType() && rhsType->isArithmeticType() && !(getLangOptions().CPlusPlus && lhsType->isEnumeralType())) { Kind = PrepareScalarCast(*this, rhs, lhsType); return Compatible; } - if (isa(lhsType)) { - if (rhsType->isIntegerType()) { - Kind = CK_IntegralToPointer; // FIXME: null? - return IntToPointer; - } - + // Conversions to normal pointers. + if (const PointerType *lhsPointer = dyn_cast(lhsType)) { + // U* -> T* if (isa(rhsType)) { Kind = CK_BitCast; return CheckPointerTypesForAssignment(lhsType, rhsType); } - // In general, C pointers are not compatible with ObjC object pointers. + // int -> T* + if (rhsType->isIntegerType()) { + Kind = CK_IntegralToPointer; // FIXME: null? + return IntToPointer; + } + + // C pointers are not compatible with ObjC object pointers, + // with two exceptions: if (isa(rhsType)) { - Kind = CK_AnyPointerToObjCPointerCast; - if (lhsType->isVoidPointerType()) // an exception to the rule. + // - conversions to void* + if (lhsPointer->getPointeeType()->isVoidType()) { + Kind = CK_AnyPointerToObjCPointerCast; return Compatible; - return IncompatiblePointer; - } - if (rhsType->getAs()) { - if (lhsType->getAs()->getPointeeType()->isVoidType()) { + } + + // - conversions from 'Class' to the redefinition type + if (rhsType->isObjCClassType() && + Context.hasSameType(lhsType, Context.ObjCClassRedefinitionType)) { Kind = CK_BitCast; return Compatible; } - // Treat block pointers as objects. - if (getLangOptions().ObjC1 && lhsType->isObjCIdType()) { - Kind = CK_AnyPointerToObjCPointerCast; + Kind = CK_BitCast; + return IncompatiblePointer; + } + + // U^ -> void* + if (rhsType->getAs()) { + if (lhsPointer->getPointeeType()->isVoidType()) { + Kind = CK_BitCast; return Compatible; } } + return Incompatible; } + // Conversions to block pointers. if (isa(lhsType)) { + // U^ -> T^ + if (rhsType->isBlockPointerType()) { + Kind = CK_AnyPointerToBlockPointerCast; + return CheckBlockPointerTypesForAssignment(lhsType, rhsType); + } + + // int or null -> T^ if (rhsType->isIntegerType()) { Kind = CK_IntegralToPointer; // FIXME: null return IntToBlockPointer; } - Kind = CK_AnyPointerToObjCPointerCast; - - // Treat block pointers as objects. - if (getLangOptions().ObjC1 && rhsType->isObjCIdType()) + // id -> T^ + if (getLangOptions().ObjC1 && rhsType->isObjCIdType()) { + Kind = CK_AnyPointerToBlockPointerCast; return Compatible; + } - if (rhsType->isBlockPointerType()) - return CheckBlockPointerTypesForAssignment(lhsType, rhsType); - + // void* -> T^ if (const PointerType *RHSPT = rhsType->getAs()) - if (RHSPT->getPointeeType()->isVoidType()) + if (RHSPT->getPointeeType()->isVoidType()) { + Kind = CK_AnyPointerToBlockPointerCast; return Compatible; + } return Incompatible; } + // Conversions to Objective-C pointers. if (isa(lhsType)) { + // A* -> B* + if (rhsType->isObjCObjectPointerType()) { + Kind = CK_BitCast; + return CheckObjCPointerTypesForAssignment(lhsType, rhsType); + } + + // int or null -> A* if (rhsType->isIntegerType()) { Kind = CK_IntegralToPointer; // FIXME: null return IntToPointer; } - Kind = CK_BitCast; - - // In general, C pointers are not compatible with ObjC object pointers. + // In general, C pointers are not compatible with ObjC object pointers, + // with two exceptions: if (isa(rhsType)) { - if (rhsType->isVoidPointerType()) // an exception to the rule. + // - conversions from 'void*' + if (rhsType->isVoidPointerType()) { + Kind = CK_AnyPointerToObjCPointerCast; return Compatible; - return IncompatiblePointer; - } - if (rhsType->isObjCObjectPointerType()) { - return CheckObjCPointerTypesForAssignment(lhsType, rhsType); - } - if (const PointerType *RHSPT = rhsType->getAs()) { - if (RHSPT->getPointeeType()->isVoidType()) + } + + // - conversions to 'Class' from its redefinition type + if (lhsType->isObjCClassType() && + Context.hasSameType(rhsType, Context.ObjCClassRedefinitionType)) { + Kind = CK_BitCast; return Compatible; + } + + Kind = CK_AnyPointerToObjCPointerCast; + return IncompatiblePointer; } - // Treat block pointers as objects. - if (rhsType->isBlockPointerType()) + + // T^ -> A* + if (rhsType->isBlockPointerType()) { + Kind = CK_AnyPointerToObjCPointerCast; return Compatible; + } + return Incompatible; } + + // Conversions from pointers that are not covered by the above. if (isa(rhsType)) { - // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer. + // T* -> _Bool if (lhsType == Context.BoolTy) { Kind = CK_PointerToBoolean; return Compatible; } + // T* -> int if (lhsType->isIntegerType()) { Kind = CK_PointerToIntegral; return PointerToInt; } - if (isa(lhsType) && - rhsType->getAs()->getPointeeType()->isVoidType()) { - Kind = CK_AnyPointerToBlockPointerCast; - return Compatible; - } return Incompatible; } + + // Conversions from Objective-C pointers that are not covered by the above. if (isa(rhsType)) { - // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer. + // T* -> _Bool if (lhsType == Context.BoolTy) { Kind = CK_PointerToBoolean; return Compatible; } + // T* -> int if (lhsType->isIntegerType()) { Kind = CK_PointerToIntegral; return PointerToInt; } - Kind = CK_BitCast; - - // In general, C pointers are not compatible with ObjC object pointers. - if (isa(lhsType)) { - if (lhsType->isVoidPointerType()) // an exception to the rule. - return Compatible; - return IncompatiblePointer; - } - if (isa(lhsType) && - rhsType->getAs()->getPointeeType()->isVoidType()) { - Kind = CK_AnyPointerToBlockPointerCast; - return Compatible; - } return Incompatible; } + // struct A -> struct B if (isa(lhsType) && isa(rhsType)) { if (Context.typesAreCompatible(lhsType, rhsType)) { Kind = CK_NoOp; return Compatible; } } + return Incompatible; }