//===--- ExprObjC.cpp - (ObjC) Expression AST Node Implementation ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the subclesses of Expr class declared in ExprObjC.h
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ExprObjC.h"

#include "clang/AST/ASTContext.h"

using namespace clang;

ObjCArrayLiteral::ObjCArrayLiteral(ArrayRef<Expr *> Elements, QualType T,
                                   ObjCMethodDecl *Method, SourceRange SR)
    : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
           false, false),
      NumElements(Elements.size()), Range(SR), ArrayWithObjectsMethod(Method) {
  Expr **SaveElements = getElements();
  for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
    if (Elements[I]->isTypeDependent() || Elements[I]->isValueDependent())
      ExprBits.ValueDependent = true;
    if (Elements[I]->isInstantiationDependent())
      ExprBits.InstantiationDependent = true;
    if (Elements[I]->containsUnexpandedParameterPack())
      ExprBits.ContainsUnexpandedParameterPack = true;

    SaveElements[I] = Elements[I];
  }
}

ObjCArrayLiteral *ObjCArrayLiteral::Create(const ASTContext &C,
                                           ArrayRef<Expr *> Elements,
                                           QualType T, ObjCMethodDecl *Method,
                                           SourceRange SR) {
  void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Elements.size()));
  return new (Mem) ObjCArrayLiteral(Elements, T, Method, SR);
}

ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(const ASTContext &C,
                                                unsigned NumElements) {

  void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumElements));
  return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements);
}

ObjCDictionaryLiteral::ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
                                             bool HasPackExpansions, QualType T,
                                             ObjCMethodDecl *method,
                                             SourceRange SR)
    : Expr(ObjCDictionaryLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
           false, false),
      NumElements(VK.size()), HasPackExpansions(HasPackExpansions), Range(SR),
      DictWithObjectsMethod(method) {
  KeyValuePair *KeyValues = getTrailingObjects<KeyValuePair>();
  ExpansionData *Expansions =
      HasPackExpansions ? getTrailingObjects<ExpansionData>() : nullptr;
  for (unsigned I = 0; I < NumElements; I++) {
    if (VK[I].Key->isTypeDependent() || VK[I].Key->isValueDependent() ||
        VK[I].Value->isTypeDependent() || VK[I].Value->isValueDependent())
      ExprBits.ValueDependent = true;
    if (VK[I].Key->isInstantiationDependent() ||
        VK[I].Value->isInstantiationDependent())
      ExprBits.InstantiationDependent = true;
    if (VK[I].EllipsisLoc.isInvalid() &&
        (VK[I].Key->containsUnexpandedParameterPack() ||
         VK[I].Value->containsUnexpandedParameterPack()))
      ExprBits.ContainsUnexpandedParameterPack = true;

    KeyValues[I].Key = VK[I].Key;
    KeyValues[I].Value = VK[I].Value;
    if (Expansions) {
      Expansions[I].EllipsisLoc = VK[I].EllipsisLoc;
      if (VK[I].NumExpansions)
        Expansions[I].NumExpansionsPlusOne = *VK[I].NumExpansions + 1;
      else
        Expansions[I].NumExpansionsPlusOne = 0;
    }
  }
}

ObjCDictionaryLiteral *
ObjCDictionaryLiteral::Create(const ASTContext &C,
                              ArrayRef<ObjCDictionaryElement> VK,
                              bool HasPackExpansions, QualType T,
                              ObjCMethodDecl *method, SourceRange SR) {
  void *Mem = C.Allocate(totalSizeToAlloc<KeyValuePair, ExpansionData>(
      VK.size(), HasPackExpansions ? VK.size() : 0));
  return new (Mem) ObjCDictionaryLiteral(VK, HasPackExpansions, T, method, SR);
}

ObjCDictionaryLiteral *
ObjCDictionaryLiteral::CreateEmpty(const ASTContext &C, unsigned NumElements,
                                   bool HasPackExpansions) {
  void *Mem = C.Allocate(totalSizeToAlloc<KeyValuePair, ExpansionData>(
      NumElements, HasPackExpansions ? NumElements : 0));
  return new (Mem)
      ObjCDictionaryLiteral(EmptyShell(), NumElements, HasPackExpansions);
}

QualType ObjCPropertyRefExpr::getReceiverType(const ASTContext &ctx) const {
  if (isClassReceiver())
    return ctx.getObjCInterfaceType(getClassReceiver());

  if (isSuperReceiver())
    return getSuperReceiverType();

  return getBase()->getType();
}

ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK,
                                 SourceLocation LBracLoc,
                                 SourceLocation SuperLoc, bool IsInstanceSuper,
                                 QualType SuperType, Selector Sel,
                                 ArrayRef<SourceLocation> SelLocs,
                                 SelectorLocationsKind SelLocsK,
                                 ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
                                 SourceLocation RBracLoc, bool isImplicit)
    : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary,
           /*TypeDependent=*/false, /*ValueDependent=*/false,
           /*InstantiationDependent=*/false,
           /*ContainsUnexpandedParameterPack=*/false),
      SelectorOrMethod(
          reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())),
      Kind(IsInstanceSuper ? SuperInstance : SuperClass),
      HasMethod(Method != nullptr), IsDelegateInitCall(false),
      IsImplicit(isImplicit), SuperLoc(SuperLoc), LBracLoc(LBracLoc),
      RBracLoc(RBracLoc) {
  initArgsAndSelLocs(Args, SelLocs, SelLocsK);
  setReceiverPointer(SuperType.getAsOpaquePtr());
}

ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK,
                                 SourceLocation LBracLoc,
                                 TypeSourceInfo *Receiver, Selector Sel,
                                 ArrayRef<SourceLocation> SelLocs,
                                 SelectorLocationsKind SelLocsK,
                                 ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
                                 SourceLocation RBracLoc, bool isImplicit)
    : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(),
           T->isDependentType(), T->isInstantiationDependentType(),
           T->containsUnexpandedParameterPack()),
      SelectorOrMethod(
          reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())),
      Kind(Class), HasMethod(Method != nullptr), IsDelegateInitCall(false),
      IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) {
  initArgsAndSelLocs(Args, SelLocs, SelLocsK);
  setReceiverPointer(Receiver);
}

ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK,
                                 SourceLocation LBracLoc, Expr *Receiver,
                                 Selector Sel, ArrayRef<SourceLocation> SelLocs,
                                 SelectorLocationsKind SelLocsK,
                                 ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
                                 SourceLocation RBracLoc, bool isImplicit)
    : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary,
           Receiver->isTypeDependent(), Receiver->isTypeDependent(),
           Receiver->isInstantiationDependent(),
           Receiver->containsUnexpandedParameterPack()),
      SelectorOrMethod(
          reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())),
      Kind(Instance), HasMethod(Method != nullptr), IsDelegateInitCall(false),
      IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) {
  initArgsAndSelLocs(Args, SelLocs, SelLocsK);
  setReceiverPointer(Receiver);
}

void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args,
                                         ArrayRef<SourceLocation> SelLocs,
                                         SelectorLocationsKind SelLocsK) {
  setNumArgs(Args.size());
  Expr **MyArgs = getArgs();
  for (unsigned I = 0; I != Args.size(); ++I) {
    if (Args[I]->isTypeDependent())
      ExprBits.TypeDependent = true;
    if (Args[I]->isValueDependent())
      ExprBits.ValueDependent = true;
    if (Args[I]->isInstantiationDependent())
      ExprBits.InstantiationDependent = true;
    if (Args[I]->containsUnexpandedParameterPack())
      ExprBits.ContainsUnexpandedParameterPack = true;

    MyArgs[I] = Args[I];
  }

  SelLocsKind = SelLocsK;
  if (!isImplicit()) {
    if (SelLocsK == SelLoc_NonStandard)
      std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
  }
}

ObjCMessageExpr *
ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK,
                        SourceLocation LBracLoc, SourceLocation SuperLoc,
                        bool IsInstanceSuper, QualType SuperType, Selector Sel,
                        ArrayRef<SourceLocation> SelLocs,
                        ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
                        SourceLocation RBracLoc, bool isImplicit) {
  assert((!SelLocs.empty() || isImplicit) &&
         "No selector locs for non-implicit message");
  ObjCMessageExpr *Mem;
  SelectorLocationsKind SelLocsK = SelectorLocationsKind();
  if (isImplicit)
    Mem = alloc(Context, Args.size(), 0);
  else
    Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
  return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper,
                                   SuperType, Sel, SelLocs, SelLocsK, Method,
                                   Args, RBracLoc, isImplicit);
}

ObjCMessageExpr *
ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK,
                        SourceLocation LBracLoc, TypeSourceInfo *Receiver,
                        Selector Sel, ArrayRef<SourceLocation> SelLocs,
                        ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
                        SourceLocation RBracLoc, bool isImplicit) {
  assert((!SelLocs.empty() || isImplicit) &&
         "No selector locs for non-implicit message");
  ObjCMessageExpr *Mem;
  SelectorLocationsKind SelLocsK = SelectorLocationsKind();
  if (isImplicit)
    Mem = alloc(Context, Args.size(), 0);
  else
    Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
  return new (Mem)
      ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLocs, SelLocsK, Method,
                      Args, RBracLoc, isImplicit);
}

ObjCMessageExpr *
ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK,
                        SourceLocation LBracLoc, Expr *Receiver, Selector Sel,
                        ArrayRef<SourceLocation> SelLocs,
                        ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
                        SourceLocation RBracLoc, bool isImplicit) {
  assert((!SelLocs.empty() || isImplicit) &&
         "No selector locs for non-implicit message");
  ObjCMessageExpr *Mem;
  SelectorLocationsKind SelLocsK = SelectorLocationsKind();
  if (isImplicit)
    Mem = alloc(Context, Args.size(), 0);
  else
    Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
  return new (Mem)
      ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLocs, SelLocsK, Method,
                      Args, RBracLoc, isImplicit);
}

ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(const ASTContext &Context,
                                              unsigned NumArgs,
                                              unsigned NumStoredSelLocs) {
  ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs);
  return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs);
}

ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C,
                                        ArrayRef<Expr *> Args,
                                        SourceLocation RBraceLoc,
                                        ArrayRef<SourceLocation> SelLocs,
                                        Selector Sel,
                                        SelectorLocationsKind &SelLocsK) {
  SelLocsK = hasStandardSelectorLocs(Sel, SelLocs, Args, RBraceLoc);
  unsigned NumStoredSelLocs =
      (SelLocsK == SelLoc_NonStandard) ? SelLocs.size() : 0;
  return alloc(C, Args.size(), NumStoredSelLocs);
}

ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, unsigned NumArgs,
                                        unsigned NumStoredSelLocs) {
  return (ObjCMessageExpr *)C.Allocate(
      totalSizeToAlloc<void *, SourceLocation>(NumArgs + 1, NumStoredSelLocs),
      alignof(ObjCMessageExpr));
}

void ObjCMessageExpr::getSelectorLocs(
    SmallVectorImpl<SourceLocation> &SelLocs) const {
  for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i)
    SelLocs.push_back(getSelectorLoc(i));
}

SourceRange ObjCMessageExpr::getReceiverRange() const {
  switch (getReceiverKind()) {
  case Instance:
    return getInstanceReceiver()->getSourceRange();

  case Class:
    return getClassReceiverTypeInfo()->getTypeLoc().getSourceRange();

  case SuperInstance:
  case SuperClass:
    return getSuperLoc();
  }

  llvm_unreachable("Invalid ReceiverKind!");
}

Selector ObjCMessageExpr::getSelector() const {
  if (HasMethod)
    return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod)
        ->getSelector();
  return Selector(SelectorOrMethod);
}

QualType ObjCMessageExpr::getReceiverType() const {
  switch (getReceiverKind()) {
  case Instance:
    return getInstanceReceiver()->getType();
  case Class:
    return getClassReceiver();
  case SuperInstance:
  case SuperClass:
    return getSuperType();
  }

  llvm_unreachable("unexpected receiver kind");
}

ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
  QualType T = getReceiverType();

  if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
    return Ptr->getInterfaceDecl();

  if (const ObjCObjectType *Ty = T->getAs<ObjCObjectType>())
    return Ty->getInterface();

  return nullptr;
}

Stmt::child_range ObjCMessageExpr::children() {
  Stmt **begin;
  if (getReceiverKind() == Instance)
    begin = reinterpret_cast<Stmt **>(getTrailingObjects<void *>());
  else
    begin = reinterpret_cast<Stmt **>(getArgs());
  return child_range(begin,
                     reinterpret_cast<Stmt **>(getArgs() + getNumArgs()));
}

StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
  switch (getBridgeKind()) {
  case OBC_Bridge:
    return "__bridge";
  case OBC_BridgeTransfer:
    return "__bridge_transfer";
  case OBC_BridgeRetained:
    return "__bridge_retained";
  }

  llvm_unreachable("Invalid BridgeKind!");
}
