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