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