TransUnbridgedCasts.cpp revision 341825
1249423Sdim//===--- TransUnbridgedCasts.cpp - Transformations to ARC mode ------------===//
2224135Sdim//
3224135Sdim//                     The LLVM Compiler Infrastructure
4224135Sdim//
5224135Sdim// This file is distributed under the University of Illinois Open Source
6224135Sdim// License. See LICENSE.TXT for details.
7224135Sdim//
8224135Sdim//===----------------------------------------------------------------------===//
9224135Sdim//
10224135Sdim// rewriteUnbridgedCasts:
11224135Sdim//
12224135Sdim// A cast of non-objc pointer to an objc one is checked. If the non-objc pointer
13224135Sdim// is from a file-level variable, __bridge cast is used to convert it.
14224135Sdim// For the result of a function call that we know is +1/+0,
15239462Sdim// __bridge/CFBridgingRelease is used.
16224135Sdim//
17224135Sdim//  NSString *str = (NSString *)kUTTypePlainText;
18224135Sdim//  str = b ? kUTTypeRTF : kUTTypePlainText;
19224135Sdim//  NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault,
20224135Sdim//                                                         _uuid);
21224135Sdim// ---->
22224135Sdim//  NSString *str = (__bridge NSString *)kUTTypePlainText;
23224135Sdim//  str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
24239462Sdim// NSString *_uuidString = (NSString *)
25239462Sdim//            CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid));
26224135Sdim//
27224135Sdim// For a C pointer to ObjC, for casting 'self', __bridge is used.
28224135Sdim//
29224135Sdim//  CFStringRef str = (CFStringRef)self;
30224135Sdim// ---->
31224135Sdim//  CFStringRef str = (__bridge CFStringRef)self;
32224135Sdim//
33249423Sdim// Uses of Block_copy/Block_release macros are rewritten:
34249423Sdim//
35249423Sdim//  c = Block_copy(b);
36249423Sdim//  Block_release(c);
37249423Sdim// ---->
38249423Sdim//  c = [b copy];
39249423Sdim//  <removed>
40249423Sdim//
41224135Sdim//===----------------------------------------------------------------------===//
42224135Sdim
43224135Sdim#include "Transforms.h"
44224135Sdim#include "Internals.h"
45239462Sdim#include "clang/AST/ASTContext.h"
46249423Sdim#include "clang/AST/Attr.h"
47226633Sdim#include "clang/AST/ParentMap.h"
48249423Sdim#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
49224135Sdim#include "clang/Basic/SourceManager.h"
50239462Sdim#include "clang/Lex/Lexer.h"
51239462Sdim#include "clang/Sema/SemaDiagnostic.h"
52234353Sdim#include "llvm/ADT/SmallString.h"
53224135Sdim
54224135Sdimusing namespace clang;
55224135Sdimusing namespace arcmt;
56224135Sdimusing namespace trans;
57224135Sdim
58224135Sdimnamespace {
59224135Sdim
60224135Sdimclass UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
61224135Sdim  MigrationPass &Pass;
62224135Sdim  IdentifierInfo *SelfII;
63276479Sdim  std::unique_ptr<ParentMap> StmtMap;
64239462Sdim  Decl *ParentD;
65249423Sdim  Stmt *Body;
66276479Sdim  mutable std::unique_ptr<ExprSet> Removables;
67226633Sdim
68224135Sdimpublic:
69276479Sdim  UnbridgedCastRewriter(MigrationPass &pass)
70276479Sdim    : Pass(pass), ParentD(nullptr), Body(nullptr) {
71224135Sdim    SelfII = &Pass.Ctx.Idents.get("self");
72224135Sdim  }
73224135Sdim
74239462Sdim  void transformBody(Stmt *body, Decl *ParentD) {
75239462Sdim    this->ParentD = ParentD;
76249423Sdim    Body = body;
77226633Sdim    StmtMap.reset(new ParentMap(body));
78226633Sdim    TraverseStmt(body);
79226633Sdim  }
80226633Sdim
81261991Sdim  bool TraverseBlockDecl(BlockDecl *D) {
82261991Sdim    // ParentMap does not enter into a BlockDecl to record its stmts, so use a
83261991Sdim    // new UnbridgedCastRewriter to handle the block.
84261991Sdim    UnbridgedCastRewriter(Pass).transformBody(D->getBody(), D);
85261991Sdim    return true;
86261991Sdim  }
87261991Sdim
88224135Sdim  bool VisitCastExpr(CastExpr *E) {
89249423Sdim    if (E->getCastKind() != CK_CPointerToObjCPointerCast &&
90249423Sdim        E->getCastKind() != CK_BitCast &&
91249423Sdim        E->getCastKind() != CK_AnyPointerToBlockPointerCast)
92224135Sdim      return true;
93224135Sdim
94224135Sdim    QualType castType = E->getType();
95224135Sdim    Expr *castExpr = E->getSubExpr();
96224135Sdim    QualType castExprType = castExpr->getType();
97224135Sdim
98249423Sdim    if (castType->isObjCRetainableType() == castExprType->isObjCRetainableType())
99224135Sdim      return true;
100341825Sdim
101224135Sdim    bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
102224135Sdim    bool castRetainable = castType->isObjCIndirectLifetimeType();
103224135Sdim    if (exprRetainable == castRetainable) return true;
104224135Sdim
105224135Sdim    if (castExpr->isNullPointerConstant(Pass.Ctx,
106224135Sdim                                        Expr::NPC_ValueDependentIsNull))
107224135Sdim      return true;
108224135Sdim
109224135Sdim    SourceLocation loc = castExpr->getExprLoc();
110224135Sdim    if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc))
111224135Sdim      return true;
112224135Sdim
113249423Sdim    if (castType->isObjCRetainableType())
114224135Sdim      transformNonObjCToObjCCast(E);
115224135Sdim    else
116224135Sdim      transformObjCToNonObjCCast(E);
117224135Sdim
118224135Sdim    return true;
119224135Sdim  }
120224135Sdim
121224135Sdimprivate:
122224135Sdim  void transformNonObjCToObjCCast(CastExpr *E) {
123224135Sdim    if (!E) return;
124224135Sdim
125224135Sdim    // Global vars are assumed that are cast as unretained.
126224135Sdim    if (isGlobalVar(E))
127224135Sdim      if (E->getSubExpr()->getType()->isPointerType()) {
128224135Sdim        castToObjCObject(E, /*retained=*/false);
129224135Sdim        return;
130224135Sdim      }
131224135Sdim
132224135Sdim    // If the cast is directly over the result of a Core Foundation function
133224135Sdim    // try to figure out whether it should be cast as retained or unretained.
134224135Sdim    Expr *inner = E->IgnoreParenCasts();
135224135Sdim    if (CallExpr *callE = dyn_cast<CallExpr>(inner)) {
136224135Sdim      if (FunctionDecl *FD = callE->getDirectCallee()) {
137276479Sdim        if (FD->hasAttr<CFReturnsRetainedAttr>()) {
138224135Sdim          castToObjCObject(E, /*retained=*/true);
139224135Sdim          return;
140224135Sdim        }
141276479Sdim        if (FD->hasAttr<CFReturnsNotRetainedAttr>()) {
142224135Sdim          castToObjCObject(E, /*retained=*/false);
143224135Sdim          return;
144224135Sdim        }
145224135Sdim        if (FD->isGlobal() &&
146224135Sdim            FD->getIdentifier() &&
147224135Sdim            ento::cocoa::isRefType(E->getSubExpr()->getType(), "CF",
148224135Sdim                                   FD->getIdentifier()->getName())) {
149224135Sdim          StringRef fname = FD->getIdentifier()->getName();
150224135Sdim          if (fname.endswith("Retain") ||
151224135Sdim              fname.find("Create") != StringRef::npos ||
152224135Sdim              fname.find("Copy") != StringRef::npos) {
153234353Sdim            // Do not migrate to couple of bridge transfer casts which
154234353Sdim            // cancel each other out. Leave it unchanged so error gets user
155234353Sdim            // attention instead.
156341825Sdim            if (FD->getName() == "CFRetain" &&
157234353Sdim                FD->getNumParams() == 1 &&
158234353Sdim                FD->getParent()->isTranslationUnit() &&
159261991Sdim                FD->isExternallyVisible()) {
160234353Sdim              Expr *Arg = callE->getArg(0);
161234353Sdim              if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
162234353Sdim                const Expr *sub = ICE->getSubExpr();
163234353Sdim                QualType T = sub->getType();
164234353Sdim                if (T->isObjCObjectPointerType())
165234353Sdim                  return;
166234353Sdim              }
167234353Sdim            }
168224135Sdim            castToObjCObject(E, /*retained=*/true);
169224135Sdim            return;
170224135Sdim          }
171224135Sdim
172224135Sdim          if (fname.find("Get") != StringRef::npos) {
173224135Sdim            castToObjCObject(E, /*retained=*/false);
174224135Sdim            return;
175224135Sdim          }
176224135Sdim        }
177224135Sdim      }
178224135Sdim    }
179239462Sdim
180239462Sdim    // If returning an ivar or a member of an ivar from a +0 method, use
181239462Sdim    // a __bridge cast.
182239462Sdim    Expr *base = inner->IgnoreParenImpCasts();
183239462Sdim    while (isa<MemberExpr>(base))
184239462Sdim      base = cast<MemberExpr>(base)->getBase()->IgnoreParenImpCasts();
185239462Sdim    if (isa<ObjCIvarRefExpr>(base) &&
186239462Sdim        isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(E))) {
187239462Sdim      if (ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) {
188239462Sdim        if (!method->hasAttr<NSReturnsRetainedAttr>()) {
189239462Sdim          castToObjCObject(E, /*retained=*/false);
190239462Sdim          return;
191239462Sdim        }
192239462Sdim      }
193239462Sdim    }
194224135Sdim  }
195224135Sdim
196224135Sdim  void castToObjCObject(CastExpr *E, bool retained) {
197224135Sdim    rewriteToBridgedCast(E, retained ? OBC_BridgeTransfer : OBC_Bridge);
198224135Sdim  }
199224135Sdim
200224135Sdim  void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) {
201226633Sdim    Transaction Trans(Pass.TA);
202226633Sdim    rewriteToBridgedCast(E, Kind, Trans);
203226633Sdim  }
204226633Sdim
205226633Sdim  void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind,
206226633Sdim                            Transaction &Trans) {
207224135Sdim    TransformActions &TA = Pass.TA;
208224135Sdim
209224135Sdim    // We will remove the compiler diagnostic.
210224135Sdim    if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast,
211224135Sdim                          diag::err_arc_cast_requires_bridge,
212226633Sdim                          E->getLocStart())) {
213226633Sdim      Trans.abort();
214224135Sdim      return;
215226633Sdim    }
216224135Sdim
217224135Sdim    StringRef bridge;
218224135Sdim    switch(Kind) {
219224135Sdim    case OBC_Bridge:
220224135Sdim      bridge = "__bridge "; break;
221224135Sdim    case OBC_BridgeTransfer:
222224135Sdim      bridge = "__bridge_transfer "; break;
223224135Sdim    case OBC_BridgeRetained:
224224135Sdim      bridge = "__bridge_retained "; break;
225224135Sdim    }
226224135Sdim
227224135Sdim    TA.clearDiagnostic(diag::err_arc_mismatched_cast,
228224135Sdim                       diag::err_arc_cast_requires_bridge,
229224135Sdim                       E->getLocStart());
230239462Sdim    if (Kind == OBC_Bridge || !Pass.CFBridgingFunctionsDefined()) {
231239462Sdim      if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) {
232239462Sdim        TA.insertAfterToken(CCE->getLParenLoc(), bridge);
233239462Sdim      } else {
234239462Sdim        SourceLocation insertLoc = E->getSubExpr()->getLocStart();
235239462Sdim        SmallString<128> newCast;
236239462Sdim        newCast += '(';
237239462Sdim        newCast += bridge;
238239462Sdim        newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
239239462Sdim        newCast += ')';
240239462Sdim
241239462Sdim        if (isa<ParenExpr>(E->getSubExpr())) {
242239462Sdim          TA.insert(insertLoc, newCast.str());
243239462Sdim        } else {
244239462Sdim          newCast += '(';
245239462Sdim          TA.insert(insertLoc, newCast.str());
246239462Sdim          TA.insertAfterToken(E->getLocEnd(), ")");
247239462Sdim        }
248239462Sdim      }
249224135Sdim    } else {
250239462Sdim      assert(Kind == OBC_BridgeTransfer || Kind == OBC_BridgeRetained);
251239462Sdim      SmallString<32> BridgeCall;
252224135Sdim
253239462Sdim      Expr *WrapE = E->getSubExpr();
254239462Sdim      SourceLocation InsertLoc = WrapE->getLocStart();
255239462Sdim
256239462Sdim      SourceManager &SM = Pass.Ctx.getSourceManager();
257239462Sdim      char PrevChar = *SM.getCharacterData(InsertLoc.getLocWithOffset(-1));
258239462Sdim      if (Lexer::isIdentifierBodyChar(PrevChar, Pass.Ctx.getLangOpts()))
259239462Sdim        BridgeCall += ' ';
260239462Sdim
261239462Sdim      if (Kind == OBC_BridgeTransfer)
262239462Sdim        BridgeCall += "CFBridgingRelease";
263239462Sdim      else
264239462Sdim        BridgeCall += "CFBridgingRetain";
265239462Sdim
266239462Sdim      if (isa<ParenExpr>(WrapE)) {
267239462Sdim        TA.insert(InsertLoc, BridgeCall);
268224135Sdim      } else {
269239462Sdim        BridgeCall += '(';
270239462Sdim        TA.insert(InsertLoc, BridgeCall);
271239462Sdim        TA.insertAfterToken(WrapE->getLocEnd(), ")");
272224135Sdim      }
273224135Sdim    }
274224135Sdim  }
275224135Sdim
276226633Sdim  void rewriteCastForCFRetain(CastExpr *castE, CallExpr *callE) {
277226633Sdim    Transaction Trans(Pass.TA);
278226633Sdim    Pass.TA.replace(callE->getSourceRange(), callE->getArg(0)->getSourceRange());
279226633Sdim    rewriteToBridgedCast(castE, OBC_BridgeRetained, Trans);
280226633Sdim  }
281226633Sdim
282249423Sdim  void getBlockMacroRanges(CastExpr *E, SourceRange &Outer, SourceRange &Inner) {
283249423Sdim    SourceManager &SM = Pass.Ctx.getSourceManager();
284249423Sdim    SourceLocation Loc = E->getExprLoc();
285249423Sdim    assert(Loc.isMacroID());
286341825Sdim    CharSourceRange MacroRange = SM.getImmediateExpansionRange(Loc);
287249423Sdim    SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange();
288249423Sdim    SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin());
289249423Sdim    SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd());
290249423Sdim
291341825Sdim    Outer = MacroRange.getAsRange();
292249423Sdim    Inner = SourceRange(InnerBegin, InnerEnd);
293249423Sdim  }
294249423Sdim
295249423Sdim  void rewriteBlockCopyMacro(CastExpr *E) {
296249423Sdim    SourceRange OuterRange, InnerRange;
297249423Sdim    getBlockMacroRanges(E, OuterRange, InnerRange);
298249423Sdim
299249423Sdim    Transaction Trans(Pass.TA);
300249423Sdim    Pass.TA.replace(OuterRange, InnerRange);
301249423Sdim    Pass.TA.insert(InnerRange.getBegin(), "[");
302249423Sdim    Pass.TA.insertAfterToken(InnerRange.getEnd(), " copy]");
303249423Sdim    Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
304249423Sdim                            diag::err_arc_cast_requires_bridge,
305249423Sdim                            OuterRange);
306249423Sdim  }
307249423Sdim
308249423Sdim  void removeBlockReleaseMacro(CastExpr *E) {
309249423Sdim    SourceRange OuterRange, InnerRange;
310249423Sdim    getBlockMacroRanges(E, OuterRange, InnerRange);
311249423Sdim
312249423Sdim    Transaction Trans(Pass.TA);
313249423Sdim    Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
314249423Sdim                            diag::err_arc_cast_requires_bridge,
315249423Sdim                            OuterRange);
316249423Sdim    if (!hasSideEffects(E, Pass.Ctx)) {
317249423Sdim      if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E))))
318249423Sdim        return;
319249423Sdim    }
320249423Sdim    Pass.TA.replace(OuterRange, InnerRange);
321249423Sdim  }
322249423Sdim
323249423Sdim  bool tryRemoving(Expr *E) const {
324249423Sdim    if (!Removables) {
325249423Sdim      Removables.reset(new ExprSet);
326249423Sdim      collectRemovables(Body, *Removables);
327249423Sdim    }
328249423Sdim
329249423Sdim    if (Removables->count(E)) {
330249423Sdim      Pass.TA.removeStmt(E);
331249423Sdim      return true;
332249423Sdim    }
333249423Sdim
334249423Sdim    return false;
335249423Sdim  }
336249423Sdim
337224135Sdim  void transformObjCToNonObjCCast(CastExpr *E) {
338249423Sdim    SourceLocation CastLoc = E->getExprLoc();
339249423Sdim    if (CastLoc.isMacroID()) {
340249423Sdim      StringRef MacroName = Lexer::getImmediateMacroName(CastLoc,
341249423Sdim                                                    Pass.Ctx.getSourceManager(),
342249423Sdim                                                    Pass.Ctx.getLangOpts());
343249423Sdim      if (MacroName == "Block_copy") {
344249423Sdim        rewriteBlockCopyMacro(E);
345249423Sdim        return;
346249423Sdim      }
347249423Sdim      if (MacroName == "Block_release") {
348249423Sdim        removeBlockReleaseMacro(E);
349249423Sdim        return;
350249423Sdim      }
351249423Sdim    }
352249423Sdim
353224135Sdim    if (isSelf(E->getSubExpr()))
354224135Sdim      return rewriteToBridgedCast(E, OBC_Bridge);
355226633Sdim
356226633Sdim    CallExpr *callE;
357226633Sdim    if (isPassedToCFRetain(E, callE))
358226633Sdim      return rewriteCastForCFRetain(E, callE);
359226633Sdim
360226633Sdim    ObjCMethodFamily family = getFamilyOfMessage(E->getSubExpr());
361226633Sdim    if (family == OMF_retain)
362226633Sdim      return rewriteToBridgedCast(E, OBC_BridgeRetained);
363226633Sdim
364226633Sdim    if (family == OMF_autorelease || family == OMF_release) {
365226633Sdim      std::string err = "it is not safe to cast to '";
366226633Sdim      err += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
367226633Sdim      err += "' the result of '";
368226633Sdim      err += family == OMF_autorelease ? "autorelease" : "release";
369226633Sdim      err += "' message; a __bridge cast may result in a pointer to a "
370226633Sdim          "destroyed object and a __bridge_retained may leak the object";
371226633Sdim      Pass.TA.reportError(err, E->getLocStart(),
372226633Sdim                          E->getSubExpr()->getSourceRange());
373226633Sdim      Stmt *parent = E;
374226633Sdim      do {
375226633Sdim        parent = StmtMap->getParentIgnoreParenImpCasts(parent);
376226633Sdim      } while (parent && isa<ExprWithCleanups>(parent));
377226633Sdim
378226633Sdim      if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
379226633Sdim        std::string note = "remove the cast and change return type of function "
380226633Sdim            "to '";
381226633Sdim        note += E->getSubExpr()->getType().getAsString(Pass.Ctx.getPrintingPolicy());
382226633Sdim        note += "' to have the object automatically autoreleased";
383226633Sdim        Pass.TA.reportNote(note, retS->getLocStart());
384226633Sdim      }
385226633Sdim    }
386226633Sdim
387234353Sdim    Expr *subExpr = E->getSubExpr();
388234353Sdim
389234353Sdim    // Look through pseudo-object expressions.
390234353Sdim    if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) {
391234353Sdim      subExpr = pseudo->getResultExpr();
392234353Sdim      assert(subExpr && "no result for pseudo-object of non-void type?");
393234353Sdim    }
394234353Sdim
395234353Sdim    if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) {
396226633Sdim      if (implCE->getCastKind() == CK_ARCConsumeObject)
397226633Sdim        return rewriteToBridgedCast(E, OBC_BridgeRetained);
398226633Sdim      if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
399226633Sdim        return rewriteToBridgedCast(E, OBC_Bridge);
400226633Sdim    }
401226633Sdim
402226633Sdim    bool isConsumed = false;
403226633Sdim    if (isPassedToCParamWithKnownOwnership(E, isConsumed))
404226633Sdim      return rewriteToBridgedCast(E, isConsumed ? OBC_BridgeRetained
405226633Sdim                                                : OBC_Bridge);
406224135Sdim  }
407224135Sdim
408226633Sdim  static ObjCMethodFamily getFamilyOfMessage(Expr *E) {
409226633Sdim    E = E->IgnoreParenCasts();
410226633Sdim    if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))
411226633Sdim      return ME->getMethodFamily();
412226633Sdim
413226633Sdim    return OMF_None;
414226633Sdim  }
415226633Sdim
416226633Sdim  bool isPassedToCFRetain(Expr *E, CallExpr *&callE) const {
417226633Sdim    if ((callE = dyn_cast_or_null<CallExpr>(
418226633Sdim                                     StmtMap->getParentIgnoreParenImpCasts(E))))
419226633Sdim      if (FunctionDecl *
420226633Sdim            FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl()))
421226633Sdim        if (FD->getName() == "CFRetain" && FD->getNumParams() == 1 &&
422226633Sdim            FD->getParent()->isTranslationUnit() &&
423261991Sdim            FD->isExternallyVisible())
424226633Sdim          return true;
425226633Sdim
426226633Sdim    return false;
427226633Sdim  }
428226633Sdim
429226633Sdim  bool isPassedToCParamWithKnownOwnership(Expr *E, bool &isConsumed) const {
430226633Sdim    if (CallExpr *callE = dyn_cast_or_null<CallExpr>(
431226633Sdim                                     StmtMap->getParentIgnoreParenImpCasts(E)))
432226633Sdim      if (FunctionDecl *
433226633Sdim            FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) {
434226633Sdim        unsigned i = 0;
435226633Sdim        for (unsigned e = callE->getNumArgs(); i != e; ++i) {
436226633Sdim          Expr *arg = callE->getArg(i);
437226633Sdim          if (arg == E || arg->IgnoreParenImpCasts() == E)
438226633Sdim            break;
439226633Sdim        }
440249423Sdim        if (i < callE->getNumArgs() && i < FD->getNumParams()) {
441226633Sdim          ParmVarDecl *PD = FD->getParamDecl(i);
442276479Sdim          if (PD->hasAttr<CFConsumedAttr>()) {
443226633Sdim            isConsumed = true;
444226633Sdim            return true;
445226633Sdim          }
446226633Sdim        }
447226633Sdim      }
448226633Sdim
449226633Sdim    return false;
450226633Sdim  }
451226633Sdim
452226633Sdim  bool isSelf(Expr *E) const {
453224135Sdim    E = E->IgnoreParenLValueCasts();
454224135Sdim    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
455226633Sdim      if (ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
456226633Sdim        if (IPD->getIdentifier() == SelfII)
457226633Sdim          return true;
458226633Sdim
459224135Sdim    return false;
460224135Sdim  }
461224135Sdim};
462224135Sdim
463224135Sdim} // end anonymous namespace
464224135Sdim
465224135Sdimvoid trans::rewriteUnbridgedCasts(MigrationPass &pass) {
466226633Sdim  BodyTransform<UnbridgedCastRewriter> trans(pass);
467224135Sdim  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
468224135Sdim}
469