//===--- TransProperties.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.
//
//===----------------------------------------------------------------------===//
//
// 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/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "clang/Sema/SemaDiagnostic.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(nullptr), ImplD(nullptr) {}
  };

  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 = nullptr) {
    for (auto *Prop : D->instance_properties()) {
      if (Prop->getAtLoc().isInvalid())
        continue;
      unsigned RawLoc = Prop->getAtLoc().getRawEncoding();
      if (PrevAtProps)
        if (PrevAtProps->find(RawLoc) != PrevAtProps->end())
          continue;
      PropsTy &props = AtProps[RawLoc];
      props.push_back(Prop);
    }
  }

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

    collectProperties(iface, AtProps);

    // Look through extensions.
    for (auto *Ext : iface->visible_extensions())
      collectProperties(Ext, 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);
    }
  }

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 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_strong_property_ownership,
                                diag::err_arc_assign_property_ownership,
                                diag::err_arc_inconsistent_property_ownership,
                                I->IvarD->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_strong_property_ownership,
                                diag::err_arc_assign_property_ownership,
                                diag::err_arc_inconsistent_property_ownership,
                                I->IvarD->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_strong_property_ownership,
                                diag::err_arc_assign_property_ownership,
                                diag::err_arc_inconsistent_property_ownership,
                                I->IvarD->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 (isPlusOneAssign(E))
          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;    
  }

  // \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());
}
