From: Fariborz Jahanian Date: Tue, 31 Jan 2012 21:58:23 +0000 (+0000) Subject: arc migrator: Do not attempt to migrate to bridge casts which X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2908ffbc5f54323f150405fa2b06f50788ae55c7;p=clang arc migrator: Do not attempt to migrate to bridge casts which cancel out each other. Leave it alone so users can take a look (unmigrated code forces error diagnostic). // rdar://10521744 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149435 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp index 3bfa15c6e0..5650824c96 100644 --- a/lib/ARCMigrate/TransUnbridgedCasts.cpp +++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp @@ -128,6 +128,21 @@ private: if (fname.endswith("Retain") || fname.find("Create") != StringRef::npos || fname.find("Copy") != StringRef::npos) { + // Do not migrate to couple of bridge transfer casts which + // cancel each other out. Leave it unchanged so error gets user + // attention instead. + if (FD->getName() == "CFRetain" && + FD->getNumParams() == 1 && + FD->getParent()->isTranslationUnit() && + FD->getLinkage() == ExternalLinkage) { + Expr *Arg = callE->getArg(0); + if (const CastExpr *ICE = dyn_cast(Arg)) { + const Expr *sub = ICE->getSubExpr(); + QualType T = sub->getType(); + if (T->isObjCObjectPointerType()) + return; + } + } castToObjCObject(E, /*retained=*/true); return; } diff --git a/test/ARCMT/no-canceling-bridge-to-bridge-cast.m b/test/ARCMT/no-canceling-bridge-to-bridge-cast.m new file mode 100644 index 0000000000..e94e6574ae --- /dev/null +++ b/test/ARCMT/no-canceling-bridge-to-bridge-cast.m @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -arcmt-check -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -verify %s +// DISABLE: mingw32 +// rdar://10387088 +typedef const void * CFTypeRef; + +extern +CFTypeRef CFRetain(CFTypeRef cf); + +@interface INTF +{ + void *cf_format; + id objc_format; +} +@end + +@interface NSString ++ (id)stringWithFormat:(NSString *)format; +@end + +@implementation INTF +- (void) Meth { + NSString *result; + + result = (id) CFRetain([NSString stringWithFormat:@"PBXLoopMode"]); // expected-error {{cast of C pointer type 'CFTypeRef' (aka 'const void *') to Objective-C pointer type 'id' requires a bridged cast}} \ + // expected-note {{use __bridge to convert directly (no change in ownership)}} \ + // expected-note {{use __bridge_transfer to transfer ownership of a +1 'CFTypeRef' (aka 'const void *') into ARC}} + + result = (id) CFRetain((id)((objc_format))); // expected-error {{cast of C pointer type 'CFTypeRef' (aka 'const void *') to Objective-C pointer type 'id' requires a bridged cast}} \ + // expected-note {{use __bridge to convert directly (no change in ownership)}} \ + // expected-note {{use __bridge_transfer to transfer ownership of a +1 'CFTypeRef' (aka 'const void *') into ARC}} + + result = (id) CFRetain((id)((cf_format))); // expected-error {{cast of C pointer type 'CFTypeRef' (aka 'const void *') to Objective-C pointer type 'id' requires a bridged cast}} \ + // expected-note {{use __bridge to convert directly (no change in ownership)}} \ + // expected-note {{use __bridge_transfer to transfer ownership of a +1 'CFTypeRef' (aka 'const void *') into ARC}} + + result = (id) CFRetain((CFTypeRef)((objc_format))); // expected-error {{cast of C pointer type 'CFTypeRef' (aka 'const void *') to Objective-C pointer type 'id' requires a bridged cast}} \ + // expected-note {{use __bridge to convert directly (no change in ownership)}} \ + // expected-note {{use __bridge_transfer to transfer ownership of a +1 'CFTypeRef' (aka 'const void *') into ARC}} + + result = (id) CFRetain(cf_format); // OK +} +@end +