1 //===--- TransUnbridgedCasts.cpp - Tranformations to ARC mode -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // rewriteUnbridgedCasts:
12 // A cast of non-objc pointer to an objc one is checked. If the non-objc pointer
13 // is from a file-level variable, __bridge cast is used to convert it.
14 // For the result of a function call that we know is +1/+0,
15 // __bridge/__bridge_transfer is used.
17 // NSString *str = (NSString *)kUTTypePlainText;
18 // str = b ? kUTTypeRTF : kUTTypePlainText;
19 // NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault,
22 // NSString *str = (__bridge NSString *)kUTTypePlainText;
23 // str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
24 // NSString *_uuidString = (__bridge_transfer NSString *)
25 // CFUUIDCreateString(kCFAllocatorDefault, _uuid);
27 // For a C pointer to ObjC, for casting 'self', __bridge is used.
29 // CFStringRef str = (CFStringRef)self;
31 // CFStringRef str = (__bridge CFStringRef)self;
33 //===----------------------------------------------------------------------===//
35 #include "Transforms.h"
36 #include "Internals.h"
37 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
38 #include "clang/Sema/SemaDiagnostic.h"
39 #include "clang/Basic/SourceManager.h"
41 using namespace clang;
42 using namespace arcmt;
43 using namespace trans;
44 using llvm::StringRef;
48 class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
50 IdentifierInfo *SelfII;
52 UnbridgedCastRewriter(MigrationPass &pass) : Pass(pass) {
53 SelfII = &Pass.Ctx.Idents.get("self");
56 bool VisitCastExpr(CastExpr *E) {
57 if (E->getCastKind() != CK_AnyPointerToObjCPointerCast
58 && E->getCastKind() != CK_BitCast)
61 QualType castType = E->getType();
62 Expr *castExpr = E->getSubExpr();
63 QualType castExprType = castExpr->getType();
65 if (castType->isObjCObjectPointerType() &&
66 castExprType->isObjCObjectPointerType())
68 if (!castType->isObjCObjectPointerType() &&
69 !castExprType->isObjCObjectPointerType())
72 bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
73 bool castRetainable = castType->isObjCIndirectLifetimeType();
74 if (exprRetainable == castRetainable) return true;
76 if (castExpr->isNullPointerConstant(Pass.Ctx,
77 Expr::NPC_ValueDependentIsNull))
80 SourceLocation loc = castExpr->getExprLoc();
81 if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc))
84 if (castType->isObjCObjectPointerType())
85 transformNonObjCToObjCCast(E);
87 transformObjCToNonObjCCast(E);
93 void transformNonObjCToObjCCast(CastExpr *E) {
96 // Global vars are assumed that are cast as unretained.
98 if (E->getSubExpr()->getType()->isPointerType()) {
99 castToObjCObject(E, /*retained=*/false);
103 // If the cast is directly over the result of a Core Foundation function
104 // try to figure out whether it should be cast as retained or unretained.
105 Expr *inner = E->IgnoreParenCasts();
106 if (CallExpr *callE = dyn_cast<CallExpr>(inner)) {
107 if (FunctionDecl *FD = callE->getDirectCallee()) {
108 if (FD->getAttr<CFReturnsRetainedAttr>()) {
109 castToObjCObject(E, /*retained=*/true);
112 if (FD->getAttr<CFReturnsNotRetainedAttr>()) {
113 castToObjCObject(E, /*retained=*/false);
116 if (FD->isGlobal() &&
117 FD->getIdentifier() &&
118 ento::cocoa::isRefType(E->getSubExpr()->getType(), "CF",
119 FD->getIdentifier()->getName())) {
120 StringRef fname = FD->getIdentifier()->getName();
121 if (fname.endswith("Retain") ||
122 fname.find("Create") != StringRef::npos ||
123 fname.find("Copy") != StringRef::npos) {
124 castToObjCObject(E, /*retained=*/true);
128 if (fname.find("Get") != StringRef::npos) {
129 castToObjCObject(E, /*retained=*/false);
137 void castToObjCObject(CastExpr *E, bool retained) {
138 rewriteToBridgedCast(E, retained ? OBC_BridgeTransfer : OBC_Bridge);
141 void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) {
142 TransformActions &TA = Pass.TA;
144 // We will remove the compiler diagnostic.
145 if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast,
146 diag::err_arc_cast_requires_bridge,
153 bridge = "__bridge "; break;
154 case OBC_BridgeTransfer:
155 bridge = "__bridge_transfer "; break;
156 case OBC_BridgeRetained:
157 bridge = "__bridge_retained "; break;
160 Transaction Trans(TA);
161 TA.clearDiagnostic(diag::err_arc_mismatched_cast,
162 diag::err_arc_cast_requires_bridge,
164 if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) {
165 TA.insertAfterToken(CCE->getLParenLoc(), bridge);
167 SourceLocation insertLoc = E->getSubExpr()->getLocStart();
168 llvm::SmallString<128> newCast;
171 newCast += E->getType().getAsString(Pass.Ctx.PrintingPolicy);
174 if (isa<ParenExpr>(E->getSubExpr())) {
175 TA.insert(insertLoc, newCast.str());
178 TA.insert(insertLoc, newCast.str());
179 TA.insertAfterToken(E->getLocEnd(), ")");
184 void transformObjCToNonObjCCast(CastExpr *E) {
185 if (isSelf(E->getSubExpr()))
186 return rewriteToBridgedCast(E, OBC_Bridge);
189 bool isSelf(Expr *E) {
190 E = E->IgnoreParenLValueCasts();
191 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
192 if (DRE->getDecl()->getIdentifier() == SelfII)
198 } // end anonymous namespace
200 void trans::rewriteUnbridgedCasts(MigrationPass &pass) {
201 UnbridgedCastRewriter trans(pass);
202 trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());