//===--- 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.ends_with("Retain") || fname.contains("Create") ||
              fname.contains("Copy")) {
            // 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.contains("Get")) {
            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::isAsciiIdentifierContinueChar(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());
}
