xref: /aosp_15_r20/external/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===--- TransUnbridgedCasts.cpp - Transformations to ARC mode ------------===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // rewriteUnbridgedCasts:
11*67e74705SXin Li //
12*67e74705SXin Li // A cast of non-objc pointer to an objc one is checked. If the non-objc pointer
13*67e74705SXin Li // is from a file-level variable, __bridge cast is used to convert it.
14*67e74705SXin Li // For the result of a function call that we know is +1/+0,
15*67e74705SXin Li // __bridge/CFBridgingRelease is used.
16*67e74705SXin Li //
17*67e74705SXin Li //  NSString *str = (NSString *)kUTTypePlainText;
18*67e74705SXin Li //  str = b ? kUTTypeRTF : kUTTypePlainText;
19*67e74705SXin Li //  NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault,
20*67e74705SXin Li //                                                         _uuid);
21*67e74705SXin Li // ---->
22*67e74705SXin Li //  NSString *str = (__bridge NSString *)kUTTypePlainText;
23*67e74705SXin Li //  str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
24*67e74705SXin Li // NSString *_uuidString = (NSString *)
25*67e74705SXin Li //            CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid));
26*67e74705SXin Li //
27*67e74705SXin Li // For a C pointer to ObjC, for casting 'self', __bridge is used.
28*67e74705SXin Li //
29*67e74705SXin Li //  CFStringRef str = (CFStringRef)self;
30*67e74705SXin Li // ---->
31*67e74705SXin Li //  CFStringRef str = (__bridge CFStringRef)self;
32*67e74705SXin Li //
33*67e74705SXin Li // Uses of Block_copy/Block_release macros are rewritten:
34*67e74705SXin Li //
35*67e74705SXin Li //  c = Block_copy(b);
36*67e74705SXin Li //  Block_release(c);
37*67e74705SXin Li // ---->
38*67e74705SXin Li //  c = [b copy];
39*67e74705SXin Li //  <removed>
40*67e74705SXin Li //
41*67e74705SXin Li //===----------------------------------------------------------------------===//
42*67e74705SXin Li 
43*67e74705SXin Li #include "Transforms.h"
44*67e74705SXin Li #include "Internals.h"
45*67e74705SXin Li #include "clang/AST/ASTContext.h"
46*67e74705SXin Li #include "clang/AST/Attr.h"
47*67e74705SXin Li #include "clang/AST/ParentMap.h"
48*67e74705SXin Li #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
49*67e74705SXin Li #include "clang/Basic/SourceManager.h"
50*67e74705SXin Li #include "clang/Lex/Lexer.h"
51*67e74705SXin Li #include "clang/Sema/SemaDiagnostic.h"
52*67e74705SXin Li #include "llvm/ADT/SmallString.h"
53*67e74705SXin Li 
54*67e74705SXin Li using namespace clang;
55*67e74705SXin Li using namespace arcmt;
56*67e74705SXin Li using namespace trans;
57*67e74705SXin Li 
58*67e74705SXin Li namespace {
59*67e74705SXin Li 
60*67e74705SXin Li class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
61*67e74705SXin Li   MigrationPass &Pass;
62*67e74705SXin Li   IdentifierInfo *SelfII;
63*67e74705SXin Li   std::unique_ptr<ParentMap> StmtMap;
64*67e74705SXin Li   Decl *ParentD;
65*67e74705SXin Li   Stmt *Body;
66*67e74705SXin Li   mutable std::unique_ptr<ExprSet> Removables;
67*67e74705SXin Li 
68*67e74705SXin Li public:
UnbridgedCastRewriter(MigrationPass & pass)69*67e74705SXin Li   UnbridgedCastRewriter(MigrationPass &pass)
70*67e74705SXin Li     : Pass(pass), ParentD(nullptr), Body(nullptr) {
71*67e74705SXin Li     SelfII = &Pass.Ctx.Idents.get("self");
72*67e74705SXin Li   }
73*67e74705SXin Li 
transformBody(Stmt * body,Decl * ParentD)74*67e74705SXin Li   void transformBody(Stmt *body, Decl *ParentD) {
75*67e74705SXin Li     this->ParentD = ParentD;
76*67e74705SXin Li     Body = body;
77*67e74705SXin Li     StmtMap.reset(new ParentMap(body));
78*67e74705SXin Li     TraverseStmt(body);
79*67e74705SXin Li   }
80*67e74705SXin Li 
TraverseBlockDecl(BlockDecl * D)81*67e74705SXin Li   bool TraverseBlockDecl(BlockDecl *D) {
82*67e74705SXin Li     // ParentMap does not enter into a BlockDecl to record its stmts, so use a
83*67e74705SXin Li     // new UnbridgedCastRewriter to handle the block.
84*67e74705SXin Li     UnbridgedCastRewriter(Pass).transformBody(D->getBody(), D);
85*67e74705SXin Li     return true;
86*67e74705SXin Li   }
87*67e74705SXin Li 
VisitCastExpr(CastExpr * E)88*67e74705SXin Li   bool VisitCastExpr(CastExpr *E) {
89*67e74705SXin Li     if (E->getCastKind() != CK_CPointerToObjCPointerCast &&
90*67e74705SXin Li         E->getCastKind() != CK_BitCast &&
91*67e74705SXin Li         E->getCastKind() != CK_AnyPointerToBlockPointerCast)
92*67e74705SXin Li       return true;
93*67e74705SXin Li 
94*67e74705SXin Li     QualType castType = E->getType();
95*67e74705SXin Li     Expr *castExpr = E->getSubExpr();
96*67e74705SXin Li     QualType castExprType = castExpr->getType();
97*67e74705SXin Li 
98*67e74705SXin Li     if (castType->isObjCRetainableType() == castExprType->isObjCRetainableType())
99*67e74705SXin Li       return true;
100*67e74705SXin Li 
101*67e74705SXin Li     bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
102*67e74705SXin Li     bool castRetainable = castType->isObjCIndirectLifetimeType();
103*67e74705SXin Li     if (exprRetainable == castRetainable) return true;
104*67e74705SXin Li 
105*67e74705SXin Li     if (castExpr->isNullPointerConstant(Pass.Ctx,
106*67e74705SXin Li                                         Expr::NPC_ValueDependentIsNull))
107*67e74705SXin Li       return true;
108*67e74705SXin Li 
109*67e74705SXin Li     SourceLocation loc = castExpr->getExprLoc();
110*67e74705SXin Li     if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc))
111*67e74705SXin Li       return true;
112*67e74705SXin Li 
113*67e74705SXin Li     if (castType->isObjCRetainableType())
114*67e74705SXin Li       transformNonObjCToObjCCast(E);
115*67e74705SXin Li     else
116*67e74705SXin Li       transformObjCToNonObjCCast(E);
117*67e74705SXin Li 
118*67e74705SXin Li     return true;
119*67e74705SXin Li   }
120*67e74705SXin Li 
121*67e74705SXin Li private:
transformNonObjCToObjCCast(CastExpr * E)122*67e74705SXin Li   void transformNonObjCToObjCCast(CastExpr *E) {
123*67e74705SXin Li     if (!E) return;
124*67e74705SXin Li 
125*67e74705SXin Li     // Global vars are assumed that are cast as unretained.
126*67e74705SXin Li     if (isGlobalVar(E))
127*67e74705SXin Li       if (E->getSubExpr()->getType()->isPointerType()) {
128*67e74705SXin Li         castToObjCObject(E, /*retained=*/false);
129*67e74705SXin Li         return;
130*67e74705SXin Li       }
131*67e74705SXin Li 
132*67e74705SXin Li     // If the cast is directly over the result of a Core Foundation function
133*67e74705SXin Li     // try to figure out whether it should be cast as retained or unretained.
134*67e74705SXin Li     Expr *inner = E->IgnoreParenCasts();
135*67e74705SXin Li     if (CallExpr *callE = dyn_cast<CallExpr>(inner)) {
136*67e74705SXin Li       if (FunctionDecl *FD = callE->getDirectCallee()) {
137*67e74705SXin Li         if (FD->hasAttr<CFReturnsRetainedAttr>()) {
138*67e74705SXin Li           castToObjCObject(E, /*retained=*/true);
139*67e74705SXin Li           return;
140*67e74705SXin Li         }
141*67e74705SXin Li         if (FD->hasAttr<CFReturnsNotRetainedAttr>()) {
142*67e74705SXin Li           castToObjCObject(E, /*retained=*/false);
143*67e74705SXin Li           return;
144*67e74705SXin Li         }
145*67e74705SXin Li         if (FD->isGlobal() &&
146*67e74705SXin Li             FD->getIdentifier() &&
147*67e74705SXin Li             ento::cocoa::isRefType(E->getSubExpr()->getType(), "CF",
148*67e74705SXin Li                                    FD->getIdentifier()->getName())) {
149*67e74705SXin Li           StringRef fname = FD->getIdentifier()->getName();
150*67e74705SXin Li           if (fname.endswith("Retain") ||
151*67e74705SXin Li               fname.find("Create") != StringRef::npos ||
152*67e74705SXin Li               fname.find("Copy") != StringRef::npos) {
153*67e74705SXin Li             // Do not migrate to couple of bridge transfer casts which
154*67e74705SXin Li             // cancel each other out. Leave it unchanged so error gets user
155*67e74705SXin Li             // attention instead.
156*67e74705SXin Li             if (FD->getName() == "CFRetain" &&
157*67e74705SXin Li                 FD->getNumParams() == 1 &&
158*67e74705SXin Li                 FD->getParent()->isTranslationUnit() &&
159*67e74705SXin Li                 FD->isExternallyVisible()) {
160*67e74705SXin Li               Expr *Arg = callE->getArg(0);
161*67e74705SXin Li               if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
162*67e74705SXin Li                 const Expr *sub = ICE->getSubExpr();
163*67e74705SXin Li                 QualType T = sub->getType();
164*67e74705SXin Li                 if (T->isObjCObjectPointerType())
165*67e74705SXin Li                   return;
166*67e74705SXin Li               }
167*67e74705SXin Li             }
168*67e74705SXin Li             castToObjCObject(E, /*retained=*/true);
169*67e74705SXin Li             return;
170*67e74705SXin Li           }
171*67e74705SXin Li 
172*67e74705SXin Li           if (fname.find("Get") != StringRef::npos) {
173*67e74705SXin Li             castToObjCObject(E, /*retained=*/false);
174*67e74705SXin Li             return;
175*67e74705SXin Li           }
176*67e74705SXin Li         }
177*67e74705SXin Li       }
178*67e74705SXin Li     }
179*67e74705SXin Li 
180*67e74705SXin Li     // If returning an ivar or a member of an ivar from a +0 method, use
181*67e74705SXin Li     // a __bridge cast.
182*67e74705SXin Li     Expr *base = inner->IgnoreParenImpCasts();
183*67e74705SXin Li     while (isa<MemberExpr>(base))
184*67e74705SXin Li       base = cast<MemberExpr>(base)->getBase()->IgnoreParenImpCasts();
185*67e74705SXin Li     if (isa<ObjCIvarRefExpr>(base) &&
186*67e74705SXin Li         isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(E))) {
187*67e74705SXin Li       if (ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) {
188*67e74705SXin Li         if (!method->hasAttr<NSReturnsRetainedAttr>()) {
189*67e74705SXin Li           castToObjCObject(E, /*retained=*/false);
190*67e74705SXin Li           return;
191*67e74705SXin Li         }
192*67e74705SXin Li       }
193*67e74705SXin Li     }
194*67e74705SXin Li   }
195*67e74705SXin Li 
castToObjCObject(CastExpr * E,bool retained)196*67e74705SXin Li   void castToObjCObject(CastExpr *E, bool retained) {
197*67e74705SXin Li     rewriteToBridgedCast(E, retained ? OBC_BridgeTransfer : OBC_Bridge);
198*67e74705SXin Li   }
199*67e74705SXin Li 
rewriteToBridgedCast(CastExpr * E,ObjCBridgeCastKind Kind)200*67e74705SXin Li   void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) {
201*67e74705SXin Li     Transaction Trans(Pass.TA);
202*67e74705SXin Li     rewriteToBridgedCast(E, Kind, Trans);
203*67e74705SXin Li   }
204*67e74705SXin Li 
rewriteToBridgedCast(CastExpr * E,ObjCBridgeCastKind Kind,Transaction & Trans)205*67e74705SXin Li   void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind,
206*67e74705SXin Li                             Transaction &Trans) {
207*67e74705SXin Li     TransformActions &TA = Pass.TA;
208*67e74705SXin Li 
209*67e74705SXin Li     // We will remove the compiler diagnostic.
210*67e74705SXin Li     if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast,
211*67e74705SXin Li                           diag::err_arc_cast_requires_bridge,
212*67e74705SXin Li                           E->getLocStart())) {
213*67e74705SXin Li       Trans.abort();
214*67e74705SXin Li       return;
215*67e74705SXin Li     }
216*67e74705SXin Li 
217*67e74705SXin Li     StringRef bridge;
218*67e74705SXin Li     switch(Kind) {
219*67e74705SXin Li     case OBC_Bridge:
220*67e74705SXin Li       bridge = "__bridge "; break;
221*67e74705SXin Li     case OBC_BridgeTransfer:
222*67e74705SXin Li       bridge = "__bridge_transfer "; break;
223*67e74705SXin Li     case OBC_BridgeRetained:
224*67e74705SXin Li       bridge = "__bridge_retained "; break;
225*67e74705SXin Li     }
226*67e74705SXin Li 
227*67e74705SXin Li     TA.clearDiagnostic(diag::err_arc_mismatched_cast,
228*67e74705SXin Li                        diag::err_arc_cast_requires_bridge,
229*67e74705SXin Li                        E->getLocStart());
230*67e74705SXin Li     if (Kind == OBC_Bridge || !Pass.CFBridgingFunctionsDefined()) {
231*67e74705SXin Li       if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) {
232*67e74705SXin Li         TA.insertAfterToken(CCE->getLParenLoc(), bridge);
233*67e74705SXin Li       } else {
234*67e74705SXin Li         SourceLocation insertLoc = E->getSubExpr()->getLocStart();
235*67e74705SXin Li         SmallString<128> newCast;
236*67e74705SXin Li         newCast += '(';
237*67e74705SXin Li         newCast += bridge;
238*67e74705SXin Li         newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
239*67e74705SXin Li         newCast += ')';
240*67e74705SXin Li 
241*67e74705SXin Li         if (isa<ParenExpr>(E->getSubExpr())) {
242*67e74705SXin Li           TA.insert(insertLoc, newCast.str());
243*67e74705SXin Li         } else {
244*67e74705SXin Li           newCast += '(';
245*67e74705SXin Li           TA.insert(insertLoc, newCast.str());
246*67e74705SXin Li           TA.insertAfterToken(E->getLocEnd(), ")");
247*67e74705SXin Li         }
248*67e74705SXin Li       }
249*67e74705SXin Li     } else {
250*67e74705SXin Li       assert(Kind == OBC_BridgeTransfer || Kind == OBC_BridgeRetained);
251*67e74705SXin Li       SmallString<32> BridgeCall;
252*67e74705SXin Li 
253*67e74705SXin Li       Expr *WrapE = E->getSubExpr();
254*67e74705SXin Li       SourceLocation InsertLoc = WrapE->getLocStart();
255*67e74705SXin Li 
256*67e74705SXin Li       SourceManager &SM = Pass.Ctx.getSourceManager();
257*67e74705SXin Li       char PrevChar = *SM.getCharacterData(InsertLoc.getLocWithOffset(-1));
258*67e74705SXin Li       if (Lexer::isIdentifierBodyChar(PrevChar, Pass.Ctx.getLangOpts()))
259*67e74705SXin Li         BridgeCall += ' ';
260*67e74705SXin Li 
261*67e74705SXin Li       if (Kind == OBC_BridgeTransfer)
262*67e74705SXin Li         BridgeCall += "CFBridgingRelease";
263*67e74705SXin Li       else
264*67e74705SXin Li         BridgeCall += "CFBridgingRetain";
265*67e74705SXin Li 
266*67e74705SXin Li       if (isa<ParenExpr>(WrapE)) {
267*67e74705SXin Li         TA.insert(InsertLoc, BridgeCall);
268*67e74705SXin Li       } else {
269*67e74705SXin Li         BridgeCall += '(';
270*67e74705SXin Li         TA.insert(InsertLoc, BridgeCall);
271*67e74705SXin Li         TA.insertAfterToken(WrapE->getLocEnd(), ")");
272*67e74705SXin Li       }
273*67e74705SXin Li     }
274*67e74705SXin Li   }
275*67e74705SXin Li 
rewriteCastForCFRetain(CastExpr * castE,CallExpr * callE)276*67e74705SXin Li   void rewriteCastForCFRetain(CastExpr *castE, CallExpr *callE) {
277*67e74705SXin Li     Transaction Trans(Pass.TA);
278*67e74705SXin Li     Pass.TA.replace(callE->getSourceRange(), callE->getArg(0)->getSourceRange());
279*67e74705SXin Li     rewriteToBridgedCast(castE, OBC_BridgeRetained, Trans);
280*67e74705SXin Li   }
281*67e74705SXin Li 
getBlockMacroRanges(CastExpr * E,SourceRange & Outer,SourceRange & Inner)282*67e74705SXin Li   void getBlockMacroRanges(CastExpr *E, SourceRange &Outer, SourceRange &Inner) {
283*67e74705SXin Li     SourceManager &SM = Pass.Ctx.getSourceManager();
284*67e74705SXin Li     SourceLocation Loc = E->getExprLoc();
285*67e74705SXin Li     assert(Loc.isMacroID());
286*67e74705SXin Li     SourceLocation MacroBegin, MacroEnd;
287*67e74705SXin Li     std::tie(MacroBegin, MacroEnd) = SM.getImmediateExpansionRange(Loc);
288*67e74705SXin Li     SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange();
289*67e74705SXin Li     SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin());
290*67e74705SXin Li     SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd());
291*67e74705SXin Li 
292*67e74705SXin Li     Outer = SourceRange(MacroBegin, MacroEnd);
293*67e74705SXin Li     Inner = SourceRange(InnerBegin, InnerEnd);
294*67e74705SXin Li   }
295*67e74705SXin Li 
rewriteBlockCopyMacro(CastExpr * E)296*67e74705SXin Li   void rewriteBlockCopyMacro(CastExpr *E) {
297*67e74705SXin Li     SourceRange OuterRange, InnerRange;
298*67e74705SXin Li     getBlockMacroRanges(E, OuterRange, InnerRange);
299*67e74705SXin Li 
300*67e74705SXin Li     Transaction Trans(Pass.TA);
301*67e74705SXin Li     Pass.TA.replace(OuterRange, InnerRange);
302*67e74705SXin Li     Pass.TA.insert(InnerRange.getBegin(), "[");
303*67e74705SXin Li     Pass.TA.insertAfterToken(InnerRange.getEnd(), " copy]");
304*67e74705SXin Li     Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
305*67e74705SXin Li                             diag::err_arc_cast_requires_bridge,
306*67e74705SXin Li                             OuterRange);
307*67e74705SXin Li   }
308*67e74705SXin Li 
removeBlockReleaseMacro(CastExpr * E)309*67e74705SXin Li   void removeBlockReleaseMacro(CastExpr *E) {
310*67e74705SXin Li     SourceRange OuterRange, InnerRange;
311*67e74705SXin Li     getBlockMacroRanges(E, OuterRange, InnerRange);
312*67e74705SXin Li 
313*67e74705SXin Li     Transaction Trans(Pass.TA);
314*67e74705SXin Li     Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
315*67e74705SXin Li                             diag::err_arc_cast_requires_bridge,
316*67e74705SXin Li                             OuterRange);
317*67e74705SXin Li     if (!hasSideEffects(E, Pass.Ctx)) {
318*67e74705SXin Li       if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E))))
319*67e74705SXin Li         return;
320*67e74705SXin Li     }
321*67e74705SXin Li     Pass.TA.replace(OuterRange, InnerRange);
322*67e74705SXin Li   }
323*67e74705SXin Li 
tryRemoving(Expr * E) const324*67e74705SXin Li   bool tryRemoving(Expr *E) const {
325*67e74705SXin Li     if (!Removables) {
326*67e74705SXin Li       Removables.reset(new ExprSet);
327*67e74705SXin Li       collectRemovables(Body, *Removables);
328*67e74705SXin Li     }
329*67e74705SXin Li 
330*67e74705SXin Li     if (Removables->count(E)) {
331*67e74705SXin Li       Pass.TA.removeStmt(E);
332*67e74705SXin Li       return true;
333*67e74705SXin Li     }
334*67e74705SXin Li 
335*67e74705SXin Li     return false;
336*67e74705SXin Li   }
337*67e74705SXin Li 
transformObjCToNonObjCCast(CastExpr * E)338*67e74705SXin Li   void transformObjCToNonObjCCast(CastExpr *E) {
339*67e74705SXin Li     SourceLocation CastLoc = E->getExprLoc();
340*67e74705SXin Li     if (CastLoc.isMacroID()) {
341*67e74705SXin Li       StringRef MacroName = Lexer::getImmediateMacroName(CastLoc,
342*67e74705SXin Li                                                     Pass.Ctx.getSourceManager(),
343*67e74705SXin Li                                                     Pass.Ctx.getLangOpts());
344*67e74705SXin Li       if (MacroName == "Block_copy") {
345*67e74705SXin Li         rewriteBlockCopyMacro(E);
346*67e74705SXin Li         return;
347*67e74705SXin Li       }
348*67e74705SXin Li       if (MacroName == "Block_release") {
349*67e74705SXin Li         removeBlockReleaseMacro(E);
350*67e74705SXin Li         return;
351*67e74705SXin Li       }
352*67e74705SXin Li     }
353*67e74705SXin Li 
354*67e74705SXin Li     if (isSelf(E->getSubExpr()))
355*67e74705SXin Li       return rewriteToBridgedCast(E, OBC_Bridge);
356*67e74705SXin Li 
357*67e74705SXin Li     CallExpr *callE;
358*67e74705SXin Li     if (isPassedToCFRetain(E, callE))
359*67e74705SXin Li       return rewriteCastForCFRetain(E, callE);
360*67e74705SXin Li 
361*67e74705SXin Li     ObjCMethodFamily family = getFamilyOfMessage(E->getSubExpr());
362*67e74705SXin Li     if (family == OMF_retain)
363*67e74705SXin Li       return rewriteToBridgedCast(E, OBC_BridgeRetained);
364*67e74705SXin Li 
365*67e74705SXin Li     if (family == OMF_autorelease || family == OMF_release) {
366*67e74705SXin Li       std::string err = "it is not safe to cast to '";
367*67e74705SXin Li       err += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
368*67e74705SXin Li       err += "' the result of '";
369*67e74705SXin Li       err += family == OMF_autorelease ? "autorelease" : "release";
370*67e74705SXin Li       err += "' message; a __bridge cast may result in a pointer to a "
371*67e74705SXin Li           "destroyed object and a __bridge_retained may leak the object";
372*67e74705SXin Li       Pass.TA.reportError(err, E->getLocStart(),
373*67e74705SXin Li                           E->getSubExpr()->getSourceRange());
374*67e74705SXin Li       Stmt *parent = E;
375*67e74705SXin Li       do {
376*67e74705SXin Li         parent = StmtMap->getParentIgnoreParenImpCasts(parent);
377*67e74705SXin Li       } while (parent && isa<ExprWithCleanups>(parent));
378*67e74705SXin Li 
379*67e74705SXin Li       if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
380*67e74705SXin Li         std::string note = "remove the cast and change return type of function "
381*67e74705SXin Li             "to '";
382*67e74705SXin Li         note += E->getSubExpr()->getType().getAsString(Pass.Ctx.getPrintingPolicy());
383*67e74705SXin Li         note += "' to have the object automatically autoreleased";
384*67e74705SXin Li         Pass.TA.reportNote(note, retS->getLocStart());
385*67e74705SXin Li       }
386*67e74705SXin Li     }
387*67e74705SXin Li 
388*67e74705SXin Li     Expr *subExpr = E->getSubExpr();
389*67e74705SXin Li 
390*67e74705SXin Li     // Look through pseudo-object expressions.
391*67e74705SXin Li     if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) {
392*67e74705SXin Li       subExpr = pseudo->getResultExpr();
393*67e74705SXin Li       assert(subExpr && "no result for pseudo-object of non-void type?");
394*67e74705SXin Li     }
395*67e74705SXin Li 
396*67e74705SXin Li     if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) {
397*67e74705SXin Li       if (implCE->getCastKind() == CK_ARCConsumeObject)
398*67e74705SXin Li         return rewriteToBridgedCast(E, OBC_BridgeRetained);
399*67e74705SXin Li       if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
400*67e74705SXin Li         return rewriteToBridgedCast(E, OBC_Bridge);
401*67e74705SXin Li     }
402*67e74705SXin Li 
403*67e74705SXin Li     bool isConsumed = false;
404*67e74705SXin Li     if (isPassedToCParamWithKnownOwnership(E, isConsumed))
405*67e74705SXin Li       return rewriteToBridgedCast(E, isConsumed ? OBC_BridgeRetained
406*67e74705SXin Li                                                 : OBC_Bridge);
407*67e74705SXin Li   }
408*67e74705SXin Li 
getFamilyOfMessage(Expr * E)409*67e74705SXin Li   static ObjCMethodFamily getFamilyOfMessage(Expr *E) {
410*67e74705SXin Li     E = E->IgnoreParenCasts();
411*67e74705SXin Li     if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))
412*67e74705SXin Li       return ME->getMethodFamily();
413*67e74705SXin Li 
414*67e74705SXin Li     return OMF_None;
415*67e74705SXin Li   }
416*67e74705SXin Li 
isPassedToCFRetain(Expr * E,CallExpr * & callE) const417*67e74705SXin Li   bool isPassedToCFRetain(Expr *E, CallExpr *&callE) const {
418*67e74705SXin Li     if ((callE = dyn_cast_or_null<CallExpr>(
419*67e74705SXin Li                                      StmtMap->getParentIgnoreParenImpCasts(E))))
420*67e74705SXin Li       if (FunctionDecl *
421*67e74705SXin Li             FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl()))
422*67e74705SXin Li         if (FD->getName() == "CFRetain" && FD->getNumParams() == 1 &&
423*67e74705SXin Li             FD->getParent()->isTranslationUnit() &&
424*67e74705SXin Li             FD->isExternallyVisible())
425*67e74705SXin Li           return true;
426*67e74705SXin Li 
427*67e74705SXin Li     return false;
428*67e74705SXin Li   }
429*67e74705SXin Li 
isPassedToCParamWithKnownOwnership(Expr * E,bool & isConsumed) const430*67e74705SXin Li   bool isPassedToCParamWithKnownOwnership(Expr *E, bool &isConsumed) const {
431*67e74705SXin Li     if (CallExpr *callE = dyn_cast_or_null<CallExpr>(
432*67e74705SXin Li                                      StmtMap->getParentIgnoreParenImpCasts(E)))
433*67e74705SXin Li       if (FunctionDecl *
434*67e74705SXin Li             FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) {
435*67e74705SXin Li         unsigned i = 0;
436*67e74705SXin Li         for (unsigned e = callE->getNumArgs(); i != e; ++i) {
437*67e74705SXin Li           Expr *arg = callE->getArg(i);
438*67e74705SXin Li           if (arg == E || arg->IgnoreParenImpCasts() == E)
439*67e74705SXin Li             break;
440*67e74705SXin Li         }
441*67e74705SXin Li         if (i < callE->getNumArgs() && i < FD->getNumParams()) {
442*67e74705SXin Li           ParmVarDecl *PD = FD->getParamDecl(i);
443*67e74705SXin Li           if (PD->hasAttr<CFConsumedAttr>()) {
444*67e74705SXin Li             isConsumed = true;
445*67e74705SXin Li             return true;
446*67e74705SXin Li           }
447*67e74705SXin Li         }
448*67e74705SXin Li       }
449*67e74705SXin Li 
450*67e74705SXin Li     return false;
451*67e74705SXin Li   }
452*67e74705SXin Li 
isSelf(Expr * E) const453*67e74705SXin Li   bool isSelf(Expr *E) const {
454*67e74705SXin Li     E = E->IgnoreParenLValueCasts();
455*67e74705SXin Li     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
456*67e74705SXin Li       if (ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
457*67e74705SXin Li         if (IPD->getIdentifier() == SelfII)
458*67e74705SXin Li           return true;
459*67e74705SXin Li 
460*67e74705SXin Li     return false;
461*67e74705SXin Li   }
462*67e74705SXin Li };
463*67e74705SXin Li 
464*67e74705SXin Li } // end anonymous namespace
465*67e74705SXin Li 
rewriteUnbridgedCasts(MigrationPass & pass)466*67e74705SXin Li void trans::rewriteUnbridgedCasts(MigrationPass &pass) {
467*67e74705SXin Li   BodyTransform<UnbridgedCastRewriter> trans(pass);
468*67e74705SXin Li   trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
469*67e74705SXin Li }
470