From: Argyrios Kyrtzidis Date: Fri, 1 Jun 2012 00:10:47 +0000 (+0000) Subject: [arcmt] Use CFBridgingRetain/CFBridgingRelease instead of __bridge_retained/__bridge_... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=684190b8dbe5258f4708ffbd816b8c5ee5b3502d;p=clang [arcmt] Use CFBridgingRetain/CFBridgingRelease instead of __bridge_retained/__bridge_transfer when migrating. rdar://11569198 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157785 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 80bfde4ca3..ff974f7d48 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2107,6 +2107,7 @@ public: LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef ArgTys, bool AllowRawAndTemplate); + bool isKnownName(StringRef name); void ArgumentDependentLookup(DeclarationName Name, bool Operator, SourceLocation Loc, diff --git a/lib/ARCMigrate/Internals.h b/lib/ARCMigrate/Internals.h index 59177c483e..935fc9b525 100644 --- a/lib/ARCMigrate/Internals.h +++ b/lib/ARCMigrate/Internals.h @@ -12,6 +12,7 @@ #include "clang/ARCMigrate/ARCMT.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" namespace clang { class Sema; @@ -144,6 +145,7 @@ public: Sema &SemaRef; TransformActions &TA; std::vector &ARCMTMacroLocs; + llvm::Optional EnableCFBridgeFns; MigrationPass(ASTContext &Ctx, LangOptions::GCMode OrigGCMode, Sema &sema, TransformActions &TA, @@ -157,6 +159,8 @@ public: void setNSAllocReallocError(bool val) { MigOptions.NoNSAllocReallocError = val; } bool noFinalizeRemoval() const { return MigOptions.NoFinalizeRemoval; } void setNoFinalizeRemoval(bool val) {MigOptions.NoFinalizeRemoval = val; } + + bool CFBridgingFunctionsDefined(); }; static inline StringRef getARCMTMacroName() { diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp index 48437c795f..37cebc9e3a 100644 --- a/lib/ARCMigrate/TransUnbridgedCasts.cpp +++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp @@ -12,7 +12,7 @@ // A cast of non-objc pointer to an objc one is checked. If the non-objc pointer // is from a file-level variable, __bridge cast is used to convert it. // For the result of a function call that we know is +1/+0, -// __bridge/__bridge_transfer is used. +// __bridge/CFBridgingRelease is used. // // NSString *str = (NSString *)kUTTypePlainText; // str = b ? kUTTypeRTF : kUTTypePlainText; @@ -21,8 +21,8 @@ // ----> // NSString *str = (__bridge NSString *)kUTTypePlainText; // str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText); -// NSString *_uuidString = (__bridge_transfer NSString *) -// CFUUIDCreateString(kCFAllocatorDefault, _uuid); +// NSString *_uuidString = (NSString *) +// CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid)); // // For a C pointer to ObjC, for casting 'self', __bridge is used. // @@ -191,22 +191,42 @@ private: 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(), bridge); - } else { - SourceLocation insertLoc = E->getSubExpr()->getLocStart(); - SmallString<128> newCast; - newCast += '('; - newCast += bridge; - newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy()); - newCast += ')'; - - if (isa(E->getSubExpr())) { - TA.insert(insertLoc, newCast.str()); + if (Kind == OBC_Bridge || !Pass.CFBridgingFunctionsDefined()) { + if (CStyleCastExpr *CCE = dyn_cast(E)) { + TA.insertAfterToken(CCE->getLParenLoc(), bridge); } else { + SourceLocation insertLoc = E->getSubExpr()->getLocStart(); + SmallString<128> newCast; newCast += '('; - TA.insert(insertLoc, newCast.str()); - TA.insertAfterToken(E->getLocEnd(), ")"); + newCast += bridge; + newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy()); + newCast += ')'; + + if (isa(E->getSubExpr())) { + TA.insert(insertLoc, newCast.str()); + } else { + newCast += '('; + TA.insert(insertLoc, newCast.str()); + TA.insertAfterToken(E->getLocEnd(), ")"); + } + } + } else { + assert(Kind == OBC_BridgeTransfer || Kind == OBC_BridgeRetained); + StringRef cfBridging; + if (Kind == OBC_BridgeTransfer) + cfBridging = "CFBridgingRelease"; + else + cfBridging = "CFBridgingRetain"; + + Expr *WrapE = E->getSubExpr(); + SourceLocation insertLoc = WrapE->getLocStart(); + if (isa(WrapE)) { + TA.insert(insertLoc, cfBridging); + } else { + std::string withParens = cfBridging; + withParens += '('; + TA.insert(insertLoc, withParens); + TA.insertAfterToken(WrapE->getLocEnd(), ")"); } } } diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp index 24b650561c..71598362b5 100644 --- a/lib/ARCMigrate/Transforms.cpp +++ b/lib/ARCMigrate/Transforms.cpp @@ -10,6 +10,7 @@ #include "Transforms.h" #include "Internals.h" #include "clang/Sema/SemaDiagnostic.h" +#include "clang/Sema/Sema.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/Lex/Lexer.h" @@ -25,6 +26,13 @@ using namespace trans; ASTTraverser::~ASTTraverser() { } +bool MigrationPass::CFBridgingFunctionsDefined() { + if (!EnableCFBridgeFns.hasValue()) + EnableCFBridgeFns = SemaRef.isKnownName("CFBridgingRetain") && + SemaRef.isKnownName("CFBridgingRelease"); + return *EnableCFBridgeFns; +} + //===----------------------------------------------------------------------===// // Helpers. //===----------------------------------------------------------------------===// diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index c1f7aae0a2..5ee3c7b8c9 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -2771,11 +2771,12 @@ namespace { }; } -static bool -KnownName(Sema &S, const char *name) { - LookupResult R(S, &S.Context.Idents.get(name), SourceLocation(), +bool Sema::isKnownName(StringRef name) { + if (name.empty()) + return false; + LookupResult R(*this, &Context.Idents.get(name), SourceLocation(), Sema::LookupOrdinaryName); - return S.LookupName(R, S.TUScope, false); + return LookupName(R, TUScope, false); } static void addFixitForObjCARCConversion(Sema &S, @@ -2884,7 +2885,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, << castType << castRange << castExpr->getSourceRange(); - bool br = KnownName(S, "CFBridgingRelease"); + bool br = S.isKnownName("CFBridgingRelease"); { DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, @@ -2903,7 +2904,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, // Bridge from a CF type to an ARC type. if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) { - bool br = KnownName(S, "CFBridgingRetain"); + bool br = S.isKnownName("CFBridgingRetain"); S.Diag(loc, diag::err_arc_cast_requires_bridge) << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit << unsigned(castExprType->isBlockPointerType()) // of ObjC|block type @@ -3156,7 +3157,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, break; case OBC_BridgeRetained: { - bool br = KnownName(*this, "CFBridgingRelease"); + bool br = isKnownName("CFBridgingRelease"); Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind) << 2 << FromType @@ -3199,7 +3200,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, break; case OBC_BridgeTransfer: { - bool br = KnownName(*this, "CFBridgingRetain"); + bool br = isKnownName("CFBridgingRetain"); Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind) << (FromType->isBlockPointerType()? 1 : 0) << FromType diff --git a/test/ARCMT/Common.h b/test/ARCMT/Common.h index 708e407c92..ed48949702 100644 --- a/test/ARCMT/Common.h +++ b/test/ARCMT/Common.h @@ -6,6 +6,7 @@ #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) #define CF_CONSUMED __attribute__((cf_consumed)) +#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) #define NS_INLINE static __inline__ __attribute__((always_inline)) #define nil ((void*) 0) @@ -21,7 +22,7 @@ typedef struct _NSZone NSZone; typedef const void * CFTypeRef; CFTypeRef CFRetain(CFTypeRef cf); -id CFBridgingRelease(CFTypeRef CF_CONSUMED X); +CFTypeRef CFMakeCollectable(CFTypeRef cf) NS_AUTOMATED_REFCOUNT_UNAVAILABLE; NS_INLINE NS_RETURNS_RETAINED id NSMakeCollectable(CFTypeRef CF_CONSUMED cf) NS_AUTOMATED_REFCOUNT_UNAVAILABLE; @@ -79,3 +80,25 @@ typedef id xpc_object_t; void _dispatch_object_validate(dispatch_object_t object); void _xpc_object_validate(xpc_object_t object); + +#if __has_feature(objc_arc) + +NS_INLINE CF_RETURNS_RETAINED CFTypeRef CFBridgingRetain(id X) { + return (__bridge_retained CFTypeRef)X; +} + +NS_INLINE id CFBridgingRelease(CFTypeRef CF_CONSUMED X) { + return (__bridge_transfer id)X; +} + +#else + +NS_INLINE CF_RETURNS_RETAINED CFTypeRef CFBridgingRetain(id X) { + return X ? CFRetain((CFTypeRef)X) : NULL; +} + +NS_INLINE id CFBridgingRelease(CFTypeRef CF_CONSUMED X) { + return [(id)CFMakeCollectable(X) autorelease]; +} + +#endif diff --git a/test/ARCMT/autoreleases.m.result b/test/ARCMT/autoreleases.m.result index 93ec9717dd..6593fc9199 100644 --- a/test/ARCMT/autoreleases.m.result +++ b/test/ARCMT/autoreleases.m.result @@ -35,7 +35,7 @@ _prop = newVal; } -(void) setProp2:(CFTypeRef) newVal { - _prop = (__bridge_transfer id)CFRetain(newVal); + _prop = (id)CFBridgingRelease(CFRetain(newVal)); } -(id) xpc_prop { diff --git a/test/ARCMT/nonobjc-to-objc-cast.m.result b/test/ARCMT/nonobjc-to-objc-cast.m.result index b50a948e27..0a3b2bb526 100644 --- a/test/ARCMT/nonobjc-to-objc-cast.m.result +++ b/test/ARCMT/nonobjc-to-objc-cast.m.result @@ -28,9 +28,9 @@ void f(BOOL b, id p) { str = (NSString *)p; // no change. CFUUIDRef _uuid; - NSString *_uuidString = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid); - _uuidString = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid); - _uuidString = (__bridge_transfer NSString *)(CFRetain(_uuid)); + NSString *_uuidString = (NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid)); + _uuidString = (NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid)); + _uuidString = CFBridgingRelease(CFRetain(_uuid)); } @implementation NSString (StrExt) @@ -47,16 +47,16 @@ void f2(NSString *s) { CFStringRef ref = (__bridge CFStringRef)([s string]); ref = (__bridge CFStringRef)[s string]; ref = (__bridge CFStringRef)(s.string); - ref = (__bridge_retained CFStringRef)([NSString new]); - ref = (__bridge_retained CFStringRef)([s newString]); - ref = (__bridge_retained CFStringRef)[NSString new]; - ref = (__bridge_retained CFStringRef)([[NSString alloc] init]); - ref = (__bridge_retained CFStringRef)([s string]); - ref = (__bridge_retained CFStringRef)[s string]; - ref = (__bridge_retained CFTypeRef)([s string]); - ref = (__bridge_retained CFTypeRef)(s); - ref = (__bridge_retained CFStringRef)(s); - - consumeParam((__bridge_retained CFStringRef)s); - consumeParam((__bridge_retained CFStringRef)(s)); + ref = CFBridgingRetain([NSString new]); + ref = CFBridgingRetain([s newString]); + ref = (CFStringRef)CFBridgingRetain([NSString new]); + ref = CFBridgingRetain([[NSString alloc] init]); + ref = CFBridgingRetain([s string]); + ref = (CFStringRef)CFBridgingRetain([s string]); + ref = CFBridgingRetain([s string]); + ref = CFBridgingRetain(s); + ref = CFBridgingRetain(s); + + consumeParam((CFStringRef)CFBridgingRetain(s)); + consumeParam(CFBridgingRetain(s)); }