//===--- TransAutoreleasePool.cpp - Tranformations to ARC mode ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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/Sema/SemaDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include <map>

using namespace clang;
using namespace arcmt;
using namespace trans;
using llvm::StringRef;

namespace {

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

public:
  ReleaseCollector(Decl *D, llvm::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(Decl *D, MigrationPass &pass)
    : Dcl(D), Body(0), Pass(pass) {
    PoolII = &pass.Ctx.Idents.get("NSAutoreleasePool");
    DrainSel = pass.Ctx.Selectors.getNullarySelector(
                                                 &pass.Ctx.Idents.get("drain"));
  }

  void transformBody(Stmt *body) {
    Body = body;
    TraverseStmt(body);
  }
  
  ~AutoreleasePoolRewriter() {
    llvm::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 (llvm::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 (llvm::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)->getLocEnd(),
                                                           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)->getLocEnd()),
                                      scope.CompoundParent->getLocStart());
        } else {
          Pass.TA.replaceStmt(*scope.Begin, "@autoreleasepool {");
          Pass.TA.replaceStmt(*scope.End, "}");
          Pass.TA.increaseIndentation(scope.getIndentedRange(),
                                      scope.CompoundParent->getLocStart());
        }
      }

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

  bool VisitCompoundStmt(CompoundStmt *S) {
    llvm::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;
    llvm::SmallVector<ObjCMessageExpr *, 4> Releases;

    PoolScope() : PoolVar(0), CompoundParent(0), 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)->getLocStart(), (*rangeE)->getLocEnd());
    }
  };

  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)->getLocStart(),
                               (*scope.End)->getLocStart());
    }

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

    bool VisitBlockDeclRefExpr(BlockDeclRefExpr *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) {
      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() == 0 ||
               isa<DeclRefExpr>(retS->getRetValue()->IgnoreParenCasts())) &&
              findLocationAfterSemi(retS->getLocEnd(), 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)->getLocStart());
        Pass.TA.reportNote("intended @autoreleasepool scope ends here",
                           (*scope.End)->getLocStart());
        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 (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S))
      S = EWC->getSubExpr();
    if (Expr *E = dyn_cast<Expr>(S))
      S = E->IgnoreParenCasts();
    return S;
  }

  Decl *Dcl;
  Stmt *Body;
  MigrationPass &Pass;

  IdentifierInfo *PoolII;
  Selector DrainSel;
  
  struct PoolVarInfo {
    DeclStmt *Dcl;
    ExprSet Refs;
    llvm::SmallVector<PoolScope, 2> Scopes;

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

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

} // anonymous namespace

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