aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ARCMigrate/Internals.h4
-rw-r--r--lib/ARCMigrate/TransUnbridgedCasts.cpp54
-rw-r--r--lib/ARCMigrate/Transforms.cpp8
-rw-r--r--lib/Sema/SemaExprObjC.cpp17
4 files changed, 58 insertions, 25 deletions
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<SourceLocation> &ARCMTMacroLocs;
+ llvm::Optional<bool> 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<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(), ")");
}
}
}
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