diff options
Diffstat (limited to 'lib/ARCMigrate/TransUnbridgedCasts.cpp')
| -rw-r--r-- | lib/ARCMigrate/TransUnbridgedCasts.cpp | 466 | 
1 files changed, 0 insertions, 466 deletions
diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp deleted file mode 100644 index e767ad5346c30..0000000000000 --- a/lib/ARCMigrate/TransUnbridgedCasts.cpp +++ /dev/null @@ -1,466 +0,0 @@ -//===--- TransUnbridgedCasts.cpp - Transformations to ARC mode ------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// rewriteUnbridgedCasts: -// -// A cast of non-objc pointer to an objc one is checked. If the non-objc pointer -// is from a file-level variable, __bridge cast is used to convert it. -// For the result of a function call that we know is +1/+0, -// __bridge/CFBridgingRelease is used. -// -//  NSString *str = (NSString *)kUTTypePlainText; -//  str = b ? kUTTypeRTF : kUTTypePlainText; -//  NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, -//                                                         _uuid); -// ----> -//  NSString *str = (__bridge NSString *)kUTTypePlainText; -//  str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText); -// NSString *_uuidString = (NSString *) -//            CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid)); -// -// For a C pointer to ObjC, for casting 'self', __bridge is used. -// -//  CFStringRef str = (CFStringRef)self; -// ----> -//  CFStringRef str = (__bridge CFStringRef)self; -// -// Uses of Block_copy/Block_release macros are rewritten: -// -//  c = Block_copy(b); -//  Block_release(c); -// ----> -//  c = [b copy]; -//  <removed> -// -//===----------------------------------------------------------------------===// - -#include "Transforms.h" -#include "Internals.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Attr.h" -#include "clang/AST/ParentMap.h" -#include "clang/Analysis/DomainSpecific/CocoaConventions.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Lex/Lexer.h" -#include "clang/Sema/SemaDiagnostic.h" -#include "llvm/ADT/SmallString.h" - -using namespace clang; -using namespace arcmt; -using namespace trans; - -namespace { - -class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{ -  MigrationPass &Pass; -  IdentifierInfo *SelfII; -  std::unique_ptr<ParentMap> StmtMap; -  Decl *ParentD; -  Stmt *Body; -  mutable std::unique_ptr<ExprSet> Removables; - -public: -  UnbridgedCastRewriter(MigrationPass &pass) -    : Pass(pass), ParentD(nullptr), Body(nullptr) { -    SelfII = &Pass.Ctx.Idents.get("self"); -  } - -  void transformBody(Stmt *body, Decl *ParentD) { -    this->ParentD = ParentD; -    Body = body; -    StmtMap.reset(new ParentMap(body)); -    TraverseStmt(body); -  } - -  bool TraverseBlockDecl(BlockDecl *D) { -    // ParentMap does not enter into a BlockDecl to record its stmts, so use a -    // new UnbridgedCastRewriter to handle the block. -    UnbridgedCastRewriter(Pass).transformBody(D->getBody(), D); -    return true; -  } - -  bool VisitCastExpr(CastExpr *E) { -    if (E->getCastKind() != CK_CPointerToObjCPointerCast && -        E->getCastKind() != CK_BitCast && -        E->getCastKind() != CK_AnyPointerToBlockPointerCast) -      return true; - -    QualType castType = E->getType(); -    Expr *castExpr = E->getSubExpr(); -    QualType castExprType = castExpr->getType(); - -    if (castType->isObjCRetainableType() == castExprType->isObjCRetainableType()) -      return true; - -    bool exprRetainable = castExprType->isObjCIndirectLifetimeType(); -    bool castRetainable = castType->isObjCIndirectLifetimeType(); -    if (exprRetainable == castRetainable) return true; - -    if (castExpr->isNullPointerConstant(Pass.Ctx, -                                        Expr::NPC_ValueDependentIsNull)) -      return true; - -    SourceLocation loc = castExpr->getExprLoc(); -    if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc)) -      return true; - -    if (castType->isObjCRetainableType()) -      transformNonObjCToObjCCast(E); -    else -      transformObjCToNonObjCCast(E); - -    return true; -  } - -private: -  void transformNonObjCToObjCCast(CastExpr *E) { -    if (!E) return; - -    // Global vars are assumed that are cast as unretained. -    if (isGlobalVar(E)) -      if (E->getSubExpr()->getType()->isPointerType()) { -        castToObjCObject(E, /*retained=*/false); -        return; -      } - -    // If the cast is directly over the result of a Core Foundation function -    // try to figure out whether it should be cast as retained or unretained. -    Expr *inner = E->IgnoreParenCasts(); -    if (CallExpr *callE = dyn_cast<CallExpr>(inner)) { -      if (FunctionDecl *FD = callE->getDirectCallee()) { -        if (FD->hasAttr<CFReturnsRetainedAttr>()) { -          castToObjCObject(E, /*retained=*/true); -          return; -        } -        if (FD->hasAttr<CFReturnsNotRetainedAttr>()) { -          castToObjCObject(E, /*retained=*/false); -          return; -        } -        if (FD->isGlobal() && -            FD->getIdentifier() && -            ento::cocoa::isRefType(E->getSubExpr()->getType(), "CF", -                                   FD->getIdentifier()->getName())) { -          StringRef fname = FD->getIdentifier()->getName(); -          if (fname.endswith("Retain") || -              fname.find("Create") != StringRef::npos || -              fname.find("Copy") != StringRef::npos) { -            // Do not migrate to couple of bridge transfer casts which -            // cancel each other out. Leave it unchanged so error gets user -            // attention instead. -            if (FD->getName() == "CFRetain" && -                FD->getNumParams() == 1 && -                FD->getParent()->isTranslationUnit() && -                FD->isExternallyVisible()) { -              Expr *Arg = callE->getArg(0); -              if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) { -                const Expr *sub = ICE->getSubExpr(); -                QualType T = sub->getType(); -                if (T->isObjCObjectPointerType()) -                  return; -              } -            } -            castToObjCObject(E, /*retained=*/true); -            return; -          } - -          if (fname.find("Get") != StringRef::npos) { -            castToObjCObject(E, /*retained=*/false); -            return; -          } -        } -      } -    } - -    // If returning an ivar or a member of an ivar from a +0 method, use -    // a __bridge cast. -    Expr *base = inner->IgnoreParenImpCasts(); -    while (isa<MemberExpr>(base)) -      base = cast<MemberExpr>(base)->getBase()->IgnoreParenImpCasts(); -    if (isa<ObjCIvarRefExpr>(base) && -        isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(E))) { -      if (ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) { -        if (!method->hasAttr<NSReturnsRetainedAttr>()) { -          castToObjCObject(E, /*retained=*/false); -          return; -        } -      } -    } -  } - -  void castToObjCObject(CastExpr *E, bool retained) { -    rewriteToBridgedCast(E, retained ? OBC_BridgeTransfer : OBC_Bridge); -  } - -  void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) { -    Transaction Trans(Pass.TA); -    rewriteToBridgedCast(E, Kind, Trans); -  } - -  void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind, -                            Transaction &Trans) { -    TransformActions &TA = Pass.TA; - -    // We will remove the compiler diagnostic. -    if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast, -                          diag::err_arc_cast_requires_bridge, -                          E->getBeginLoc())) { -      Trans.abort(); -      return; -    } - -    StringRef bridge; -    switch(Kind) { -    case OBC_Bridge: -      bridge = "__bridge "; break; -    case OBC_BridgeTransfer: -      bridge = "__bridge_transfer "; break; -    case OBC_BridgeRetained: -      bridge = "__bridge_retained "; break; -    } - -    TA.clearDiagnostic(diag::err_arc_mismatched_cast, -                       diag::err_arc_cast_requires_bridge, E->getBeginLoc()); -    if (Kind == OBC_Bridge || !Pass.CFBridgingFunctionsDefined()) { -      if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) { -        TA.insertAfterToken(CCE->getLParenLoc(), bridge); -      } else { -        SourceLocation insertLoc = E->getSubExpr()->getBeginLoc(); -        SmallString<128> newCast; -        newCast += '('; -        newCast += bridge; -        newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy()); -        newCast += ')'; - -        if (isa<ParenExpr>(E->getSubExpr())) { -          TA.insert(insertLoc, newCast.str()); -        } else { -          newCast += '('; -          TA.insert(insertLoc, newCast.str()); -          TA.insertAfterToken(E->getEndLoc(), ")"); -        } -      } -    } else { -      assert(Kind == OBC_BridgeTransfer || Kind == OBC_BridgeRetained); -      SmallString<32> BridgeCall; - -      Expr *WrapE = E->getSubExpr(); -      SourceLocation InsertLoc = WrapE->getBeginLoc(); - -      SourceManager &SM = Pass.Ctx.getSourceManager(); -      char PrevChar = *SM.getCharacterData(InsertLoc.getLocWithOffset(-1)); -      if (Lexer::isIdentifierBodyChar(PrevChar, Pass.Ctx.getLangOpts())) -        BridgeCall += ' '; - -      if (Kind == OBC_BridgeTransfer) -        BridgeCall += "CFBridgingRelease"; -      else -        BridgeCall += "CFBridgingRetain"; - -      if (isa<ParenExpr>(WrapE)) { -        TA.insert(InsertLoc, BridgeCall); -      } else { -        BridgeCall += '('; -        TA.insert(InsertLoc, BridgeCall); -        TA.insertAfterToken(WrapE->getEndLoc(), ")"); -      } -    } -  } - -  void rewriteCastForCFRetain(CastExpr *castE, CallExpr *callE) { -    Transaction Trans(Pass.TA); -    Pass.TA.replace(callE->getSourceRange(), callE->getArg(0)->getSourceRange()); -    rewriteToBridgedCast(castE, OBC_BridgeRetained, Trans); -  } - -  void getBlockMacroRanges(CastExpr *E, SourceRange &Outer, SourceRange &Inner) { -    SourceManager &SM = Pass.Ctx.getSourceManager(); -    SourceLocation Loc = E->getExprLoc(); -    assert(Loc.isMacroID()); -    CharSourceRange MacroRange = SM.getImmediateExpansionRange(Loc); -    SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange(); -    SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin()); -    SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd()); - -    Outer = MacroRange.getAsRange(); -    Inner = SourceRange(InnerBegin, InnerEnd); -  } - -  void rewriteBlockCopyMacro(CastExpr *E) { -    SourceRange OuterRange, InnerRange; -    getBlockMacroRanges(E, OuterRange, InnerRange); - -    Transaction Trans(Pass.TA); -    Pass.TA.replace(OuterRange, InnerRange); -    Pass.TA.insert(InnerRange.getBegin(), "["); -    Pass.TA.insertAfterToken(InnerRange.getEnd(), " copy]"); -    Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast, -                            diag::err_arc_cast_requires_bridge, -                            OuterRange); -  } - -  void removeBlockReleaseMacro(CastExpr *E) { -    SourceRange OuterRange, InnerRange; -    getBlockMacroRanges(E, OuterRange, InnerRange); - -    Transaction Trans(Pass.TA); -    Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast, -                            diag::err_arc_cast_requires_bridge, -                            OuterRange); -    if (!hasSideEffects(E, Pass.Ctx)) { -      if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E)))) -        return; -    } -    Pass.TA.replace(OuterRange, InnerRange); -  } - -  bool tryRemoving(Expr *E) const { -    if (!Removables) { -      Removables.reset(new ExprSet); -      collectRemovables(Body, *Removables); -    } - -    if (Removables->count(E)) { -      Pass.TA.removeStmt(E); -      return true; -    } - -    return false; -  } - -  void transformObjCToNonObjCCast(CastExpr *E) { -    SourceLocation CastLoc = E->getExprLoc(); -    if (CastLoc.isMacroID()) { -      StringRef MacroName = Lexer::getImmediateMacroName(CastLoc, -                                                    Pass.Ctx.getSourceManager(), -                                                    Pass.Ctx.getLangOpts()); -      if (MacroName == "Block_copy") { -        rewriteBlockCopyMacro(E); -        return; -      } -      if (MacroName == "Block_release") { -        removeBlockReleaseMacro(E); -        return; -      } -    } - -    if (isSelf(E->getSubExpr())) -      return rewriteToBridgedCast(E, OBC_Bridge); - -    CallExpr *callE; -    if (isPassedToCFRetain(E, callE)) -      return rewriteCastForCFRetain(E, callE); - -    ObjCMethodFamily family = getFamilyOfMessage(E->getSubExpr()); -    if (family == OMF_retain) -      return rewriteToBridgedCast(E, OBC_BridgeRetained); - -    if (family == OMF_autorelease || family == OMF_release) { -      std::string err = "it is not safe to cast to '"; -      err += E->getType().getAsString(Pass.Ctx.getPrintingPolicy()); -      err += "' the result of '"; -      err += family == OMF_autorelease ? "autorelease" : "release"; -      err += "' message; a __bridge cast may result in a pointer to a " -          "destroyed object and a __bridge_retained may leak the object"; -      Pass.TA.reportError(err, E->getBeginLoc(), -                          E->getSubExpr()->getSourceRange()); -      Stmt *parent = E; -      do { -        parent = StmtMap->getParentIgnoreParenImpCasts(parent); -      } while (parent && isa<FullExpr>(parent)); - -      if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) { -        std::string note = "remove the cast and change return type of function " -            "to '"; -        note += E->getSubExpr()->getType().getAsString(Pass.Ctx.getPrintingPolicy()); -        note += "' to have the object automatically autoreleased"; -        Pass.TA.reportNote(note, retS->getBeginLoc()); -      } -    } - -    Expr *subExpr = E->getSubExpr(); - -    // Look through pseudo-object expressions. -    if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) { -      subExpr = pseudo->getResultExpr(); -      assert(subExpr && "no result for pseudo-object of non-void type?"); -    } - -    if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) { -      if (implCE->getCastKind() == CK_ARCConsumeObject) -        return rewriteToBridgedCast(E, OBC_BridgeRetained); -      if (implCE->getCastKind() == CK_ARCReclaimReturnedObject) -        return rewriteToBridgedCast(E, OBC_Bridge); -    } - -    bool isConsumed = false; -    if (isPassedToCParamWithKnownOwnership(E, isConsumed)) -      return rewriteToBridgedCast(E, isConsumed ? OBC_BridgeRetained -                                                : OBC_Bridge); -  } - -  static ObjCMethodFamily getFamilyOfMessage(Expr *E) { -    E = E->IgnoreParenCasts(); -    if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) -      return ME->getMethodFamily(); - -    return OMF_None; -  } - -  bool isPassedToCFRetain(Expr *E, CallExpr *&callE) const { -    if ((callE = dyn_cast_or_null<CallExpr>( -                                     StmtMap->getParentIgnoreParenImpCasts(E)))) -      if (FunctionDecl * -            FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) -        if (FD->getName() == "CFRetain" && FD->getNumParams() == 1 && -            FD->getParent()->isTranslationUnit() && -            FD->isExternallyVisible()) -          return true; - -    return false; -  } - -  bool isPassedToCParamWithKnownOwnership(Expr *E, bool &isConsumed) const { -    if (CallExpr *callE = dyn_cast_or_null<CallExpr>( -                                     StmtMap->getParentIgnoreParenImpCasts(E))) -      if (FunctionDecl * -            FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) { -        unsigned i = 0; -        for (unsigned e = callE->getNumArgs(); i != e; ++i) { -          Expr *arg = callE->getArg(i); -          if (arg == E || arg->IgnoreParenImpCasts() == E) -            break; -        } -        if (i < callE->getNumArgs() && i < FD->getNumParams()) { -          ParmVarDecl *PD = FD->getParamDecl(i); -          if (PD->hasAttr<CFConsumedAttr>()) { -            isConsumed = true; -            return true; -          } -        } -      } - -    return false; -  } - -  bool isSelf(Expr *E) const { -    E = E->IgnoreParenLValueCasts(); -    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) -      if (ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(DRE->getDecl())) -        if (IPD->getIdentifier() == SelfII) -          return true; - -    return false; -  } -}; - -} // end anonymous namespace - -void trans::rewriteUnbridgedCasts(MigrationPass &pass) { -  BodyTransform<UnbridgedCastRewriter> trans(pass); -  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl()); -}  | 
