//===--- TransAutoreleasePool.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
//
//===----------------------------------------------------------------------===//
//
// rewriteAutoreleasePool:
//
// Calls to NSAutoreleasePools will be rewritten as an @autorelease scope.
//
//  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//  ...
//  [pool release];
// ---->
//  @autorelease {
//  ...
//  }
//
// An NSAutoreleasePool will not be touched if:
// - There is not a corresponding -release/-drain in the same scope
// - Not all references of the NSAutoreleasePool variable can be removed
// - There is a variable that is declared inside the intended @autorelease scope
//   which is also used outside it.
//
//===----------------------------------------------------------------------===//

#include "Transforms.h"
#include "Internals.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Sema/SemaDiagnostic.h"
#include <map>

using namespace clang;
using namespace arcmt;
using namespace trans;

namespace {

class ReleaseCollector : public RecursiveASTVisitor<ReleaseCollector> {
  Decl *Dcl;
  SmallVectorImpl<ObjCMessageExpr *> &Releases;

public:
  ReleaseCollector(Decl *D, SmallVectorImpl<ObjCMessageExpr *> &releases)
    : Dcl(D), Releases(releases) { }

  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
    if (!E->isInstanceMessage())
      return true;
    if (E->getMethodFamily() != OMF_release)
      return true;
    Expr *instance = E->getInstanceReceiver()->IgnoreParenCasts();
    if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(instance)) {
      if (DE->getDecl() == Dcl)
        Releases.push_back(E);
    }
    return true;
  }
};

}

namespace {

class AutoreleasePoolRewriter
                         : public RecursiveASTVisitor<AutoreleasePoolRewriter> {
public:
  AutoreleasePoolRewriter(MigrationPass &pass)
    : Body(nullptr), Pass(pass) {
    PoolII = &pass.Ctx.Idents.get("NSAutoreleasePool");
    DrainSel = pass.Ctx.Selectors.getNullarySelector(
                                                 &pass.Ctx.Idents.get("drain"));
  }

  void transformBody(Stmt *body, Decl *ParentD) {
    Body = body;
    TraverseStmt(body);
  }

  ~AutoreleasePoolRewriter() {
    SmallVector<VarDecl *, 8> VarsToHandle;

    for (std::map<VarDecl *, PoolVarInfo>::iterator
           I = PoolVars.begin(), E = PoolVars.end(); I != E; ++I) {
      VarDecl *var = I->first;
      PoolVarInfo &info = I->second;

      // Check that we can handle/rewrite all references of the pool.

      clearRefsIn(info.Dcl, info.Refs);
      for (SmallVectorImpl<PoolScope>::iterator
             scpI = info.Scopes.begin(),
             scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
        PoolScope &scope = *scpI;
        clearRefsIn(*scope.Begin, info.Refs);
        clearRefsIn(*scope.End, info.Refs);
        clearRefsIn(scope.Releases.begin(), scope.Releases.end(), info.Refs);
      }

      // Even if one reference is not handled we will not do anything about that
      // pool variable.
      if (info.Refs.empty())
        VarsToHandle.push_back(var);
    }

    for (unsigned i = 0, e = VarsToHandle.size(); i != e; ++i) {
      PoolVarInfo &info = PoolVars[VarsToHandle[i]];

      Transaction Trans(Pass.TA);

      clearUnavailableDiags(info.Dcl);
      Pass.TA.removeStmt(info.Dcl);

      // Add "@autoreleasepool { }"
      for (SmallVectorImpl<PoolScope>::iterator
             scpI = info.Scopes.begin(),
             scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
        PoolScope &scope = *scpI;
        clearUnavailableDiags(*scope.Begin);
        clearUnavailableDiags(*scope.End);
        if (scope.IsFollowedBySimpleReturnStmt) {
          // Include the return in the scope.
          Pass.TA.replaceStmt(*scope.Begin, "@autoreleasepool {");
          Pass.TA.removeStmt(*scope.End);
          Stmt::child_iterator retI = scope.End;
          ++retI;
          SourceLocation afterSemi =
              findLocationAfterSemi((*retI)->getEndLoc(), Pass.Ctx);
          assert(afterSemi.isValid() &&
                 "Didn't we check before setting IsFollowedBySimpleReturnStmt "
                 "to true?");
          Pass.TA.insertAfterToken(afterSemi, "\n}");
          Pass.TA.increaseIndentation(
              SourceRange(scope.getIndentedRange().getBegin(),
                          (*retI)->getEndLoc()),
              scope.CompoundParent->getBeginLoc());
        } else {
          Pass.TA.replaceStmt(*scope.Begin, "@autoreleasepool {");
          Pass.TA.replaceStmt(*scope.End, "}");
          Pass.TA.increaseIndentation(scope.getIndentedRange(),
                                      scope.CompoundParent->getBeginLoc());
        }
      }

      // Remove rest of pool var references.
      for (SmallVectorImpl<PoolScope>::iterator
             scpI = info.Scopes.begin(),
             scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
        PoolScope &scope = *scpI;
        for (SmallVectorImpl<ObjCMessageExpr *>::iterator
               relI = scope.Releases.begin(),
               relE = scope.Releases.end(); relI != relE; ++relI) {
          clearUnavailableDiags(*relI);
          Pass.TA.removeStmt(*relI);
        }
      }
    }
  }

  bool VisitCompoundStmt(CompoundStmt *S) {
    SmallVector<PoolScope, 4> Scopes;

    for (Stmt::child_iterator
           I = S->body_begin(), E = S->body_end(); I != E; ++I) {
      Stmt *child = getEssential(*I);
      if (DeclStmt *DclS = dyn_cast<DeclStmt>(child)) {
        if (DclS->isSingleDecl()) {
          if (VarDecl *VD = dyn_cast<VarDecl>(DclS->getSingleDecl())) {
            if (isNSAutoreleasePool(VD->getType())) {
              PoolVarInfo &info = PoolVars[VD];
              info.Dcl = DclS;
              collectRefs(VD, S, info.Refs);
              // Does this statement follow the pattern:
              // NSAutoreleasePool * pool = [NSAutoreleasePool  new];
              if (isPoolCreation(VD->getInit())) {
                Scopes.push_back(PoolScope());
                Scopes.back().PoolVar = VD;
                Scopes.back().CompoundParent = S;
                Scopes.back().Begin = I;
              }
            }
          }
        }
      } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(child)) {
        if (DeclRefExpr *dref = dyn_cast<DeclRefExpr>(bop->getLHS())) {
          if (VarDecl *VD = dyn_cast<VarDecl>(dref->getDecl())) {
            // Does this statement follow the pattern:
            // pool = [NSAutoreleasePool  new];
            if (isNSAutoreleasePool(VD->getType()) &&
                isPoolCreation(bop->getRHS())) {
              Scopes.push_back(PoolScope());
              Scopes.back().PoolVar = VD;
              Scopes.back().CompoundParent = S;
              Scopes.back().Begin = I;
            }
          }
        }
      }

      if (Scopes.empty())
        continue;

      if (isPoolDrain(Scopes.back().PoolVar, child)) {
        PoolScope &scope = Scopes.back();
        scope.End = I;
        handlePoolScope(scope, S);
        Scopes.pop_back();
      }
    }
    return true;
  }

private:
  void clearUnavailableDiags(Stmt *S) {
    if (S)
      Pass.TA.clearDiagnostic(diag::err_unavailable,
                              diag::err_unavailable_message,
                              S->getSourceRange());
  }

  struct PoolScope {
    VarDecl *PoolVar;
    CompoundStmt *CompoundParent;
    Stmt::child_iterator Begin;
    Stmt::child_iterator End;
    bool IsFollowedBySimpleReturnStmt;
    SmallVector<ObjCMessageExpr *, 4> Releases;

    PoolScope() : PoolVar(nullptr), CompoundParent(nullptr), Begin(), End(),
                  IsFollowedBySimpleReturnStmt(false) { }

    SourceRange getIndentedRange() const {
      Stmt::child_iterator rangeS = Begin;
      ++rangeS;
      if (rangeS == End)
        return SourceRange();
      Stmt::child_iterator rangeE = Begin;
      for (Stmt::child_iterator I = rangeS; I != End; ++I)
        ++rangeE;
      return SourceRange((*rangeS)->getBeginLoc(), (*rangeE)->getEndLoc());
    }
  };

  class NameReferenceChecker : public RecursiveASTVisitor<NameReferenceChecker>{
    ASTContext &Ctx;
    SourceRange ScopeRange;
    SourceLocation &referenceLoc, &declarationLoc;

  public:
    NameReferenceChecker(ASTContext &ctx, PoolScope &scope,
                         SourceLocation &referenceLoc,
                         SourceLocation &declarationLoc)
      : Ctx(ctx), referenceLoc(referenceLoc),
        declarationLoc(declarationLoc) {
      ScopeRange = SourceRange((*scope.Begin)->getBeginLoc(),
                               (*scope.End)->getBeginLoc());
    }

    bool VisitDeclRefExpr(DeclRefExpr *E) {
      return checkRef(E->getLocation(), E->getDecl()->getLocation());
    }

    bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
      return checkRef(TL.getBeginLoc(), TL.getTypedefNameDecl()->getLocation());
    }

    bool VisitTagTypeLoc(TagTypeLoc TL) {
      return checkRef(TL.getBeginLoc(), TL.getDecl()->getLocation());
    }

  private:
    bool checkRef(SourceLocation refLoc, SourceLocation declLoc) {
      if (isInScope(declLoc)) {
        referenceLoc = refLoc;
        declarationLoc = declLoc;
        return false;
      }
      return true;
    }

    bool isInScope(SourceLocation loc) {
      if (loc.isInvalid())
        return false;

      SourceManager &SM = Ctx.getSourceManager();
      if (SM.isBeforeInTranslationUnit(loc, ScopeRange.getBegin()))
        return false;
      return SM.isBeforeInTranslationUnit(loc, ScopeRange.getEnd());
    }
  };

  void handlePoolScope(PoolScope &scope, CompoundStmt *compoundS) {
    // Check that all names declared inside the scope are not used
    // outside the scope.
    {
      bool nameUsedOutsideScope = false;
      SourceLocation referenceLoc, declarationLoc;
      Stmt::child_iterator SI = scope.End, SE = compoundS->body_end();
      ++SI;
      // Check if the autoreleasepool scope is followed by a simple return
      // statement, in which case we will include the return in the scope.
      if (SI != SE)
        if (ReturnStmt *retS = dyn_cast<ReturnStmt>(*SI))
          if ((retS->getRetValue() == nullptr ||
               isa<DeclRefExpr>(retS->getRetValue()->IgnoreParenCasts())) &&
              findLocationAfterSemi(retS->getEndLoc(), Pass.Ctx).isValid()) {
            scope.IsFollowedBySimpleReturnStmt = true;
            ++SI; // the return will be included in scope, don't check it.
          }

      for (; SI != SE; ++SI) {
        nameUsedOutsideScope = !NameReferenceChecker(Pass.Ctx, scope,
                                                     referenceLoc,
                                              declarationLoc).TraverseStmt(*SI);
        if (nameUsedOutsideScope)
          break;
      }

      // If not all references were cleared it means some variables/typenames/etc
      // declared inside the pool scope are used outside of it.
      // We won't try to rewrite the pool.
      if (nameUsedOutsideScope) {
        Pass.TA.reportError("a name is referenced outside the "
            "NSAutoreleasePool scope that it was declared in", referenceLoc);
        Pass.TA.reportNote("name declared here", declarationLoc);
        Pass.TA.reportNote("intended @autoreleasepool scope begins here",
                           (*scope.Begin)->getBeginLoc());
        Pass.TA.reportNote("intended @autoreleasepool scope ends here",
                           (*scope.End)->getBeginLoc());
        return;
      }
    }

    // Collect all releases of the pool; they will be removed.
    {
      ReleaseCollector releaseColl(scope.PoolVar, scope.Releases);
      Stmt::child_iterator I = scope.Begin;
      ++I;
      for (; I != scope.End; ++I)
        releaseColl.TraverseStmt(*I);
    }

    PoolVars[scope.PoolVar].Scopes.push_back(scope);
  }

  bool isPoolCreation(Expr *E) {
    if (!E) return false;
    E = getEssential(E);
    ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
    if (!ME) return false;
    if (ME->getMethodFamily() == OMF_new &&
        ME->getReceiverKind() == ObjCMessageExpr::Class &&
        isNSAutoreleasePool(ME->getReceiverInterface()))
      return true;
    if (ME->getReceiverKind() == ObjCMessageExpr::Instance &&
        ME->getMethodFamily() == OMF_init) {
      Expr *rec = getEssential(ME->getInstanceReceiver());
      if (ObjCMessageExpr *recME = dyn_cast_or_null<ObjCMessageExpr>(rec)) {
        if (recME->getMethodFamily() == OMF_alloc &&
            recME->getReceiverKind() == ObjCMessageExpr::Class &&
            isNSAutoreleasePool(recME->getReceiverInterface()))
          return true;
      }
    }

    return false;
  }

  bool isPoolDrain(VarDecl *poolVar, Stmt *S) {
    if (!S) return false;
    S = getEssential(S);
    ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S);
    if (!ME) return false;
    if (ME->getReceiverKind() == ObjCMessageExpr::Instance) {
      Expr *rec = getEssential(ME->getInstanceReceiver());
      if (DeclRefExpr *dref = dyn_cast<DeclRefExpr>(rec))
        if (dref->getDecl() == poolVar)
          return ME->getMethodFamily() == OMF_release ||
                 ME->getSelector() == DrainSel;
    }

    return false;
  }

  bool isNSAutoreleasePool(ObjCInterfaceDecl *IDecl) {
    return IDecl && IDecl->getIdentifier() == PoolII;
  }

  bool isNSAutoreleasePool(QualType Ty) {
    QualType pointee = Ty->getPointeeType();
    if (pointee.isNull())
      return false;
    if (const ObjCInterfaceType *interT = pointee->getAs<ObjCInterfaceType>())
      return isNSAutoreleasePool(interT->getDecl());
    return false;
  }

  static Expr *getEssential(Expr *E) {
    return cast<Expr>(getEssential((Stmt*)E));
  }
  static Stmt *getEssential(Stmt *S) {
    if (FullExpr *FE = dyn_cast<FullExpr>(S))
      S = FE->getSubExpr();
    if (Expr *E = dyn_cast<Expr>(S))
      S = E->IgnoreParenCasts();
    return S;
  }

  Stmt *Body;
  MigrationPass &Pass;

  IdentifierInfo *PoolII;
  Selector DrainSel;

  struct PoolVarInfo {
    DeclStmt *Dcl;
    ExprSet Refs;
    SmallVector<PoolScope, 2> Scopes;

    PoolVarInfo() : Dcl(nullptr) { }
  };

  std::map<VarDecl *, PoolVarInfo> PoolVars;
};

} // anonymous namespace

void trans::rewriteAutoreleasePool(MigrationPass &pass) {
  BodyTransform<AutoreleasePoolRewriter> trans(pass);
  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
}
