//===--- TransProperties.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.
//
//===----------------------------------------------------------------------===//
//
// rewriteProperties:
//
// - Adds strong/weak/unsafe_unretained ownership specifier to properties that
//   are missing one.
// - Migrates properties from (retain) to (strong) and (assign) to
//   (unsafe_unretained/weak).
// - If a property is synthesized, adds the ownership specifier in the ivar
//   backing the property.
//
//  @interface Foo : NSObject {
//      NSObject *x;
//  }
//  @property (assign) id x;
//  @end
// ---->
//  @interface Foo : NSObject {
//      NSObject *__weak x;
//  }
//  @property (weak) id x;
//  @end
//
//===----------------------------------------------------------------------===//

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

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

namespace {

class PropertiesRewriter {
  MigrationContext &MigrateCtx;
  MigrationPass &Pass;
  ObjCImplementationDecl *CurImplD;
  
  enum PropActionKind {
    PropAction_None,
    PropAction_RetainReplacedWithStrong,
    PropAction_AssignRemoved,
    PropAction_AssignRewritten,
    PropAction_MaybeAddWeakOrUnsafe
  };

  struct PropData {
    ObjCPropertyDecl *PropD;
    ObjCIvarDecl *IvarD;
    ObjCPropertyImplDecl *ImplD;

    PropData(ObjCPropertyDecl *propD) : PropD(propD), IvarD(0), ImplD(0) { }
  };

  typedef SmallVector<PropData, 2> PropsTy;
  typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
  AtPropDeclsTy AtProps;
  llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;

public:
  explicit PropertiesRewriter(MigrationContext &MigrateCtx)
    : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }

  static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps,
                                AtPropDeclsTy *PrevAtProps = 0) {
    for (ObjCInterfaceDecl::prop_iterator
           propI = D->prop_begin(),
           propE = D->prop_end(); propI != propE; ++propI) {
      if (propI->getAtLoc().isInvalid())
        continue;
      unsigned RawLoc = propI->getAtLoc().getRawEncoding();
      if (PrevAtProps)
        if (PrevAtProps->find(RawLoc) != PrevAtProps->end())
          continue;
      PropsTy &props = AtProps[RawLoc];
      props.push_back(&*propI);
    }
  }

  void doTransform(ObjCImplementationDecl *D) {
    CurImplD = D;
    ObjCInterfaceDecl *iface = D->getClassInterface();
    if (!iface)
      return;

    collectProperties(iface, AtProps);

    typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
        prop_impl_iterator;
    for (prop_impl_iterator
           I = prop_impl_iterator(D->decls_begin()),
           E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
      ObjCPropertyImplDecl *implD = &*I;
      if (implD->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
        continue;
      ObjCPropertyDecl *propD = implD->getPropertyDecl();
      if (!propD || propD->isInvalidDecl())
        continue;
      ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl();
      if (!ivarD || ivarD->isInvalidDecl())
        continue;
      unsigned rawAtLoc = propD->getAtLoc().getRawEncoding();
      AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
      if (findAtLoc == AtProps.end())
        continue;
      
      PropsTy &props = findAtLoc->second;
      for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
        if (I->PropD == propD) {
          I->IvarD = ivarD;
          I->ImplD = implD;
          break;
        }
      }
    }

    for (AtPropDeclsTy::iterator
           I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
      PropsTy &props = I->second;
      if (!getPropertyType(props)->isObjCRetainableType())
        continue;
      if (hasIvarWithExplicitARCOwnership(props))
        continue;
      
      Transaction Trans(Pass.TA);
      rewriteProperty(props, atLoc);
    }

    AtPropDeclsTy AtExtProps;
    // Look through extensions.
    for (ObjCCategoryDecl *Cat = iface->getCategoryList();
           Cat; Cat = Cat->getNextClassCategory())
      if (Cat->IsClassExtension())
        collectProperties(Cat, AtExtProps, &AtProps);

    for (AtPropDeclsTy::iterator
           I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {
      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
      PropsTy &props = I->second;
      Transaction Trans(Pass.TA);
      doActionForExtensionProp(props, atLoc);
    }
  }

private:
  void doPropAction(PropActionKind kind,
                    PropsTy &props, SourceLocation atLoc,
                    bool markAction = true) {
    if (markAction)
      for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
        ActionOnProp[I->PropD->getIdentifier()] = kind;

    switch (kind) {
    case PropAction_None:
      return;
    case PropAction_RetainReplacedWithStrong: {
      StringRef toAttr = "strong";
      MigrateCtx.rewritePropertyAttribute("retain", toAttr, atLoc);
      return;
    }
    case PropAction_AssignRemoved:
      return removeAssignForDefaultStrong(props, atLoc);
    case PropAction_AssignRewritten:
      return rewriteAssign(props, atLoc);
    case PropAction_MaybeAddWeakOrUnsafe:
      return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
    }
  }

  void doActionForExtensionProp(PropsTy &props, SourceLocation atLoc) {
    llvm::DenseMap<IdentifierInfo *, PropActionKind>::iterator I;
    I = ActionOnProp.find(props[0].PropD->getIdentifier());
    if (I == ActionOnProp.end())
      return;

    doPropAction(I->second, props, atLoc, false);
  }

  void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
    ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
    
    if (propAttrs & (ObjCPropertyDecl::OBJC_PR_copy |
                     ObjCPropertyDecl::OBJC_PR_unsafe_unretained |
                     ObjCPropertyDecl::OBJC_PR_strong |
                     ObjCPropertyDecl::OBJC_PR_weak))
      return;

    if (propAttrs & ObjCPropertyDecl::OBJC_PR_retain) {
      // strong is the default.
      return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
    }

    bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);

    if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
      if (HasIvarAssignedAPlusOneObject)
        return doPropAction(PropAction_AssignRemoved, props, atLoc);
      return doPropAction(PropAction_AssignRewritten, props, atLoc);
    }

    if (HasIvarAssignedAPlusOneObject ||
        (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
      return; // 'strong' by default.

    return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
  }

  void removeAssignForDefaultStrong(PropsTy &props,
                                    SourceLocation atLoc) const {
    removeAttribute("retain", atLoc);
    if (!removeAttribute("assign", atLoc))
      return;

    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
      if (I->ImplD)
        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
                                I->ImplD->getLocation());
    }
  }

  void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
                                  /*AllowOnUnknownClass=*/Pass.isGCMigration());
    const char *toWhich = 
      (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "strong" :
      (canUseWeak ? "weak" : "unsafe_unretained");

    bool rewroteAttr = rewriteAttribute("assign", toWhich, atLoc);
    if (!rewroteAttr)
      canUseWeak = false;

    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
      if (isUserDeclared(I->IvarD)) {
        if (I->IvarD &&
            I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak) {
          const char *toWhich = 
            (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "__strong " :
              (canUseWeak ? "__weak " : "__unsafe_unretained ");
          Pass.TA.insert(I->IvarD->getLocation(), toWhich);
        }
      }
      if (I->ImplD)
        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
                                I->ImplD->getLocation());
    }
  }

  void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
                                          SourceLocation atLoc) const {
    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
                                  /*AllowOnUnknownClass=*/Pass.isGCMigration());

    bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
                                  atLoc);
    if (!addedAttr)
      canUseWeak = false;

    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
      if (isUserDeclared(I->IvarD)) {
        if (I->IvarD &&
            I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak)
          Pass.TA.insert(I->IvarD->getLocation(),
                         canUseWeak ? "__weak " : "__unsafe_unretained ");
      }
      if (I->ImplD) {
        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
                                I->ImplD->getLocation());
        Pass.TA.clearDiagnostic(
                           diag::err_arc_objc_property_default_assign_on_object,
                           I->ImplD->getLocation());
      }
    }
  }

  bool removeAttribute(StringRef fromAttr, SourceLocation atLoc) const {
    return MigrateCtx.removePropertyAttribute(fromAttr, atLoc);
  }

  bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
                        SourceLocation atLoc) const {
    return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
  }

  bool addAttribute(StringRef attr, SourceLocation atLoc) const {
    return MigrateCtx.addPropertyAttribute(attr, atLoc);
  }

  class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
    ObjCIvarDecl *Ivar;
  public:
    PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {}

    bool VisitBinAssign(BinaryOperator *E) {
      Expr *lhs = E->getLHS()->IgnoreParenImpCasts();
      if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) {
        if (RE->getDecl() != Ivar)
          return true;

      if (ObjCMessageExpr *
            ME = dyn_cast<ObjCMessageExpr>(E->getRHS()->IgnoreParenCasts()))
        if (ME->getMethodFamily() == OMF_retain)
          return false;

      ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E->getRHS());
      while (implCE && implCE->getCastKind() ==  CK_BitCast)
        implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr());

      if (implCE && implCE->getCastKind() == CK_ARCConsumeObject)
        return false;
      }

      return true;
    }
  };

  bool hasIvarAssignedAPlusOneObject(PropsTy &props) const {
    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
      PlusOneAssign oneAssign(I->IvarD);
      bool notFound = oneAssign.TraverseDecl(CurImplD);
      if (!notFound)
        return true;
    }

    return false;
  }

  bool hasIvarWithExplicitARCOwnership(PropsTy &props) const {
    if (Pass.isGCMigration())
      return false;

    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
      if (isUserDeclared(I->IvarD)) {
        if (isa<AttributedType>(I->IvarD->getType()))
          return true;
        if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
              != Qualifiers::OCL_Strong)
          return true;
      }
    }

    return false;    
  }

  bool hasAllIvarsBacked(PropsTy &props) const {
    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
      if (!isUserDeclared(I->IvarD))
        return false;

    return true;
  }

  // \brief Returns true if all declarations in the @property have GC __weak.
  bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
    if (!Pass.isGCMigration())
      return false;
    if (props.empty())
      return false;
    return MigrateCtx.AtPropsWeak.count(atLoc.getRawEncoding());
  }

  bool isUserDeclared(ObjCIvarDecl *ivarD) const {
    return ivarD && !ivarD->getSynthesize();
  }

  QualType getPropertyType(PropsTy &props) const {
    assert(!props.empty());
    QualType ty = props[0].PropD->getType().getUnqualifiedType();

#ifndef NDEBUG
    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
      assert(ty == I->PropD->getType().getUnqualifiedType());
#endif

    return ty;
  }

  ObjCPropertyDecl::PropertyAttributeKind
  getPropertyAttrs(PropsTy &props) const {
    assert(!props.empty());
    ObjCPropertyDecl::PropertyAttributeKind
      attrs = props[0].PropD->getPropertyAttributesAsWritten();

#ifndef NDEBUG
    for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
      assert(attrs == I->PropD->getPropertyAttributesAsWritten());
#endif

    return attrs;
  }
};

} // anonymous namespace

void PropertyRewriteTraverser::traverseObjCImplementation(
                                           ObjCImplementationContext &ImplCtx) {
  PropertiesRewriter(ImplCtx.getMigrationContext())
                                  .doTransform(ImplCtx.getImplementationDecl());
}
