From: Argyrios Kyrtzidis Date: Mon, 20 Jun 2011 23:39:20 +0000 (+0000) Subject: [arcmt] Always add '__bridge' cast when 'self' is cast to a C pointer. rdar://9644061 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8e2ce7fdf9e8033b77788662a9c3f61334eb5daf;p=clang [arcmt] Always add '__bridge' cast when 'self' is cast to a C pointer. rdar://9644061 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133480 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp index 0c9096296d..499c8f034c 100644 --- a/lib/ARCMigrate/Transforms.cpp +++ b/lib/ARCMigrate/Transforms.cpp @@ -453,8 +453,11 @@ namespace { class NonObjCToObjCCaster : public RecursiveASTVisitor { MigrationPass &Pass; + IdentifierInfo *SelfII; public: - NonObjCToObjCCaster(MigrationPass &pass) : Pass(pass) { } + NonObjCToObjCCaster(MigrationPass &pass) : Pass(pass) { + SelfII = &Pass.Ctx.Idents.get("self"); + } bool VisitCastExpr(CastExpr *E) { if (E->getCastKind() != CK_AnyPointerToObjCPointerCast @@ -538,6 +541,10 @@ private: } void castToObjCObject(CastExpr *E, bool retained) { + rewriteToBridgedCast(E, retained ? OBC_BridgeTransfer : OBC_Bridge); + } + + void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) { TransformActions &TA = Pass.TA; // We will remove the compiler diagnostic. @@ -546,18 +553,27 @@ private: E->getLocStart())) return; + StringRef bridge; + switch(Kind) { + case OBC_Bridge: + bridge = "__bridge "; break; + case OBC_BridgeTransfer: + bridge = "__bridge_transfer "; break; + case OBC_BridgeRetained: + bridge = "__bridge_retained "; break; + } + Transaction Trans(TA); TA.clearDiagnostic(diag::err_arc_mismatched_cast, diag::err_arc_cast_requires_bridge, E->getLocStart()); if (CStyleCastExpr *CCE = dyn_cast(E)) { - TA.insertAfterToken(CCE->getLParenLoc(), retained ? "__bridge_transfer " - : "__bridge "); + TA.insertAfterToken(CCE->getLParenLoc(), bridge); } else { SourceLocation insertLoc = E->getSubExpr()->getLocStart(); llvm::SmallString<128> newCast; newCast += '('; - newCast += retained ? "__bridge_transfer " : "__bridge "; + newCast += bridge; newCast += E->getType().getAsString(Pass.Ctx.PrintingPolicy); newCast += ')'; @@ -572,36 +588,16 @@ private: } void transformObjCToNonObjCCast(CastExpr *E) { - // FIXME: Handle these casts. - return; -#if 0 - TransformActions &TA = Pass.TA; - - // We will remove the compiler diagnostic. - if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast, - diag::err_arc_cast_requires_bridge, - E->getLocStart())) - return; - - Transaction Trans(TA); - TA.clearDiagnostic(diag::err_arc_mismatched_cast, - diag::err_arc_cast_requires_bridge, - E->getLocStart()); - - assert(!E->getType()->isObjCObjectPointerType()); + if (isSelf(E->getSubExpr())) + return rewriteToBridgedCast(E, OBC_Bridge); + } - bool shouldCast = !isa(E) && - !E->getType()->getPointeeType().isConstQualified(); - SourceLocation loc = E->getSubExpr()->getLocStart(); - if (isa(E->getSubExpr())) { - TA.insert(loc, shouldCast ? "(void*)objc_unretainedPointer" - : "objc_unretainedPointer"); - } else { - TA.insert(loc, shouldCast ? "(void*)objc_unretainedPointer(" - : "objc_unretainedPointer("); - TA.insertAfterToken(E->getLocEnd(), ")"); - } -#endif + bool isSelf(Expr *E) { + E = E->IgnoreParenLValueCasts(); + if (DeclRefExpr *DRE = dyn_cast(E)) + if (DRE->getDecl()->getIdentifier() == SelfII) + return true; + return false; } static bool isGlobalVar(Expr *E) { diff --git a/test/ARCMT/nonobjc-to-objc-cast.m b/test/ARCMT/nonobjc-to-objc-cast.m index 4ca47f2259..4e1e293efb 100644 --- a/test/ARCMT/nonobjc-to-objc-cast.m +++ b/test/ARCMT/nonobjc-to-objc-cast.m @@ -24,9 +24,15 @@ void f(BOOL b, id p) { str = (NSString *)(b ? kUTTypeRTF : kUTTypePlainText); str = (NSString *)p; // no change. - // FIXME: Add objc -> c examples that we can handle. - CFUUIDRef _uuid; NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid); _uuidString = [(NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid) autorelease]; } + +@implementation NSString (StrExt) +- (NSString *)stringEscapedAsURI { + CFStringRef str = (CFStringRef)self; + CFStringRef str2 = self; + return self; +} +@end diff --git a/test/ARCMT/nonobjc-to-objc-cast.m.result b/test/ARCMT/nonobjc-to-objc-cast.m.result index f7127b7192..53dde7553d 100644 --- a/test/ARCMT/nonobjc-to-objc-cast.m.result +++ b/test/ARCMT/nonobjc-to-objc-cast.m.result @@ -24,9 +24,15 @@ void f(BOOL b, id p) { str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText); str = (NSString *)p; // no change. - // FIXME: Add objc -> c examples that we can handle. - CFUUIDRef _uuid; NSString *_uuidString = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid); _uuidString = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid); } + +@implementation NSString (StrExt) +- (NSString *)stringEscapedAsURI { + CFStringRef str = (__bridge CFStringRef)self; + CFStringRef str2 = (__bridge CFStringRef)(self); + return self; +} +@end