LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R,
ArrayRef<QualType> ArgTys,
bool AllowRawAndTemplate);
+ bool isKnownName(StringRef name);
void ArgumentDependentLookup(DeclarationName Name, bool Operator,
SourceLocation Loc,
#include "clang/ARCMigrate/ARCMT.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
namespace clang {
class Sema;
Sema &SemaRef;
TransformActions &TA;
std::vector<SourceLocation> &ARCMTMacroLocs;
+ llvm::Optional<bool> EnableCFBridgeFns;
MigrationPass(ASTContext &Ctx, LangOptions::GCMode OrigGCMode,
Sema &sema, TransformActions &TA,
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() {
// 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;
// ---->
// 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.
//
TA.clearDiagnostic(diag::err_arc_mismatched_cast,
diag::err_arc_cast_requires_bridge,
E->getLocStart());
- if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(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<ParenExpr>(E->getSubExpr())) {
- TA.insert(insertLoc, newCast.str());
+ if (Kind == OBC_Bridge || !Pass.CFBridgingFunctionsDefined()) {
+ if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(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<ParenExpr>(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<ParenExpr>(WrapE)) {
+ TA.insert(insertLoc, cfBridging);
+ } else {
+ std::string withParens = cfBridging;
+ withParens += '(';
+ TA.insert(insertLoc, withParens);
+ TA.insertAfterToken(WrapE->getLocEnd(), ")");
}
}
}
#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"
ASTTraverser::~ASTTraverser() { }
+bool MigrationPass::CFBridgingFunctionsDefined() {
+ if (!EnableCFBridgeFns.hasValue())
+ EnableCFBridgeFns = SemaRef.isKnownName("CFBridgingRetain") &&
+ SemaRef.isKnownName("CFBridgingRelease");
+ return *EnableCFBridgeFns;
+}
+
//===----------------------------------------------------------------------===//
// Helpers.
//===----------------------------------------------------------------------===//
};
}
-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,
<< 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,
// 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
break;
case OBC_BridgeRetained: {
- bool br = KnownName(*this, "CFBridgingRelease");
+ bool br = isKnownName("CFBridgingRelease");
Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)
<< 2
<< FromType
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
#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)
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;
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
_prop = newVal;
}
-(void) setProp2:(CFTypeRef) newVal {
- _prop = (__bridge_transfer id)CFRetain(newVal);
+ _prop = (id)CFBridgingRelease(CFRetain(newVal));
}
-(id) xpc_prop {
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)
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));
}