diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5e30b2edeaca..557626c0014b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3854,12 +3854,20 @@ def err_arc_cast_requires_bridge : Error< "requires a bridged cast">; def note_arc_bridge : Note< "use __bridge to convert directly (no change in ownership)">; +def note_arc_cstyle_bridge : Note< + "use __bridge with C-style cast to convert directly (no change in ownership)">; def note_arc_bridge_transfer : Note< "use %select{__bridge_transfer|CFBridgingRelease call}1 to transfer " "ownership of a +1 %0 into ARC">; +def note_arc_cstyle_bridge_transfer : Note< + "use __bridge_transfer with C-style cast to transfer " + "ownership of a +1 %0 into ARC">; def note_arc_bridge_retained : Note< "use %select{__bridge_retained|CFBridgingRetain call}1 to make an " "ARC object available as a +1 %0">; +def note_arc_cstyle_bridge_retained : Note< + "use __bridge_retained with C-style cast to make an " + "ARC object available as a +1 %0">; } // ARC Casting category diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index c0df31868aa4..2dbba853e405 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -2925,15 +2925,22 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, assert(CreateRule != ACC_bottom && "This cast should already be accepted."); if (CreateRule != ACC_plusOne) { - DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); + DiagnosticBuilder DiagB = + (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge) + : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, castType, castExpr, "__bridge ", 0); } if (CreateRule != ACC_plusZero) { - DiagnosticBuilder DiagB = S.Diag(br ? castExpr->getExprLoc() : noteLoc, - diag::note_arc_bridge_transfer) - << castExprType << br; + DiagnosticBuilder DiagB = + (CCK == Sema::CCK_OtherCast && !br) ? + S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer) << castExprType : + S.Diag(br ? castExpr->getExprLoc() : noteLoc, + diag::note_arc_bridge_transfer) + << castExprType << br; + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, castType, castExpr, "__bridge_transfer ", br ? "CFBridgingRelease" : 0); @@ -2958,15 +2965,21 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, assert(CreateRule != ACC_bottom && "This cast should already be accepted."); if (CreateRule != ACC_plusOne) { - DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); + DiagnosticBuilder DiagB = + (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge) + : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, castType, castExpr, "__bridge ", 0); } if (CreateRule != ACC_plusZero) { - DiagnosticBuilder DiagB = S.Diag(br ? castExpr->getExprLoc() : noteLoc, - diag::note_arc_bridge_retained) - << castType << br; + DiagnosticBuilder DiagB = + (CCK == Sema::CCK_OtherCast && !br) ? + S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained) << castType : + S.Diag(br ? castExpr->getExprLoc() : noteLoc, + diag::note_arc_bridge_retained) + << castType << br; + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, castType, castExpr, "__bridge_retained ", br ? "CFBridgingRetain" : 0); diff --git a/clang/test/SemaObjCXX/arc-unbridged-cast.mm b/clang/test/SemaObjCXX/arc-unbridged-cast.mm index f7d239148704..3f7f76da5be2 100644 --- a/clang/test/SemaObjCXX/arc-unbridged-cast.mm +++ b/clang/test/SemaObjCXX/arc-unbridged-cast.mm @@ -108,3 +108,12 @@ void testTakerFunctions(id string) { takeCFVariadicAudited(1, (CFStringRef) string); takeCFConsumedAudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRetain call to}} } + +// rdar://12788838 +id obj; + +void rdar12788838() { + void *foo = reinterpret_cast(obj); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'void *' requires a bridged cast}} \ + // expected-note {{use __bridge with C-style cast to convert directly}} \ + // expected-note {{use CFBridgingRetain call to make an ARC object available as a +1 'void *'}} +}