diff options
-rw-r--r-- | include/clang/AST/Expr.h | 65 | ||||
-rw-r--r-- | include/clang/AST/ExprObjC.h | 6 | ||||
-rw-r--r-- | include/clang/AST/OperationKinds.h | 23 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 4 | ||||
-rw-r--r-- | lib/ARCMigrate/TransUnbridgedCasts.cpp | 2 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 93 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 9 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 13 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGExprComplex.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 3 | ||||
-rw-r--r-- | lib/Rewrite/RewriteObjC.cpp | 50 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaCXXCast.cpp | 24 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 96 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 19 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineC.cpp | 3 |
22 files changed, 294 insertions, 155 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 3d4b345ff5..e81b44a8ed 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -2327,68 +2327,7 @@ public: private: Stmt *Op; - void CheckCastConsistency() const { -#ifndef NDEBUG - switch (getCastKind()) { - case CK_DerivedToBase: - case CK_UncheckedDerivedToBase: - case CK_DerivedToBaseMemberPointer: - case CK_BaseToDerived: - case CK_BaseToDerivedMemberPointer: - assert(!path_empty() && "Cast kind should have a base path!"); - break; - - // These should not have an inheritance path. - case CK_BitCast: - case CK_Dynamic: - case CK_ToUnion: - case CK_ArrayToPointerDecay: - case CK_FunctionToPointerDecay: - case CK_NullToMemberPointer: - case CK_NullToPointer: - case CK_ConstructorConversion: - case CK_IntegralToPointer: - case CK_PointerToIntegral: - case CK_ToVoid: - case CK_VectorSplat: - case CK_IntegralCast: - case CK_IntegralToFloating: - case CK_FloatingToIntegral: - case CK_FloatingCast: - case CK_AnyPointerToObjCPointerCast: - case CK_AnyPointerToBlockPointerCast: - case CK_ObjCObjectLValueCast: - case CK_FloatingRealToComplex: - case CK_FloatingComplexToReal: - case CK_FloatingComplexCast: - case CK_FloatingComplexToIntegralComplex: - case CK_IntegralRealToComplex: - case CK_IntegralComplexToReal: - case CK_IntegralComplexCast: - case CK_IntegralComplexToFloatingComplex: - case CK_ObjCProduceObject: - case CK_ObjCConsumeObject: - case CK_ObjCReclaimReturnedObject: - assert(!getType()->isBooleanType() && "unheralded conversion to bool"); - // fallthrough to check for null base path - - case CK_Dependent: - case CK_LValueToRValue: - case CK_GetObjCProperty: - case CK_NoOp: - case CK_PointerToBoolean: - case CK_IntegralToBoolean: - case CK_FloatingToBoolean: - case CK_MemberPointerToBoolean: - case CK_FloatingComplexToBoolean: - case CK_IntegralComplexToBoolean: - case CK_LValueBitCast: // -> bool& - case CK_UserDefinedConversion: // operator bool() - assert(path_empty() && "Cast kind should not have a base path!"); - break; - } -#endif - } + void CheckCastConsistency() const; const CXXBaseSpecifier * const *path_buffer() const { return const_cast<CastExpr*>(this)->path_buffer(); @@ -2419,7 +2358,9 @@ protected: assert(kind != CK_Invalid && "creating cast with invalid cast kind"); CastExprBits.Kind = kind; setBasePathSize(BasePathSize); +#ifndef NDEBUG CheckCastConsistency(); +#endif } /// \brief Construct an empty cast. diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 725253e45c..4420f7527c 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -989,10 +989,10 @@ class ObjCBridgedCastExpr : public ExplicitCastExpr { public: ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind, - SourceLocation BridgeKeywordLoc, TypeSourceInfo *TSInfo, - Expr *Operand) + CastKind CK, SourceLocation BridgeKeywordLoc, + TypeSourceInfo *TSInfo, Expr *Operand) : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue, - CK_BitCast, Operand, 0, TSInfo), + CK, Operand, 0, TSInfo), LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) { } /// \brief Construct an empty Objective-C bridged cast. diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 92ff604137..fa9adec4ef 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -31,9 +31,12 @@ enum CastKind { /// to be reinterpreted as a bit pattern of another type. Generally /// the operands must have equivalent size and unrelated types. /// - /// The pointer conversion char* -> int* is a bitcast. Many other - /// pointer conversions which are "physically" bitcasts are given - /// special cast kinds. + /// The pointer conversion char* -> int* is a bitcast. A conversion + /// from any pointer type to a C pointer type is a bitcast unless + /// it's actually BaseToDerived or DerivedToBase. A conversion to a + /// block pointer or ObjC pointer type is a bitcast only if the + /// operand has the same type kind; otherwise, it's one of the + /// specialized casts below. /// /// Vector coercions are bitcasts. CK_BitCast, @@ -186,12 +189,16 @@ enum CastKind { /// (float) ld CK_FloatingCast, - /// CK_AnyPointerToObjCPointerCast - Casting any other pointer kind - /// to an Objective-C pointer. - CK_AnyPointerToObjCPointerCast, + /// CK_CPointerToObjCPointerCast - Casting a C pointer kind to an + /// Objective-C pointer. + CK_CPointerToObjCPointerCast, - /// CK_AnyPointerToBlockPointerCast - Casting any other pointer kind - /// to a block pointer. + /// CK_BlockPointerToObjCPointerCast - Casting a block pointer to an + /// ObjC pointer. + CK_BlockPointerToObjCPointerCast, + + /// CK_AnyPointerToBlockPointerCast - Casting any non-block pointer + /// to a block pointer. Block-to-block casts are bitcasts. CK_AnyPointerToBlockPointerCast, /// \brief Converting between two Objective-C object types, which diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 8a826e592a..e68d206f21 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1458,7 +1458,9 @@ public: Qualifiers::ObjCLifetime getObjCARCImplicitLifetime() const; enum ScalarTypeKind { - STK_Pointer, + STK_CPointer, + STK_BlockPointer, + STK_ObjCObjectPointer, STK_MemberPointer, STK_Bool, STK_Integral, diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp index 7e922f3a27..5f9159416b 100644 --- a/lib/ARCMigrate/TransUnbridgedCasts.cpp +++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp @@ -61,7 +61,7 @@ public: } bool VisitCastExpr(CastExpr *E) { - if (E->getCastKind() != CK_AnyPointerToObjCPointerCast + if (E->getCastKind() != CK_CPointerToObjCPointerCast && E->getCastKind() != CK_BitCast) return true; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index a3df189a61..25e7de77fb 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1013,6 +1013,93 @@ SourceRange MemberExpr::getSourceRange() const { return SourceRange(StartLoc, EndLoc); } +void CastExpr::CheckCastConsistency() const { + switch (getCastKind()) { + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + case CK_DerivedToBaseMemberPointer: + case CK_BaseToDerived: + case CK_BaseToDerivedMemberPointer: + assert(!path_empty() && "Cast kind should have a base path!"); + break; + + case CK_CPointerToObjCPointerCast: + assert(getType()->isObjCObjectPointerType()); + assert(getSubExpr()->getType()->isPointerType()); + goto CheckNoBasePath; + + case CK_BlockPointerToObjCPointerCast: + assert(getType()->isObjCObjectPointerType()); + assert(getSubExpr()->getType()->isBlockPointerType()); + goto CheckNoBasePath; + + case CK_BitCast: + // Arbitrary casts to C pointer types count as bitcasts. + // Otherwise, we should only have block and ObjC pointer casts + // here if they stay within the type kind. + if (!getType()->isPointerType()) { + assert(getType()->isObjCObjectPointerType() == + getSubExpr()->getType()->isObjCObjectPointerType()); + assert(getType()->isBlockPointerType() == + getSubExpr()->getType()->isBlockPointerType()); + } + goto CheckNoBasePath; + + case CK_AnyPointerToBlockPointerCast: + assert(getType()->isBlockPointerType()); + assert(getSubExpr()->getType()->isAnyPointerType() && + !getSubExpr()->getType()->isBlockPointerType()); + goto CheckNoBasePath; + + // These should not have an inheritance path. + case CK_Dynamic: + case CK_ToUnion: + case CK_ArrayToPointerDecay: + case CK_FunctionToPointerDecay: + case CK_NullToMemberPointer: + case CK_NullToPointer: + case CK_ConstructorConversion: + case CK_IntegralToPointer: + case CK_PointerToIntegral: + case CK_ToVoid: + case CK_VectorSplat: + case CK_IntegralCast: + case CK_IntegralToFloating: + case CK_FloatingToIntegral: + case CK_FloatingCast: + case CK_ObjCObjectLValueCast: + case CK_FloatingRealToComplex: + case CK_FloatingComplexToReal: + case CK_FloatingComplexCast: + case CK_FloatingComplexToIntegralComplex: + case CK_IntegralRealToComplex: + case CK_IntegralComplexToReal: + case CK_IntegralComplexCast: + case CK_IntegralComplexToFloatingComplex: + case CK_ObjCProduceObject: + case CK_ObjCConsumeObject: + case CK_ObjCReclaimReturnedObject: + assert(!getType()->isBooleanType() && "unheralded conversion to bool"); + goto CheckNoBasePath; + + case CK_Dependent: + case CK_LValueToRValue: + case CK_GetObjCProperty: + case CK_NoOp: + case CK_PointerToBoolean: + case CK_IntegralToBoolean: + case CK_FloatingToBoolean: + case CK_MemberPointerToBoolean: + case CK_FloatingComplexToBoolean: + case CK_IntegralComplexToBoolean: + case CK_LValueBitCast: // -> bool& + case CK_UserDefinedConversion: // operator bool() + CheckNoBasePath: + assert(path_empty() && "Cast kind should not have a base path!"); + break; + } +} + const char *CastExpr::getCastKindName() const { switch (getCastKind()) { case CK_Dependent: @@ -1077,8 +1164,10 @@ const char *CastExpr::getCastKindName() const { return "FloatingToBoolean"; case CK_MemberPointerToBoolean: return "MemberPointerToBoolean"; - case CK_AnyPointerToObjCPointerCast: - return "AnyPointerToObjCPointerCast"; + case CK_CPointerToObjCPointerCast: + return "CPointerToObjCPointerCast"; + case CK_BlockPointerToObjCPointerCast: + return "BlockPointerToObjCPointerCast"; case CK_AnyPointerToBlockPointerCast: return "AnyPointerToBlockPointerCast"; case CK_ObjCObjectLValueCast: diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index ce7aca9337..eb35dd7c98 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -674,7 +674,8 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { case CK_NoOp: case CK_BitCast: - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: return Visit(SubExpr); @@ -1808,7 +1809,8 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_VectorSplat: case CK_IntegralToFloating: case CK_FloatingCast: - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_FloatingRealToComplex: @@ -2325,7 +2327,8 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_FloatingToIntegral: case CK_FloatingToBoolean: case CK_FloatingCast: - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_FloatingComplexToReal: diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 16aeb45162..ca58ec05ac 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -833,14 +833,16 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const { const Type *T = CanonicalType.getTypePtr(); if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) { if (BT->getKind() == BuiltinType::Bool) return STK_Bool; - if (BT->getKind() == BuiltinType::NullPtr) return STK_Pointer; + if (BT->getKind() == BuiltinType::NullPtr) return STK_CPointer; if (BT->isInteger()) return STK_Integral; if (BT->isFloatingPoint()) return STK_Floating; llvm_unreachable("unknown scalar builtin type"); - } else if (isa<PointerType>(T) || - isa<BlockPointerType>(T) || - isa<ObjCObjectPointerType>(T)) { - return STK_Pointer; + } else if (isa<PointerType>(T)) { + return STK_CPointer; + } else if (isa<BlockPointerType>(T)) { + return STK_BlockPointer; + } else if (isa<ObjCObjectPointerType>(T)) { + return STK_ObjCObjectPointer; } else if (isa<MemberPointerType>(T)) { return STK_MemberPointer; } else if (isa<EnumType>(T)) { @@ -853,7 +855,6 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const { } llvm_unreachable("unknown scalar type"); - return STK_Pointer; } /// \brief Determines whether the type is a C++ aggregate type or C diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 9364ade96d..daaf7a5887 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -2077,7 +2077,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_ConstructorConversion: case CK_UserDefinedConversion: - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: return EmitLValue(E->getSubExpr()); case CK_UncheckedDerivedToBase: diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index bd788d0b0a..fe6dfcd28f 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -365,7 +365,8 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { case CK_FloatingToIntegral: case CK_FloatingToBoolean: case CK_FloatingCast: - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_FloatingRealToComplex: diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index c7b9a30716..90e288a450 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -403,7 +403,8 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op, case CK_FloatingToIntegral: case CK_FloatingToBoolean: case CK_FloatingCast: - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_FloatingComplexToReal: diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 5c15ec470f..b51ff38656 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -571,7 +571,8 @@ public: case CK_NoOp: return C; - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_LValueBitCast: case CK_BitCast: diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index f4a2695ec9..35876d8c31 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1028,7 +1028,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy)); } - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_BitCast: { Value *Src = Visit(const_cast<Expr*>(E)); diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 01748ee825..17ace4fc1a 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -1997,7 +1997,8 @@ tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) { // These casts can change the type, so remember that and // soldier on. We only need to remember the outermost such // cast, though. - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_BitCast: if (!resultType) diff --git a/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp index 645883606a..83eba54c9d 100644 --- a/lib/Rewrite/RewriteObjC.cpp +++ b/lib/Rewrite/RewriteObjC.cpp @@ -1854,9 +1854,15 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { std::string syncBuf; syncBuf += " objc_sync_exit("; - Expr *syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), - CK_BitCast, - S->getSynchExpr()); + + Expr *syncExpr = S->getSynchExpr(); + CastKind CK = syncExpr->getType()->isObjCObjectPointerType() + ? CK_BitCast : + syncExpr->getType()->isBlockPointerType() + ? CK_BlockPointerToObjCPointerCast + : CK_CPointerToObjCPointerCast; + syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), + CK, syncExpr); std::string syncExprBufS; llvm::raw_string_ostream syncExprBuf(syncExprBufS); syncExpr->printPretty(syncExprBuf, *Context, 0, @@ -2709,7 +2715,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { SourceLocation()); // cast to NSConstantString * CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), - CK_BitCast, Unop); + CK_CPointerToObjCPointerCast, Unop); ReplaceStmt(Exp, cast); // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. return cast; @@ -2849,7 +2855,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, // (Class)objc_getClass("CurrentClass") CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCClassType(), - CK_BitCast, Cls); + CK_CPointerToObjCPointerCast, Cls); ClsExprs.clear(); ClsExprs.push_back(ArgExpr); Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, @@ -3051,19 +3057,41 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, // Make sure we convert "type (^)(...)" to "type (*)(...)". (void)convertBlockPointerToFunctionPointer(type); const Expr *SubExpr = ICE->IgnoreParenImpCasts(); - bool integral = SubExpr->getType()->isIntegralType(*Context); - userExpr = NoTypeInfoCStyleCastExpr(Context, type, - (integral && type->isBooleanType()) - ? CK_IntegralToBoolean : CK_BitCast, - userExpr); + CastKind CK; + if (SubExpr->getType()->isIntegralType(*Context) && + type->isBooleanType()) { + CK = CK_IntegralToBoolean; + } else if (type->isObjCObjectPointerType()) { + if (SubExpr->getType()->isBlockPointerType()) { + CK = CK_BlockPointerToObjCPointerCast; + } else if (SubExpr->getType()->isPointerType()) { + CK = CK_CPointerToObjCPointerCast; + } else { + CK = CK_BitCast; + } + } else { + CK = CK_BitCast; + } + + userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr); } // Make id<P...> cast into an 'id' cast. else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) { if (CE->getType()->isObjCQualifiedIdType()) { while ((CE = dyn_cast<CStyleCastExpr>(userExpr))) userExpr = CE->getSubExpr(); + CastKind CK; + if (userExpr->getType()->isIntegralType(*Context)) { + CK = CK_IntegralToPointer; + } else if (userExpr->getType()->isBlockPointerType()) { + CK = CK_BlockPointerToObjCPointerCast; + } else if (userExpr->getType()->isPointerType()) { + CK = CK_CPointerToObjCPointerCast; + } else { + CK = CK_BitCast; + } userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), - CK_BitCast, userExpr); + CK, userExpr); } } MsgExprs.push_back(userExpr); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 7bd0a4a330..4e4f80bd0b 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -261,7 +261,9 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) { switch (ScalarTy->getScalarTypeKind()) { case Type::STK_Bool: return CK_NoOp; - case Type::STK_Pointer: return CK_PointerToBoolean; + case Type::STK_CPointer: return CK_PointerToBoolean; + case Type::STK_BlockPointer: return CK_PointerToBoolean; + case Type::STK_ObjCObjectPointer: return CK_PointerToBoolean; case Type::STK_MemberPointer: return CK_MemberPointerToBoolean; case Type::STK_Integral: return CK_IntegralToBoolean; case Type::STK_Floating: return CK_FloatingToBoolean; diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 708433f62c..48f022063a 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -871,7 +871,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, else if (DestType->isObjCObjectPointerType()) { // allow both c-style cast and static_cast of objective-c pointers as // they are pervasive. - Kind = CK_AnyPointerToObjCPointerCast; + Kind = CK_CPointerToObjCPointerCast; return TC_Success; } else if (CStyle && DestType->isBlockPointerType()) { @@ -1630,16 +1630,34 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, (DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType())) return TC_NotApplicable; + if (IsLValueCast) { + Kind = CK_LValueBitCast; + } else if (DestType->isObjCObjectPointerType()) { + if (SrcType->isObjCObjectPointerType()) { + Kind = CK_BitCast; + } else if (SrcType->isBlockPointerType()) { + Kind = CK_BlockPointerToObjCPointerCast; + } else { + Kind = CK_CPointerToObjCPointerCast; + } + } else if (DestType->isBlockPointerType()) { + if (!SrcType->isBlockPointerType()) { + Kind = CK_AnyPointerToBlockPointerCast; + } else { + Kind = CK_BitCast; + } + } else { + Kind = CK_BitCast; + } + // Any pointer can be cast to an Objective-C pointer type with a C-style // cast. if (CStyle && DestType->isObjCObjectPointerType()) { - Kind = CK_AnyPointerToObjCPointerCast; return TC_Success; } // Not casting away constness, so the only remaining check is for compatible // pointer categories. - Kind = IsLValueCast? CK_LValueBitCast : CK_BitCast; if (SrcType->isFunctionPointerType()) { if (DestType->isFunctionPointerType()) { diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 8dfdeb4b60..94de7992ba 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1767,11 +1767,16 @@ static bool matchTypes(ASTContext &Context, Sema::MethodMatchStrategy strategy, if (!left->isScalarType() || !right->isScalarType()) return tryMatchRecordTypes(Context, strategy, left, right); - // Make scalars agree in kind, except count bools as chars. + // Make scalars agree in kind, except count bools as chars, and group + // all non-member pointers together. Type::ScalarTypeKind leftSK = left->getScalarTypeKind(); Type::ScalarTypeKind rightSK = right->getScalarTypeKind(); if (leftSK == Type::STK_Bool) leftSK = Type::STK_Integral; if (rightSK == Type::STK_Bool) rightSK = Type::STK_Integral; + if (leftSK == Type::STK_CPointer || leftSK == Type::STK_BlockPointer) + leftSK = Type::STK_ObjCObjectPointer; + if (rightSK == Type::STK_CPointer || rightSK == Type::STK_BlockPointer) + rightSK = Type::STK_ObjCObjectPointer; // Note that data member pointers and function member pointers don't // intermix because of the size differences. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d20dee44d3..f10bb3413c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3808,16 +3808,26 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { if (S.Context.hasSameUnqualifiedType(SrcTy, DestTy)) return CK_NoOp; - switch (SrcTy->getScalarTypeKind()) { + switch (Type::ScalarTypeKind SrcKind = SrcTy->getScalarTypeKind()) { case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); - case Type::STK_Pointer: + case Type::STK_CPointer: + case Type::STK_BlockPointer: + case Type::STK_ObjCObjectPointer: switch (DestTy->getScalarTypeKind()) { - case Type::STK_Pointer: - return DestTy->isObjCObjectPointerType() ? - CK_AnyPointerToObjCPointerCast : - CK_BitCast; + case Type::STK_CPointer: + return CK_BitCast; + case Type::STK_BlockPointer: + return (SrcKind == Type::STK_BlockPointer + ? CK_BitCast : CK_AnyPointerToBlockPointerCast); + case Type::STK_ObjCObjectPointer: + if (SrcKind == Type::STK_ObjCObjectPointer) + return CK_BitCast; + else if (SrcKind == Type::STK_CPointer) + return CK_CPointerToObjCPointerCast; + else + return CK_BlockPointerToObjCPointerCast; case Type::STK_Bool: return CK_PointerToBoolean; case Type::STK_Integral: @@ -3833,7 +3843,9 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { case Type::STK_Bool: // casting from bool is like casting from an integer case Type::STK_Integral: switch (DestTy->getScalarTypeKind()) { - case Type::STK_Pointer: + case Type::STK_CPointer: + case Type::STK_ObjCObjectPointer: + case Type::STK_BlockPointer: if (Src.get()->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull)) return CK_NullToPointer; @@ -3877,7 +3889,9 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { DestTy->getAs<ComplexType>()->getElementType(), CK_FloatingToIntegral); return CK_IntegralRealToComplex; - case Type::STK_Pointer: + case Type::STK_CPointer: + case Type::STK_ObjCObjectPointer: + case Type::STK_BlockPointer: llvm_unreachable("valid float->pointer cast?"); case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); @@ -3904,7 +3918,9 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { SrcTy->getAs<ComplexType>()->getElementType(), CK_FloatingComplexToReal); return CK_FloatingToIntegral; - case Type::STK_Pointer: + case Type::STK_CPointer: + case Type::STK_ObjCObjectPointer: + case Type::STK_BlockPointer: llvm_unreachable("valid complex float->pointer cast?"); case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); @@ -3931,7 +3947,9 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { SrcTy->getAs<ComplexType>()->getElementType(), CK_IntegralComplexToReal); return CK_IntegralToFloating; - case Type::STK_Pointer: + case Type::STK_CPointer: + case Type::STK_ObjCObjectPointer: + case Type::STK_BlockPointer: llvm_unreachable("valid complex int->pointer cast?"); case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); @@ -3940,7 +3958,6 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { } llvm_unreachable("Unhandled scalar cast"); - return CK_BitCast; } /// CheckCastTypes - Check type constraints for casting between types. @@ -4497,12 +4514,12 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, QualType lhptee, rhptee; // Get the pointee types. - if (LHSTy->isBlockPointerType()) { - lhptee = LHSTy->getAs<BlockPointerType>()->getPointeeType(); - rhptee = RHSTy->getAs<BlockPointerType>()->getPointeeType(); + if (const BlockPointerType *LHSBTy = LHSTy->getAs<BlockPointerType>()) { + lhptee = LHSBTy->getPointeeType(); + rhptee = RHSTy->castAs<BlockPointerType>()->getPointeeType(); } else { - lhptee = LHSTy->getAs<PointerType>()->getPointeeType(); - rhptee = RHSTy->getAs<PointerType>()->getPointeeType(); + lhptee = LHSTy->castAs<PointerType>()->getPointeeType(); + rhptee = RHSTy->castAs<PointerType>()->getPointeeType(); } if (!S.Context.typesAreCompatible(lhptee.getUnqualifiedType(), @@ -4752,23 +4769,23 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, // redefinition type if an attempt is made to access its fields. if (LHSTy->isObjCClassType() && (Context.hasSameType(RHSTy, Context.getObjCClassRedefinitionType()))) { - RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_CPointerToObjCPointerCast); return LHSTy; } if (RHSTy->isObjCClassType() && (Context.hasSameType(LHSTy, Context.getObjCClassRedefinitionType()))) { - LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_CPointerToObjCPointerCast); return RHSTy; } // And the same for struct objc_object* / id if (LHSTy->isObjCIdType() && (Context.hasSameType(RHSTy, Context.getObjCIdRedefinitionType()))) { - RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_CPointerToObjCPointerCast); return LHSTy; } if (RHSTy->isObjCIdType() && (Context.hasSameType(LHSTy, Context.getObjCIdRedefinitionType()))) { - LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_CPointerToObjCPointerCast); return RHSTy; } // And the same for struct objc_selector* / SEL @@ -4789,8 +4806,8 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult & |