[arcmt] Always add '__bridge' cast when 'self' is cast to a C pointer. rdar://9644061

llvm-svn: 133480
This commit is contained in:
Argyrios Kyrtzidis 2011-06-20 23:39:20 +00:00
parent 91da589d7e
commit 0a9d652331
3 changed files with 45 additions and 37 deletions

View File

@ -453,8 +453,11 @@ namespace {
class NonObjCToObjCCaster : public RecursiveASTVisitor<NonObjCToObjCCaster> { class NonObjCToObjCCaster : public RecursiveASTVisitor<NonObjCToObjCCaster> {
MigrationPass &Pass; MigrationPass &Pass;
IdentifierInfo *SelfII;
public: public:
NonObjCToObjCCaster(MigrationPass &pass) : Pass(pass) { } NonObjCToObjCCaster(MigrationPass &pass) : Pass(pass) {
SelfII = &Pass.Ctx.Idents.get("self");
}
bool VisitCastExpr(CastExpr *E) { bool VisitCastExpr(CastExpr *E) {
if (E->getCastKind() != CK_AnyPointerToObjCPointerCast if (E->getCastKind() != CK_AnyPointerToObjCPointerCast
@ -538,6 +541,10 @@ private:
} }
void castToObjCObject(CastExpr *E, bool retained) { void castToObjCObject(CastExpr *E, bool retained) {
rewriteToBridgedCast(E, retained ? OBC_BridgeTransfer : OBC_Bridge);
}
void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) {
TransformActions &TA = Pass.TA; TransformActions &TA = Pass.TA;
// We will remove the compiler diagnostic. // We will remove the compiler diagnostic.
@ -546,18 +553,27 @@ private:
E->getLocStart())) E->getLocStart()))
return; 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); Transaction Trans(TA);
TA.clearDiagnostic(diag::err_arc_mismatched_cast, TA.clearDiagnostic(diag::err_arc_mismatched_cast,
diag::err_arc_cast_requires_bridge, diag::err_arc_cast_requires_bridge,
E->getLocStart()); E->getLocStart());
if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) { if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) {
TA.insertAfterToken(CCE->getLParenLoc(), retained ? "__bridge_transfer " TA.insertAfterToken(CCE->getLParenLoc(), bridge);
: "__bridge ");
} else { } else {
SourceLocation insertLoc = E->getSubExpr()->getLocStart(); SourceLocation insertLoc = E->getSubExpr()->getLocStart();
llvm::SmallString<128> newCast; llvm::SmallString<128> newCast;
newCast += '('; newCast += '(';
newCast += retained ? "__bridge_transfer " : "__bridge "; newCast += bridge;
newCast += E->getType().getAsString(Pass.Ctx.PrintingPolicy); newCast += E->getType().getAsString(Pass.Ctx.PrintingPolicy);
newCast += ')'; newCast += ')';
@ -572,36 +588,16 @@ private:
} }
void transformObjCToNonObjCCast(CastExpr *E) { void transformObjCToNonObjCCast(CastExpr *E) {
// FIXME: Handle these casts. if (isSelf(E->getSubExpr()))
return; return rewriteToBridgedCast(E, OBC_Bridge);
#if 0 }
TransformActions &TA = Pass.TA;
// We will remove the compiler diagnostic. bool isSelf(Expr *E) {
if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast, E = E->IgnoreParenLValueCasts();
diag::err_arc_cast_requires_bridge, if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
E->getLocStart())) if (DRE->getDecl()->getIdentifier() == SelfII)
return; return true;
return false;
Transaction Trans(TA);
TA.clearDiagnostic(diag::err_arc_mismatched_cast,
diag::err_arc_cast_requires_bridge,
E->getLocStart());
assert(!E->getType()->isObjCObjectPointerType());
bool shouldCast = !isa<CStyleCastExpr>(E) &&
!E->getType()->getPointeeType().isConstQualified();
SourceLocation loc = E->getSubExpr()->getLocStart();
if (isa<ParenExpr>(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
} }
static bool isGlobalVar(Expr *E) { static bool isGlobalVar(Expr *E) {

View File

@ -24,9 +24,15 @@ void f(BOOL b, id p) {
str = (NSString *)(b ? kUTTypeRTF : kUTTypePlainText); str = (NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
str = (NSString *)p; // no change. str = (NSString *)p; // no change.
// FIXME: Add objc -> c examples that we can handle.
CFUUIDRef _uuid; CFUUIDRef _uuid;
NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid); NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid);
_uuidString = [(NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid) autorelease]; _uuidString = [(NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid) autorelease];
} }
@implementation NSString (StrExt)
- (NSString *)stringEscapedAsURI {
CFStringRef str = (CFStringRef)self;
CFStringRef str2 = self;
return self;
}
@end

View File

@ -24,9 +24,15 @@ void f(BOOL b, id p) {
str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText); str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
str = (NSString *)p; // no change. str = (NSString *)p; // no change.
// FIXME: Add objc -> c examples that we can handle.
CFUUIDRef _uuid; CFUUIDRef _uuid;
NSString *_uuidString = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid); NSString *_uuidString = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, _uuid);
_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