//===--- TransEmptyStatements.cpp - Transformations to ARC mode -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// removeEmptyStatementsAndDealloc:
//
// Removes empty statements that are leftovers from previous transformations.
// e.g for
//
//  [x retain];
//
// removeRetainReleaseDealloc will leave an empty ";" that removeEmptyStatements
// will remove.
//
//===----------------------------------------------------------------------===//

#include "Transforms.h"
#include "Internals.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/SourceManager.h"

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

static bool isEmptyARCMTMacroStatement(NullStmt *S,
                                       std::vector<SourceLocation> &MacroLocs,
                                       ASTContext &Ctx) {
  if (!S->hasLeadingEmptyMacro())
    return false;

  SourceLocation SemiLoc = S->getSemiLoc();
  if (SemiLoc.isInvalid() || SemiLoc.isMacroID())
    return false;

  if (MacroLocs.empty())
    return false;

  SourceManager &SM = Ctx.getSourceManager();
  std::vector<SourceLocation>::iterator
    I = std::upper_bound(MacroLocs.begin(), MacroLocs.end(), SemiLoc,
                         BeforeThanCompare<SourceLocation>(SM));
  --I;
  SourceLocation
      AfterMacroLoc = I->getLocWithOffset(getARCMTMacroName().size());
  assert(AfterMacroLoc.isFileID());

  if (AfterMacroLoc == SemiLoc)
    return true;

  int RelOffs = 0;
  if (!SM.isInSameSLocAddrSpace(AfterMacroLoc, SemiLoc, &RelOffs))
    return false;
  if (RelOffs < 0)
    return false;

  // We make the reasonable assumption that a semicolon after 100 characters
  // means that it is not the next token after our macro. If this assumption
  // fails it is not critical, we will just fail to clear out, e.g., an empty
  // 'if'.
  if (RelOffs - getARCMTMacroName().size() > 100)
    return false;

  SourceLocation AfterMacroSemiLoc = findSemiAfterLocation(AfterMacroLoc, Ctx);
  return AfterMacroSemiLoc == SemiLoc;
}

namespace {

/// \brief Returns true if the statement became empty due to previous
/// transformations.
class EmptyChecker : public StmtVisitor<EmptyChecker, bool> {
  ASTContext &Ctx;
  std::vector<SourceLocation> &MacroLocs;

public:
  EmptyChecker(ASTContext &ctx, std::vector<SourceLocation> &macroLocs)
    : Ctx(ctx), MacroLocs(macroLocs) { }

  bool VisitNullStmt(NullStmt *S) {
    return isEmptyARCMTMacroStatement(S, MacroLocs, Ctx);
  }
  bool VisitCompoundStmt(CompoundStmt *S) {
    if (S->body_empty())
      return false; // was already empty, not because of transformations.
    for (CompoundStmt::body_iterator
           I = S->body_begin(), E = S->body_end(); I != E; ++I)
      if (!Visit(*I))
        return false;
    return true;
  }
  bool VisitIfStmt(IfStmt *S) {
    if (S->getConditionVariable())
      return false;
    Expr *condE = S->getCond();
    if (!condE)
      return false;
    if (hasSideEffects(condE, Ctx))
      return false;
    if (!S->getThen() || !Visit(S->getThen()))
      return false;
    if (S->getElse() && !Visit(S->getElse()))
      return false;
    return true;
  }
  bool VisitWhileStmt(WhileStmt *S) {
    if (S->getConditionVariable())
      return false;
    Expr *condE = S->getCond();
    if (!condE)
      return false;
    if (hasSideEffects(condE, Ctx))
      return false;
    if (!S->getBody())
      return false;
    return Visit(S->getBody());
  }
  bool VisitDoStmt(DoStmt *S) {
    Expr *condE = S->getCond();
    if (!condE)
      return false;
    if (hasSideEffects(condE, Ctx))
      return false;
    if (!S->getBody())
      return false;
    return Visit(S->getBody());
  }
  bool VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
    Expr *Exp = S->getCollection();
    if (!Exp)
      return false;
    if (hasSideEffects(Exp, Ctx))
      return false;
    if (!S->getBody())
      return false;
    return Visit(S->getBody());
  }
  bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
    if (!S->getSubStmt())
      return false;
    return Visit(S->getSubStmt());
  }
};

class EmptyStatementsRemover :
                            public RecursiveASTVisitor<EmptyStatementsRemover> {
  MigrationPass &Pass;

public:
  EmptyStatementsRemover(MigrationPass &pass) : Pass(pass) { }

  bool TraverseStmtExpr(StmtExpr *E) {
    CompoundStmt *S = E->getSubStmt();
    for (CompoundStmt::body_iterator
           I = S->body_begin(), E = S->body_end(); I != E; ++I) {
      if (I != E - 1)
        check(*I);
      TraverseStmt(*I);
    }
    return true;
  }

  bool VisitCompoundStmt(CompoundStmt *S) {
    for (CompoundStmt::body_iterator
           I = S->body_begin(), E = S->body_end(); I != E; ++I)
      check(*I);
    return true;
  }

  ASTContext &getContext() { return Pass.Ctx; }

private:
  void check(Stmt *S) {
    if (!S) return;
    if (EmptyChecker(Pass.Ctx, Pass.ARCMTMacroLocs).Visit(S)) {
      Transaction Trans(Pass.TA);
      Pass.TA.removeStmt(S);
    }
  }
};

} // anonymous namespace

static bool isBodyEmpty(CompoundStmt *body, ASTContext &Ctx,
                        std::vector<SourceLocation> &MacroLocs) {
  for (CompoundStmt::body_iterator
         I = body->body_begin(), E = body->body_end(); I != E; ++I)
    if (!EmptyChecker(Ctx, MacroLocs).Visit(*I))
      return false;

  return true;
}

static void cleanupDeallocOrFinalize(MigrationPass &pass) {
  ASTContext &Ctx = pass.Ctx;
  TransformActions &TA = pass.TA;
  DeclContext *DC = Ctx.getTranslationUnitDecl();
  Selector FinalizeSel =
      Ctx.Selectors.getNullarySelector(&pass.Ctx.Idents.get("finalize"));

  typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl>
    impl_iterator;
  for (impl_iterator I = impl_iterator(DC->decls_begin()),
                     E = impl_iterator(DC->decls_end()); I != E; ++I) {
    ObjCMethodDecl *DeallocM = 0;
    ObjCMethodDecl *FinalizeM = 0;
    for (ObjCImplementationDecl::instmeth_iterator
           MI = I->instmeth_begin(),
           ME = I->instmeth_end(); MI != ME; ++MI) {
      ObjCMethodDecl *MD = *MI;
      if (!MD->hasBody())
        continue;
  
      if (MD->getMethodFamily() == OMF_dealloc) {
        DeallocM = MD;
      } else if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {
        FinalizeM = MD;
      }
    }

    if (DeallocM) {
      if (isBodyEmpty(DeallocM->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
        Transaction Trans(TA);
        TA.remove(DeallocM->getSourceRange());
      }

      if (FinalizeM) {
        Transaction Trans(TA);
        TA.remove(FinalizeM->getSourceRange());
      }

    } else if (FinalizeM) {
      if (isBodyEmpty(FinalizeM->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
        Transaction Trans(TA);
        TA.remove(FinalizeM->getSourceRange());
      } else {
        Transaction Trans(TA);
        TA.replaceText(FinalizeM->getSelectorStartLoc(), "finalize", "dealloc");
      }
    }
  }
}

void trans::removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass) {
  EmptyStatementsRemover(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());

  cleanupDeallocOrFinalize(pass);

  for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i) {
    Transaction Trans(pass.TA);
    pass.TA.remove(pass.ARCMTMacroLocs[i]);
  }
}
