clang API Documentation

TransUnbridgedCasts.cpp
Go to the documentation of this file.
00001 //===--- TransUnbridgedCasts.cpp - Transformations to ARC mode ------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // rewriteUnbridgedCasts:
00011 //
00012 // A cast of non-objc pointer to an objc one is checked. If the non-objc pointer
00013 // is from a file-level variable, __bridge cast is used to convert it.
00014 // For the result of a function call that we know is +1/+0,
00015 // __bridge/CFBridgingRelease is used.
00016 //
00017 //  NSString *str = (NSString *)kUTTypePlainText;
00018 //  str = b ? kUTTypeRTF : kUTTypePlainText;
00019 //  NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault,
00020 //                                                         _uuid);
00021 // ---->
00022 //  NSString *str = (__bridge NSString *)kUTTypePlainText;
00023 //  str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
00024 // NSString *_uuidString = (NSString *)
00025 //            CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid));
00026 //
00027 // For a C pointer to ObjC, for casting 'self', __bridge is used.
00028 //
00029 //  CFStringRef str = (CFStringRef)self;
00030 // ---->
00031 //  CFStringRef str = (__bridge CFStringRef)self;
00032 //
00033 // Uses of Block_copy/Block_release macros are rewritten:
00034 //
00035 //  c = Block_copy(b);
00036 //  Block_release(c);
00037 // ---->
00038 //  c = [b copy];
00039 //  <removed>
00040 //
00041 //===----------------------------------------------------------------------===//
00042 
00043 #include "Transforms.h"
00044 #include "Internals.h"
00045 #include "clang/AST/ASTContext.h"
00046 #include "clang/AST/Attr.h"
00047 #include "clang/AST/ParentMap.h"
00048 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
00049 #include "clang/Basic/SourceManager.h"
00050 #include "clang/Lex/Lexer.h"
00051 #include "clang/Sema/SemaDiagnostic.h"
00052 #include "llvm/ADT/SmallString.h"
00053 
00054 using namespace clang;
00055 using namespace arcmt;
00056 using namespace trans;
00057 
00058 namespace {
00059 
00060 class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
00061   MigrationPass &Pass;
00062   IdentifierInfo *SelfII;
00063   std::unique_ptr<ParentMap> StmtMap;
00064   Decl *ParentD;
00065   Stmt *Body;
00066   mutable std::unique_ptr<ExprSet> Removables;
00067 
00068 public:
00069   UnbridgedCastRewriter(MigrationPass &pass)
00070     : Pass(pass), ParentD(nullptr), Body(nullptr) {
00071     SelfII = &Pass.Ctx.Idents.get("self");
00072   }
00073 
00074   void transformBody(Stmt *body, Decl *ParentD) {
00075     this->ParentD = ParentD;
00076     Body = body;
00077     StmtMap.reset(new ParentMap(body));
00078     TraverseStmt(body);
00079   }
00080 
00081   bool TraverseBlockDecl(BlockDecl *D) {
00082     // ParentMap does not enter into a BlockDecl to record its stmts, so use a
00083     // new UnbridgedCastRewriter to handle the block.
00084     UnbridgedCastRewriter(Pass).transformBody(D->getBody(), D);
00085     return true;
00086   }
00087 
00088   bool VisitCastExpr(CastExpr *E) {
00089     if (E->getCastKind() != CK_CPointerToObjCPointerCast &&
00090         E->getCastKind() != CK_BitCast &&
00091         E->getCastKind() != CK_AnyPointerToBlockPointerCast)
00092       return true;
00093 
00094     QualType castType = E->getType();
00095     Expr *castExpr = E->getSubExpr();
00096     QualType castExprType = castExpr->getType();
00097 
00098     if (castType->isObjCRetainableType() == castExprType->isObjCRetainableType())
00099       return true;
00100     
00101     bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
00102     bool castRetainable = castType->isObjCIndirectLifetimeType();
00103     if (exprRetainable == castRetainable) return true;
00104 
00105     if (castExpr->isNullPointerConstant(Pass.Ctx,
00106                                         Expr::NPC_ValueDependentIsNull))
00107       return true;
00108 
00109     SourceLocation loc = castExpr->getExprLoc();
00110     if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc))
00111       return true;
00112 
00113     if (castType->isObjCRetainableType())
00114       transformNonObjCToObjCCast(E);
00115     else
00116       transformObjCToNonObjCCast(E);
00117 
00118     return true;
00119   }
00120 
00121 private:
00122   void transformNonObjCToObjCCast(CastExpr *E) {
00123     if (!E) return;
00124 
00125     // Global vars are assumed that are cast as unretained.
00126     if (isGlobalVar(E))
00127       if (E->getSubExpr()->getType()->isPointerType()) {
00128         castToObjCObject(E, /*retained=*/false);
00129         return;
00130       }
00131 
00132     // If the cast is directly over the result of a Core Foundation function
00133     // try to figure out whether it should be cast as retained or unretained.
00134     Expr *inner = E->IgnoreParenCasts();
00135     if (CallExpr *callE = dyn_cast<CallExpr>(inner)) {
00136       if (FunctionDecl *FD = callE->getDirectCallee()) {
00137         if (FD->hasAttr<CFReturnsRetainedAttr>()) {
00138           castToObjCObject(E, /*retained=*/true);
00139           return;
00140         }
00141         if (FD->hasAttr<CFReturnsNotRetainedAttr>()) {
00142           castToObjCObject(E, /*retained=*/false);
00143           return;
00144         }
00145         if (FD->isGlobal() &&
00146             FD->getIdentifier() &&
00147             ento::cocoa::isRefType(E->getSubExpr()->getType(), "CF",
00148                                    FD->getIdentifier()->getName())) {
00149           StringRef fname = FD->getIdentifier()->getName();
00150           if (fname.endswith("Retain") ||
00151               fname.find("Create") != StringRef::npos ||
00152               fname.find("Copy") != StringRef::npos) {
00153             // Do not migrate to couple of bridge transfer casts which
00154             // cancel each other out. Leave it unchanged so error gets user
00155             // attention instead.
00156             if (FD->getName() == "CFRetain" && 
00157                 FD->getNumParams() == 1 &&
00158                 FD->getParent()->isTranslationUnit() &&
00159                 FD->isExternallyVisible()) {
00160               Expr *Arg = callE->getArg(0);
00161               if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
00162                 const Expr *sub = ICE->getSubExpr();
00163                 QualType T = sub->getType();
00164                 if (T->isObjCObjectPointerType())
00165                   return;
00166               }
00167             }
00168             castToObjCObject(E, /*retained=*/true);
00169             return;
00170           }
00171 
00172           if (fname.find("Get") != StringRef::npos) {
00173             castToObjCObject(E, /*retained=*/false);
00174             return;
00175           }
00176         }
00177       }
00178     }
00179 
00180     // If returning an ivar or a member of an ivar from a +0 method, use
00181     // a __bridge cast.
00182     Expr *base = inner->IgnoreParenImpCasts();
00183     while (isa<MemberExpr>(base))
00184       base = cast<MemberExpr>(base)->getBase()->IgnoreParenImpCasts();
00185     if (isa<ObjCIvarRefExpr>(base) &&
00186         isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(E))) {
00187       if (ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) {
00188         if (!method->hasAttr<NSReturnsRetainedAttr>()) {
00189           castToObjCObject(E, /*retained=*/false);
00190           return;
00191         }
00192       }
00193     }
00194   }
00195 
00196   void castToObjCObject(CastExpr *E, bool retained) {
00197     rewriteToBridgedCast(E, retained ? OBC_BridgeTransfer : OBC_Bridge);
00198   }
00199 
00200   void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) {
00201     Transaction Trans(Pass.TA);
00202     rewriteToBridgedCast(E, Kind, Trans);
00203   }
00204 
00205   void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind,
00206                             Transaction &Trans) {
00207     TransformActions &TA = Pass.TA;
00208 
00209     // We will remove the compiler diagnostic.
00210     if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast,
00211                           diag::err_arc_cast_requires_bridge,
00212                           E->getLocStart())) {
00213       Trans.abort();
00214       return;
00215     }
00216 
00217     StringRef bridge;
00218     switch(Kind) {
00219     case OBC_Bridge:
00220       bridge = "__bridge "; break;
00221     case OBC_BridgeTransfer:
00222       bridge = "__bridge_transfer "; break;
00223     case OBC_BridgeRetained:
00224       bridge = "__bridge_retained "; break;
00225     }
00226 
00227     TA.clearDiagnostic(diag::err_arc_mismatched_cast,
00228                        diag::err_arc_cast_requires_bridge,
00229                        E->getLocStart());
00230     if (Kind == OBC_Bridge || !Pass.CFBridgingFunctionsDefined()) {
00231       if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) {
00232         TA.insertAfterToken(CCE->getLParenLoc(), bridge);
00233       } else {
00234         SourceLocation insertLoc = E->getSubExpr()->getLocStart();
00235         SmallString<128> newCast;
00236         newCast += '(';
00237         newCast += bridge;
00238         newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
00239         newCast += ')';
00240 
00241         if (isa<ParenExpr>(E->getSubExpr())) {
00242           TA.insert(insertLoc, newCast.str());
00243         } else {
00244           newCast += '(';
00245           TA.insert(insertLoc, newCast.str());
00246           TA.insertAfterToken(E->getLocEnd(), ")");
00247         }
00248       }
00249     } else {
00250       assert(Kind == OBC_BridgeTransfer || Kind == OBC_BridgeRetained);
00251       SmallString<32> BridgeCall;
00252 
00253       Expr *WrapE = E->getSubExpr();
00254       SourceLocation InsertLoc = WrapE->getLocStart();
00255 
00256       SourceManager &SM = Pass.Ctx.getSourceManager();
00257       char PrevChar = *SM.getCharacterData(InsertLoc.getLocWithOffset(-1));
00258       if (Lexer::isIdentifierBodyChar(PrevChar, Pass.Ctx.getLangOpts()))
00259         BridgeCall += ' ';
00260 
00261       if (Kind == OBC_BridgeTransfer)
00262         BridgeCall += "CFBridgingRelease";
00263       else
00264         BridgeCall += "CFBridgingRetain";
00265 
00266       if (isa<ParenExpr>(WrapE)) {
00267         TA.insert(InsertLoc, BridgeCall);
00268       } else {
00269         BridgeCall += '(';
00270         TA.insert(InsertLoc, BridgeCall);
00271         TA.insertAfterToken(WrapE->getLocEnd(), ")");
00272       }
00273     }
00274   }
00275 
00276   void rewriteCastForCFRetain(CastExpr *castE, CallExpr *callE) {
00277     Transaction Trans(Pass.TA);
00278     Pass.TA.replace(callE->getSourceRange(), callE->getArg(0)->getSourceRange());
00279     rewriteToBridgedCast(castE, OBC_BridgeRetained, Trans);
00280   }
00281 
00282   void getBlockMacroRanges(CastExpr *E, SourceRange &Outer, SourceRange &Inner) {
00283     SourceManager &SM = Pass.Ctx.getSourceManager();
00284     SourceLocation Loc = E->getExprLoc();
00285     assert(Loc.isMacroID());
00286     SourceLocation MacroBegin, MacroEnd;
00287     std::tie(MacroBegin, MacroEnd) = SM.getImmediateExpansionRange(Loc);
00288     SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange();
00289     SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin());
00290     SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd());
00291 
00292     Outer = SourceRange(MacroBegin, MacroEnd);
00293     Inner = SourceRange(InnerBegin, InnerEnd);
00294   }
00295 
00296   void rewriteBlockCopyMacro(CastExpr *E) {
00297     SourceRange OuterRange, InnerRange;
00298     getBlockMacroRanges(E, OuterRange, InnerRange);
00299 
00300     Transaction Trans(Pass.TA);
00301     Pass.TA.replace(OuterRange, InnerRange);
00302     Pass.TA.insert(InnerRange.getBegin(), "[");
00303     Pass.TA.insertAfterToken(InnerRange.getEnd(), " copy]");
00304     Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
00305                             diag::err_arc_cast_requires_bridge,
00306                             OuterRange);
00307   }
00308 
00309   void removeBlockReleaseMacro(CastExpr *E) {
00310     SourceRange OuterRange, InnerRange;
00311     getBlockMacroRanges(E, OuterRange, InnerRange);
00312 
00313     Transaction Trans(Pass.TA);
00314     Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
00315                             diag::err_arc_cast_requires_bridge,
00316                             OuterRange);
00317     if (!hasSideEffects(E, Pass.Ctx)) {
00318       if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E))))
00319         return;
00320     }
00321     Pass.TA.replace(OuterRange, InnerRange);
00322   }
00323 
00324   bool tryRemoving(Expr *E) const {
00325     if (!Removables) {
00326       Removables.reset(new ExprSet);
00327       collectRemovables(Body, *Removables);
00328     }
00329 
00330     if (Removables->count(E)) {
00331       Pass.TA.removeStmt(E);
00332       return true;
00333     }
00334 
00335     return false;
00336   }
00337 
00338   void transformObjCToNonObjCCast(CastExpr *E) {
00339     SourceLocation CastLoc = E->getExprLoc();
00340     if (CastLoc.isMacroID()) {
00341       StringRef MacroName = Lexer::getImmediateMacroName(CastLoc,
00342                                                     Pass.Ctx.getSourceManager(),
00343                                                     Pass.Ctx.getLangOpts());
00344       if (MacroName == "Block_copy") {
00345         rewriteBlockCopyMacro(E);
00346         return;
00347       }
00348       if (MacroName == "Block_release") {
00349         removeBlockReleaseMacro(E);
00350         return;
00351       }
00352     }
00353 
00354     if (isSelf(E->getSubExpr()))
00355       return rewriteToBridgedCast(E, OBC_Bridge);
00356 
00357     CallExpr *callE;
00358     if (isPassedToCFRetain(E, callE))
00359       return rewriteCastForCFRetain(E, callE);
00360 
00361     ObjCMethodFamily family = getFamilyOfMessage(E->getSubExpr());
00362     if (family == OMF_retain)
00363       return rewriteToBridgedCast(E, OBC_BridgeRetained);
00364 
00365     if (family == OMF_autorelease || family == OMF_release) {
00366       std::string err = "it is not safe to cast to '";
00367       err += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
00368       err += "' the result of '";
00369       err += family == OMF_autorelease ? "autorelease" : "release";
00370       err += "' message; a __bridge cast may result in a pointer to a "
00371           "destroyed object and a __bridge_retained may leak the object";
00372       Pass.TA.reportError(err, E->getLocStart(),
00373                           E->getSubExpr()->getSourceRange());
00374       Stmt *parent = E;
00375       do {
00376         parent = StmtMap->getParentIgnoreParenImpCasts(parent);
00377       } while (parent && isa<ExprWithCleanups>(parent));
00378 
00379       if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
00380         std::string note = "remove the cast and change return type of function "
00381             "to '";
00382         note += E->getSubExpr()->getType().getAsString(Pass.Ctx.getPrintingPolicy());
00383         note += "' to have the object automatically autoreleased";
00384         Pass.TA.reportNote(note, retS->getLocStart());
00385       }
00386     }
00387 
00388     Expr *subExpr = E->getSubExpr();
00389 
00390     // Look through pseudo-object expressions.
00391     if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) {
00392       subExpr = pseudo->getResultExpr();
00393       assert(subExpr && "no result for pseudo-object of non-void type?");
00394     }
00395 
00396     if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) {
00397       if (implCE->getCastKind() == CK_ARCConsumeObject)
00398         return rewriteToBridgedCast(E, OBC_BridgeRetained);
00399       if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
00400         return rewriteToBridgedCast(E, OBC_Bridge);
00401     }
00402 
00403     bool isConsumed = false;
00404     if (isPassedToCParamWithKnownOwnership(E, isConsumed))
00405       return rewriteToBridgedCast(E, isConsumed ? OBC_BridgeRetained
00406                                                 : OBC_Bridge);
00407   }
00408 
00409   static ObjCMethodFamily getFamilyOfMessage(Expr *E) {
00410     E = E->IgnoreParenCasts();
00411     if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))
00412       return ME->getMethodFamily();
00413 
00414     return OMF_None;
00415   }
00416 
00417   bool isPassedToCFRetain(Expr *E, CallExpr *&callE) const {
00418     if ((callE = dyn_cast_or_null<CallExpr>(
00419                                      StmtMap->getParentIgnoreParenImpCasts(E))))
00420       if (FunctionDecl *
00421             FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl()))
00422         if (FD->getName() == "CFRetain" && FD->getNumParams() == 1 &&
00423             FD->getParent()->isTranslationUnit() &&
00424             FD->isExternallyVisible())
00425           return true;
00426 
00427     return false;
00428   }
00429 
00430   bool isPassedToCParamWithKnownOwnership(Expr *E, bool &isConsumed) const {
00431     if (CallExpr *callE = dyn_cast_or_null<CallExpr>(
00432                                      StmtMap->getParentIgnoreParenImpCasts(E)))
00433       if (FunctionDecl *
00434             FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) {
00435         unsigned i = 0;
00436         for (unsigned e = callE->getNumArgs(); i != e; ++i) {
00437           Expr *arg = callE->getArg(i);
00438           if (arg == E || arg->IgnoreParenImpCasts() == E)
00439             break;
00440         }
00441         if (i < callE->getNumArgs() && i < FD->getNumParams()) {
00442           ParmVarDecl *PD = FD->getParamDecl(i);
00443           if (PD->hasAttr<CFConsumedAttr>()) {
00444             isConsumed = true;
00445             return true;
00446           }
00447         }
00448       }
00449 
00450     return false;
00451   }
00452 
00453   bool isSelf(Expr *E) const {
00454     E = E->IgnoreParenLValueCasts();
00455     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
00456       if (ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
00457         if (IPD->getIdentifier() == SelfII)
00458           return true;
00459 
00460     return false;
00461   }
00462 };
00463 
00464 } // end anonymous namespace
00465 
00466 void trans::rewriteUnbridgedCasts(MigrationPass &pass) {
00467   BodyTransform<UnbridgedCastRewriter> trans(pass);
00468   trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
00469 }