1249423Sdim//===--- TransUnbridgedCasts.cpp - Transformations to ARC mode ------------===//
2224135Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6224135Sdim//
7224135Sdim//===----------------------------------------------------------------------===//
8224135Sdim//
9224135Sdim// rewriteUnbridgedCasts:
10224135Sdim//
11224135Sdim// A cast of non-objc pointer to an objc one is checked. If the non-objc pointer
12224135Sdim// is from a file-level variable, __bridge cast is used to convert it.
13224135Sdim// For the result of a function call that we know is +1/+0,
14239462Sdim// __bridge/CFBridgingRelease is used.
15224135Sdim//
16224135Sdim//  NSString *str = (NSString *)kUTTypePlainText;
17224135Sdim//  str = b ? kUTTypeRTF : kUTTypePlainText;
18224135Sdim//  NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault,
19224135Sdim//                                                         _uuid);
20224135Sdim// ---->
21224135Sdim//  NSString *str = (__bridge NSString *)kUTTypePlainText;
22224135Sdim//  str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
23239462Sdim// NSString *_uuidString = (NSString *)
24239462Sdim//            CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid));
25224135Sdim//
26224135Sdim// For a C pointer to ObjC, for casting 'self', __bridge is used.
27224135Sdim//
28224135Sdim//  CFStringRef str = (CFStringRef)self;
29224135Sdim// ---->
30224135Sdim//  CFStringRef str = (__bridge CFStringRef)self;
31224135Sdim//
32249423Sdim// Uses of Block_copy/Block_release macros are rewritten:
33249423Sdim//
34249423Sdim//  c = Block_copy(b);
35249423Sdim//  Block_release(c);
36249423Sdim// ---->
37249423Sdim//  c = [b copy];
38249423Sdim//  <removed>
39249423Sdim//
40224135Sdim//===----------------------------------------------------------------------===//
41224135Sdim
42224135Sdim#include "Transforms.h"
43224135Sdim#include "Internals.h"
44239462Sdim#include "clang/AST/ASTContext.h"
45249423Sdim#include "clang/AST/Attr.h"
46226633Sdim#include "clang/AST/ParentMap.h"
47249423Sdim#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
48224135Sdim#include "clang/Basic/SourceManager.h"
49239462Sdim#include "clang/Lex/Lexer.h"
50239462Sdim#include "clang/Sema/SemaDiagnostic.h"
51234353Sdim#include "llvm/ADT/SmallString.h"
52224135Sdim
53224135Sdimusing namespace clang;
54224135Sdimusing namespace arcmt;
55224135Sdimusing namespace trans;
56224135Sdim
57224135Sdimnamespace {
58224135Sdim
59224135Sdimclass UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
60224135Sdim  MigrationPass &Pass;
61224135Sdim  IdentifierInfo *SelfII;
62276479Sdim  std::unique_ptr<ParentMap> StmtMap;
63239462Sdim  Decl *ParentD;
64249423Sdim  Stmt *Body;
65276479Sdim  mutable std::unique_ptr<ExprSet> Removables;
66226633Sdim
67224135Sdimpublic:
68276479Sdim  UnbridgedCastRewriter(MigrationPass &pass)
69276479Sdim    : Pass(pass), ParentD(nullptr), Body(nullptr) {
70224135Sdim    SelfII = &Pass.Ctx.Idents.get("self");
71224135Sdim  }
72224135Sdim
73239462Sdim  void transformBody(Stmt *body, Decl *ParentD) {
74239462Sdim    this->ParentD = ParentD;
75249423Sdim    Body = body;
76226633Sdim    StmtMap.reset(new ParentMap(body));
77226633Sdim    TraverseStmt(body);
78226633Sdim  }
79226633Sdim
80261991Sdim  bool TraverseBlockDecl(BlockDecl *D) {
81261991Sdim    // ParentMap does not enter into a BlockDecl to record its stmts, so use a
82261991Sdim    // new UnbridgedCastRewriter to handle the block.
83261991Sdim    UnbridgedCastRewriter(Pass).transformBody(D->getBody(), D);
84261991Sdim    return true;
85261991Sdim  }
86261991Sdim
87224135Sdim  bool VisitCastExpr(CastExpr *E) {
88249423Sdim    if (E->getCastKind() != CK_CPointerToObjCPointerCast &&
89249423Sdim        E->getCastKind() != CK_BitCast &&
90249423Sdim        E->getCastKind() != CK_AnyPointerToBlockPointerCast)
91224135Sdim      return true;
92224135Sdim
93224135Sdim    QualType castType = E->getType();
94224135Sdim    Expr *castExpr = E->getSubExpr();
95224135Sdim    QualType castExprType = castExpr->getType();
96224135Sdim
97249423Sdim    if (castType->isObjCRetainableType() == castExprType->isObjCRetainableType())
98224135Sdim      return true;
99341825Sdim
100224135Sdim    bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
101224135Sdim    bool castRetainable = castType->isObjCIndirectLifetimeType();
102224135Sdim    if (exprRetainable == castRetainable) return true;
103224135Sdim
104224135Sdim    if (castExpr->isNullPointerConstant(Pass.Ctx,
105224135Sdim                                        Expr::NPC_ValueDependentIsNull))
106224135Sdim      return true;
107224135Sdim
108224135Sdim    SourceLocation loc = castExpr->getExprLoc();
109224135Sdim    if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc))
110224135Sdim      return true;
111224135Sdim
112249423Sdim    if (castType->isObjCRetainableType())
113224135Sdim      transformNonObjCToObjCCast(E);
114224135Sdim    else
115224135Sdim      transformObjCToNonObjCCast(E);
116224135Sdim
117224135Sdim    return true;
118224135Sdim  }
119224135Sdim
120224135Sdimprivate:
121224135Sdim  void transformNonObjCToObjCCast(CastExpr *E) {
122224135Sdim    if (!E) return;
123224135Sdim
124224135Sdim    // Global vars are assumed that are cast as unretained.
125224135Sdim    if (isGlobalVar(E))
126224135Sdim      if (E->getSubExpr()->getType()->isPointerType()) {
127224135Sdim        castToObjCObject(E, /*retained=*/false);
128224135Sdim        return;
129224135Sdim      }
130224135Sdim
131224135Sdim    // If the cast is directly over the result of a Core Foundation function
132224135Sdim    // try to figure out whether it should be cast as retained or unretained.
133224135Sdim    Expr *inner = E->IgnoreParenCasts();
134224135Sdim    if (CallExpr *callE = dyn_cast<CallExpr>(inner)) {
135224135Sdim      if (FunctionDecl *FD = callE->getDirectCallee()) {
136276479Sdim        if (FD->hasAttr<CFReturnsRetainedAttr>()) {
137224135Sdim          castToObjCObject(E, /*retained=*/true);
138224135Sdim          return;
139224135Sdim        }
140276479Sdim        if (FD->hasAttr<CFReturnsNotRetainedAttr>()) {
141224135Sdim          castToObjCObject(E, /*retained=*/false);
142224135Sdim          return;
143224135Sdim        }
144224135Sdim        if (FD->isGlobal() &&
145224135Sdim            FD->getIdentifier() &&
146224135Sdim            ento::cocoa::isRefType(E->getSubExpr()->getType(), "CF",
147224135Sdim                                   FD->getIdentifier()->getName())) {
148224135Sdim          StringRef fname = FD->getIdentifier()->getName();
149224135Sdim          if (fname.endswith("Retain") ||
150224135Sdim              fname.find("Create") != StringRef::npos ||
151224135Sdim              fname.find("Copy") != StringRef::npos) {
152234353Sdim            // Do not migrate to couple of bridge transfer casts which
153234353Sdim            // cancel each other out. Leave it unchanged so error gets user
154234353Sdim            // attention instead.
155341825Sdim            if (FD->getName() == "CFRetain" &&
156234353Sdim                FD->getNumParams() == 1 &&
157234353Sdim                FD->getParent()->isTranslationUnit() &&
158261991Sdim                FD->isExternallyVisible()) {
159234353Sdim              Expr *Arg = callE->getArg(0);
160234353Sdim              if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
161234353Sdim                const Expr *sub = ICE->getSubExpr();
162234353Sdim                QualType T = sub->getType();
163234353Sdim                if (T->isObjCObjectPointerType())
164234353Sdim                  return;
165234353Sdim              }
166234353Sdim            }
167224135Sdim            castToObjCObject(E, /*retained=*/true);
168224135Sdim            return;
169224135Sdim          }
170224135Sdim
171224135Sdim          if (fname.find("Get") != StringRef::npos) {
172224135Sdim            castToObjCObject(E, /*retained=*/false);
173224135Sdim            return;
174224135Sdim          }
175224135Sdim        }
176224135Sdim      }
177224135Sdim    }
178239462Sdim
179239462Sdim    // If returning an ivar or a member of an ivar from a +0 method, use
180239462Sdim    // a __bridge cast.
181239462Sdim    Expr *base = inner->IgnoreParenImpCasts();
182239462Sdim    while (isa<MemberExpr>(base))
183239462Sdim      base = cast<MemberExpr>(base)->getBase()->IgnoreParenImpCasts();
184239462Sdim    if (isa<ObjCIvarRefExpr>(base) &&
185239462Sdim        isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(E))) {
186239462Sdim      if (ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) {
187239462Sdim        if (!method->hasAttr<NSReturnsRetainedAttr>()) {
188239462Sdim          castToObjCObject(E, /*retained=*/false);
189239462Sdim          return;
190239462Sdim        }
191239462Sdim      }
192239462Sdim    }
193224135Sdim  }
194224135Sdim
195224135Sdim  void castToObjCObject(CastExpr *E, bool retained) {
196224135Sdim    rewriteToBridgedCast(E, retained ? OBC_BridgeTransfer : OBC_Bridge);
197224135Sdim  }
198224135Sdim
199224135Sdim  void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) {
200226633Sdim    Transaction Trans(Pass.TA);
201226633Sdim    rewriteToBridgedCast(E, Kind, Trans);
202226633Sdim  }
203226633Sdim
204226633Sdim  void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind,
205226633Sdim                            Transaction &Trans) {
206224135Sdim    TransformActions &TA = Pass.TA;
207224135Sdim
208224135Sdim    // We will remove the compiler diagnostic.
209224135Sdim    if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast,
210224135Sdim                          diag::err_arc_cast_requires_bridge,
211344779Sdim                          E->getBeginLoc())) {
212226633Sdim      Trans.abort();
213224135Sdim      return;
214226633Sdim    }
215224135Sdim
216224135Sdim    StringRef bridge;
217224135Sdim    switch(Kind) {
218224135Sdim    case OBC_Bridge:
219224135Sdim      bridge = "__bridge "; break;
220224135Sdim    case OBC_BridgeTransfer:
221224135Sdim      bridge = "__bridge_transfer "; break;
222224135Sdim    case OBC_BridgeRetained:
223224135Sdim      bridge = "__bridge_retained "; break;
224224135Sdim    }
225224135Sdim
226224135Sdim    TA.clearDiagnostic(diag::err_arc_mismatched_cast,
227344779Sdim                       diag::err_arc_cast_requires_bridge, E->getBeginLoc());
228239462Sdim    if (Kind == OBC_Bridge || !Pass.CFBridgingFunctionsDefined()) {
229239462Sdim      if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) {
230239462Sdim        TA.insertAfterToken(CCE->getLParenLoc(), bridge);
231239462Sdim      } else {
232344779Sdim        SourceLocation insertLoc = E->getSubExpr()->getBeginLoc();
233239462Sdim        SmallString<128> newCast;
234239462Sdim        newCast += '(';
235239462Sdim        newCast += bridge;
236239462Sdim        newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
237239462Sdim        newCast += ')';
238239462Sdim
239239462Sdim        if (isa<ParenExpr>(E->getSubExpr())) {
240239462Sdim          TA.insert(insertLoc, newCast.str());
241239462Sdim        } else {
242239462Sdim          newCast += '(';
243239462Sdim          TA.insert(insertLoc, newCast.str());
244344779Sdim          TA.insertAfterToken(E->getEndLoc(), ")");
245239462Sdim        }
246239462Sdim      }
247224135Sdim    } else {
248239462Sdim      assert(Kind == OBC_BridgeTransfer || Kind == OBC_BridgeRetained);
249239462Sdim      SmallString<32> BridgeCall;
250224135Sdim
251239462Sdim      Expr *WrapE = E->getSubExpr();
252344779Sdim      SourceLocation InsertLoc = WrapE->getBeginLoc();
253239462Sdim
254239462Sdim      SourceManager &SM = Pass.Ctx.getSourceManager();
255239462Sdim      char PrevChar = *SM.getCharacterData(InsertLoc.getLocWithOffset(-1));
256239462Sdim      if (Lexer::isIdentifierBodyChar(PrevChar, Pass.Ctx.getLangOpts()))
257239462Sdim        BridgeCall += ' ';
258239462Sdim
259239462Sdim      if (Kind == OBC_BridgeTransfer)
260239462Sdim        BridgeCall += "CFBridgingRelease";
261239462Sdim      else
262239462Sdim        BridgeCall += "CFBridgingRetain";
263239462Sdim
264239462Sdim      if (isa<ParenExpr>(WrapE)) {
265239462Sdim        TA.insert(InsertLoc, BridgeCall);
266224135Sdim      } else {
267239462Sdim        BridgeCall += '(';
268239462Sdim        TA.insert(InsertLoc, BridgeCall);
269344779Sdim        TA.insertAfterToken(WrapE->getEndLoc(), ")");
270224135Sdim      }
271224135Sdim    }
272224135Sdim  }
273224135Sdim
274226633Sdim  void rewriteCastForCFRetain(CastExpr *castE, CallExpr *callE) {
275226633Sdim    Transaction Trans(Pass.TA);
276226633Sdim    Pass.TA.replace(callE->getSourceRange(), callE->getArg(0)->getSourceRange());
277226633Sdim    rewriteToBridgedCast(castE, OBC_BridgeRetained, Trans);
278226633Sdim  }
279226633Sdim
280249423Sdim  void getBlockMacroRanges(CastExpr *E, SourceRange &Outer, SourceRange &Inner) {
281249423Sdim    SourceManager &SM = Pass.Ctx.getSourceManager();
282249423Sdim    SourceLocation Loc = E->getExprLoc();
283249423Sdim    assert(Loc.isMacroID());
284341825Sdim    CharSourceRange MacroRange = SM.getImmediateExpansionRange(Loc);
285249423Sdim    SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange();
286249423Sdim    SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin());
287249423Sdim    SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd());
288249423Sdim
289341825Sdim    Outer = MacroRange.getAsRange();
290249423Sdim    Inner = SourceRange(InnerBegin, InnerEnd);
291249423Sdim  }
292249423Sdim
293249423Sdim  void rewriteBlockCopyMacro(CastExpr *E) {
294249423Sdim    SourceRange OuterRange, InnerRange;
295249423Sdim    getBlockMacroRanges(E, OuterRange, InnerRange);
296249423Sdim
297249423Sdim    Transaction Trans(Pass.TA);
298249423Sdim    Pass.TA.replace(OuterRange, InnerRange);
299249423Sdim    Pass.TA.insert(InnerRange.getBegin(), "[");
300249423Sdim    Pass.TA.insertAfterToken(InnerRange.getEnd(), " copy]");
301249423Sdim    Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
302249423Sdim                            diag::err_arc_cast_requires_bridge,
303249423Sdim                            OuterRange);
304249423Sdim  }
305249423Sdim
306249423Sdim  void removeBlockReleaseMacro(CastExpr *E) {
307249423Sdim    SourceRange OuterRange, InnerRange;
308249423Sdim    getBlockMacroRanges(E, OuterRange, InnerRange);
309249423Sdim
310249423Sdim    Transaction Trans(Pass.TA);
311249423Sdim    Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
312249423Sdim                            diag::err_arc_cast_requires_bridge,
313249423Sdim                            OuterRange);
314249423Sdim    if (!hasSideEffects(E, Pass.Ctx)) {
315249423Sdim      if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E))))
316249423Sdim        return;
317249423Sdim    }
318249423Sdim    Pass.TA.replace(OuterRange, InnerRange);
319249423Sdim  }
320249423Sdim
321249423Sdim  bool tryRemoving(Expr *E) const {
322249423Sdim    if (!Removables) {
323249423Sdim      Removables.reset(new ExprSet);
324249423Sdim      collectRemovables(Body, *Removables);
325249423Sdim    }
326249423Sdim
327249423Sdim    if (Removables->count(E)) {
328249423Sdim      Pass.TA.removeStmt(E);
329249423Sdim      return true;
330249423Sdim    }
331249423Sdim
332249423Sdim    return false;
333249423Sdim  }
334249423Sdim
335224135Sdim  void transformObjCToNonObjCCast(CastExpr *E) {
336249423Sdim    SourceLocation CastLoc = E->getExprLoc();
337249423Sdim    if (CastLoc.isMacroID()) {
338249423Sdim      StringRef MacroName = Lexer::getImmediateMacroName(CastLoc,
339249423Sdim                                                    Pass.Ctx.getSourceManager(),
340249423Sdim                                                    Pass.Ctx.getLangOpts());
341249423Sdim      if (MacroName == "Block_copy") {
342249423Sdim        rewriteBlockCopyMacro(E);
343249423Sdim        return;
344249423Sdim      }
345249423Sdim      if (MacroName == "Block_release") {
346249423Sdim        removeBlockReleaseMacro(E);
347249423Sdim        return;
348249423Sdim      }
349249423Sdim    }
350249423Sdim
351224135Sdim    if (isSelf(E->getSubExpr()))
352224135Sdim      return rewriteToBridgedCast(E, OBC_Bridge);
353226633Sdim
354226633Sdim    CallExpr *callE;
355226633Sdim    if (isPassedToCFRetain(E, callE))
356226633Sdim      return rewriteCastForCFRetain(E, callE);
357226633Sdim
358226633Sdim    ObjCMethodFamily family = getFamilyOfMessage(E->getSubExpr());
359226633Sdim    if (family == OMF_retain)
360226633Sdim      return rewriteToBridgedCast(E, OBC_BridgeRetained);
361226633Sdim
362226633Sdim    if (family == OMF_autorelease || family == OMF_release) {
363226633Sdim      std::string err = "it is not safe to cast to '";
364226633Sdim      err += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
365226633Sdim      err += "' the result of '";
366226633Sdim      err += family == OMF_autorelease ? "autorelease" : "release";
367226633Sdim      err += "' message; a __bridge cast may result in a pointer to a "
368226633Sdim          "destroyed object and a __bridge_retained may leak the object";
369344779Sdim      Pass.TA.reportError(err, E->getBeginLoc(),
370226633Sdim                          E->getSubExpr()->getSourceRange());
371226633Sdim      Stmt *parent = E;
372226633Sdim      do {
373226633Sdim        parent = StmtMap->getParentIgnoreParenImpCasts(parent);
374344779Sdim      } while (parent && isa<FullExpr>(parent));
375226633Sdim
376226633Sdim      if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
377226633Sdim        std::string note = "remove the cast and change return type of function "
378226633Sdim            "to '";
379226633Sdim        note += E->getSubExpr()->getType().getAsString(Pass.Ctx.getPrintingPolicy());
380226633Sdim        note += "' to have the object automatically autoreleased";
381344779Sdim        Pass.TA.reportNote(note, retS->getBeginLoc());
382226633Sdim      }
383226633Sdim    }
384226633Sdim
385234353Sdim    Expr *subExpr = E->getSubExpr();
386234353Sdim
387234353Sdim    // Look through pseudo-object expressions.
388234353Sdim    if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) {
389234353Sdim      subExpr = pseudo->getResultExpr();
390234353Sdim      assert(subExpr && "no result for pseudo-object of non-void type?");
391234353Sdim    }
392234353Sdim
393234353Sdim    if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) {
394226633Sdim      if (implCE->getCastKind() == CK_ARCConsumeObject)
395226633Sdim        return rewriteToBridgedCast(E, OBC_BridgeRetained);
396226633Sdim      if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
397226633Sdim        return rewriteToBridgedCast(E, OBC_Bridge);
398226633Sdim    }
399226633Sdim
400226633Sdim    bool isConsumed = false;
401226633Sdim    if (isPassedToCParamWithKnownOwnership(E, isConsumed))
402226633Sdim      return rewriteToBridgedCast(E, isConsumed ? OBC_BridgeRetained
403226633Sdim                                                : OBC_Bridge);
404224135Sdim  }
405224135Sdim
406226633Sdim  static ObjCMethodFamily getFamilyOfMessage(Expr *E) {
407226633Sdim    E = E->IgnoreParenCasts();
408226633Sdim    if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))
409226633Sdim      return ME->getMethodFamily();
410226633Sdim
411226633Sdim    return OMF_None;
412226633Sdim  }
413226633Sdim
414226633Sdim  bool isPassedToCFRetain(Expr *E, CallExpr *&callE) const {
415226633Sdim    if ((callE = dyn_cast_or_null<CallExpr>(
416226633Sdim                                     StmtMap->getParentIgnoreParenImpCasts(E))))
417226633Sdim      if (FunctionDecl *
418226633Sdim            FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl()))
419226633Sdim        if (FD->getName() == "CFRetain" && FD->getNumParams() == 1 &&
420226633Sdim            FD->getParent()->isTranslationUnit() &&
421261991Sdim            FD->isExternallyVisible())
422226633Sdim          return true;
423226633Sdim
424226633Sdim    return false;
425226633Sdim  }
426226633Sdim
427226633Sdim  bool isPassedToCParamWithKnownOwnership(Expr *E, bool &isConsumed) const {
428226633Sdim    if (CallExpr *callE = dyn_cast_or_null<CallExpr>(
429226633Sdim                                     StmtMap->getParentIgnoreParenImpCasts(E)))
430226633Sdim      if (FunctionDecl *
431226633Sdim            FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) {
432226633Sdim        unsigned i = 0;
433226633Sdim        for (unsigned e = callE->getNumArgs(); i != e; ++i) {
434226633Sdim          Expr *arg = callE->getArg(i);
435226633Sdim          if (arg == E || arg->IgnoreParenImpCasts() == E)
436226633Sdim            break;
437226633Sdim        }
438249423Sdim        if (i < callE->getNumArgs() && i < FD->getNumParams()) {
439226633Sdim          ParmVarDecl *PD = FD->getParamDecl(i);
440276479Sdim          if (PD->hasAttr<CFConsumedAttr>()) {
441226633Sdim            isConsumed = true;
442226633Sdim            return true;
443226633Sdim          }
444226633Sdim        }
445226633Sdim      }
446226633Sdim
447226633Sdim    return false;
448226633Sdim  }
449226633Sdim
450226633Sdim  bool isSelf(Expr *E) const {
451224135Sdim    E = E->IgnoreParenLValueCasts();
452224135Sdim    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
453226633Sdim      if (ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
454226633Sdim        if (IPD->getIdentifier() == SelfII)
455226633Sdim          return true;
456226633Sdim
457224135Sdim    return false;
458224135Sdim  }
459224135Sdim};
460224135Sdim
461224135Sdim} // end anonymous namespace
462224135Sdim
463224135Sdimvoid trans::rewriteUnbridgedCasts(MigrationPass &pass) {
464226633Sdim  BodyTransform<UnbridgedCastRewriter> trans(pass);
465224135Sdim  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
466224135Sdim}
467