//===--- DeclObjC.cpp - ObjC Declaration 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 Objective-C related Decl classes.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/DeclObjC.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Stmt.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;

//===----------------------------------------------------------------------===//
// ObjCListBase
//===----------------------------------------------------------------------===//

void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
  List = nullptr;
  if (Elts == 0) return;  // Setting to an empty list is a noop.


  List = new (Ctx) void*[Elts];
  NumElts = Elts;
  memcpy(List, InList, sizeof(void*)*Elts);
}

void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts, 
                           const SourceLocation *Locs, ASTContext &Ctx) {
  if (Elts == 0)
    return;

  Locations = new (Ctx) SourceLocation[Elts];
  memcpy(Locations, Locs, sizeof(SourceLocation) * Elts);
  set(InList, Elts, Ctx);
}

//===----------------------------------------------------------------------===//
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//

void ObjCContainerDecl::anchor() { }

/// getIvarDecl - This method looks up an ivar in this ContextDecl.
///
ObjCIvarDecl *
ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const {
  lookup_result R = lookup(Id);
  for (lookup_iterator Ivar = R.begin(), IvarEnd = R.end();
       Ivar != IvarEnd; ++Ivar) {
    if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar))
      return ivar;
  }
  return nullptr;
}

// Get the local instance/class method declared in this interface.
ObjCMethodDecl *
ObjCContainerDecl::getMethod(Selector Sel, bool isInstance,
                             bool AllowHidden) const {
  // If this context is a hidden protocol definition, don't find any
  // methods there.
  if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
    if (const ObjCProtocolDecl *Def = Proto->getDefinition())
      if (Def->isHidden() && !AllowHidden)
        return nullptr;
  }

  // Since instance & class methods can have the same name, the loop below
  // ensures we get the correct method.
  //
  // @interface Whatever
  // - (int) class_method;
  // + (float) class_method;
  // @end
  //
  lookup_result R = lookup(Sel);
  for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
       Meth != MethEnd; ++Meth) {
    ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
    if (MD && MD->isInstanceMethod() == isInstance)
      return MD;
  }
  return nullptr;
}

/// \brief This routine returns 'true' if a user declared setter method was
/// found in the class, its protocols, its super classes or categories.
/// It also returns 'true' if one of its categories has declared a 'readwrite'
/// property.  This is because, user must provide a setter method for the
/// category's 'readwrite' property.
bool ObjCContainerDecl::HasUserDeclaredSetterMethod(
    const ObjCPropertyDecl *Property) const {
  Selector Sel = Property->getSetterName();
  lookup_result R = lookup(Sel);
  for (lookup_iterator Meth = R.begin(), MethEnd = R.end();
       Meth != MethEnd; ++Meth) {
    ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
    if (MD && MD->isInstanceMethod() && !MD->isImplicit())
      return true;
  }

  if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(this)) {
    // Also look into categories, including class extensions, looking
    // for a user declared instance method.
    for (const auto *Cat : ID->visible_categories()) {
      if (ObjCMethodDecl *MD = Cat->getInstanceMethod(Sel))
        if (!MD->isImplicit())
          return true;
      if (Cat->IsClassExtension())
        continue;
      // Also search through the categories looking for a 'readwrite'
      // declaration of this property. If one found, presumably a setter will
      // be provided (properties declared in categories will not get
      // auto-synthesized).
      for (const auto *P : Cat->properties())
        if (P->getIdentifier() == Property->getIdentifier()) {
          if (P->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite)
            return true;
          break;
        }
    }
    
    // Also look into protocols, for a user declared instance method.
    for (const auto *Proto : ID->all_referenced_protocols())
      if (Proto->HasUserDeclaredSetterMethod(Property))
        return true;

    // And in its super class.
    ObjCInterfaceDecl *OSC = ID->getSuperClass();
    while (OSC) {
      if (OSC->HasUserDeclaredSetterMethod(Property))
        return true;
      OSC = OSC->getSuperClass();
    }
  }
  if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(this))
    for (const auto *PI : PD->protocols())
      if (PI->HasUserDeclaredSetterMethod(Property))
        return true;
  return false;
}

ObjCPropertyDecl *
ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
                                   const IdentifierInfo *propertyID,
                                   ObjCPropertyQueryKind queryKind) {
  // If this context is a hidden protocol definition, don't find any
  // property.
  if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(DC)) {
    if (const ObjCProtocolDecl *Def = Proto->getDefinition())
      if (Def->isHidden())
        return nullptr;
  }

  // If context is class, then lookup property in its visible extensions.
  // This comes before property is looked up in primary class.
  if (auto *IDecl = dyn_cast<ObjCInterfaceDecl>(DC)) {
    for (const auto *Ext : IDecl->visible_extensions())
      if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext,
                                                       propertyID,
                                                       queryKind))
        return PD;
  }

  DeclContext::lookup_result R = DC->lookup(propertyID);
  ObjCPropertyDecl *classProp = nullptr;
  for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
       ++I)
    if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I)) {
      // If queryKind is unknown, we return the instance property if one
      // exists; otherwise we return the class property.
      if ((queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown &&
           !PD->isClassProperty()) ||
          (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_class &&
           PD->isClassProperty()) ||
          (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance &&
           !PD->isClassProperty()))
        return PD;

      if (PD->isClassProperty())
        classProp = PD;
    }

  if (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown)
    // We can't find the instance property, return the class property.
    return classProp;

  return nullptr;
}

IdentifierInfo *
ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const {
  SmallString<128> ivarName;
  {
    llvm::raw_svector_ostream os(ivarName);
    os << '_' << getIdentifier()->getName();
  }
  return &Ctx.Idents.get(ivarName.str());
}

/// FindPropertyDeclaration - Finds declaration of the property given its name
/// in 'PropertyId' and returns it. It returns 0, if not found.
ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
    const IdentifierInfo *PropertyId,
    ObjCPropertyQueryKind QueryKind) const {
  // Don't find properties within hidden protocol definitions.
  if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
    if (const ObjCProtocolDecl *Def = Proto->getDefinition())
      if (Def->isHidden())
        return nullptr;
  }
 
  // Search the extensions of a class first; they override what's in
  // the class itself.
  if (const auto *ClassDecl = dyn_cast<ObjCInterfaceDecl>(this)) {
    for (const auto *Ext : ClassDecl->visible_extensions()) {
      if (auto *P = Ext->FindPropertyDeclaration(PropertyId, QueryKind))
        return P;
    }
  }

  if (ObjCPropertyDecl *PD =
        ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId,
                                           QueryKind))
    return PD;

  switch (getKind()) {
    default:
      break;
    case Decl::ObjCProtocol: {
      const ObjCProtocolDecl *PID = cast<ObjCProtocolDecl>(this);
      for (const auto *I : PID->protocols())
        if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
                                                             QueryKind))
          return P;
      break;
    }
    case Decl::ObjCInterface: {
      const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this);
      // Look through categories (but not extensions; they were handled above).
      for (const auto *Cat : OID->visible_categories()) {
        if (!Cat->IsClassExtension())
          if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(
                                             PropertyId, QueryKind))
            return P;
      }

      // Look through protocols.
      for (const auto *I : OID->all_referenced_protocols())
        if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
                                                             QueryKind))
          return P;

      // Finally, check the super class.
      if (const ObjCInterfaceDecl *superClass = OID->getSuperClass())
        return superClass->FindPropertyDeclaration(PropertyId, QueryKind);
      break;
    }
    case Decl::ObjCCategory: {
      const ObjCCategoryDecl *OCD = cast<ObjCCategoryDecl>(this);
      // Look through protocols.
      if (!OCD->IsClassExtension())
        for (const auto *I : OCD->protocols())
          if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
                                                               QueryKind))
            return P;
      break;
    }
  }
  return nullptr;
}

void ObjCInterfaceDecl::anchor() { }

ObjCTypeParamList *ObjCInterfaceDecl::getTypeParamList() const {
  // If this particular declaration has a type parameter list, return it.
  if (ObjCTypeParamList *written = getTypeParamListAsWritten())
    return written;

  // If there is a definition, return its type parameter list.
  if (const ObjCInterfaceDecl *def = getDefinition())
    return def->getTypeParamListAsWritten();

  // Otherwise, look at previous declarations to determine whether any
  // of them has a type parameter list, skipping over those
  // declarations that do not.
  for (auto decl = getMostRecentDecl(); decl; decl = decl->getPreviousDecl()) {
    if (ObjCTypeParamList *written = decl->getTypeParamListAsWritten())
      return written;
  }

  return nullptr;
}

void ObjCInterfaceDecl::setTypeParamList(ObjCTypeParamList *TPL) {
  TypeParamList = TPL;
  if (!TPL)
    return;
  // Set the declaration context of each of the type parameters.
  for (auto typeParam : *TypeParamList)
    typeParam->setDeclContext(this);
}

ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const {
  // FIXME: Should make sure no callers ever do this.
  if (!hasDefinition())
    return nullptr;
    
  if (data().ExternallyCompleted)
    LoadExternalDefinition();

  if (const ObjCObjectType *superType = getSuperClassType()) {
    if (ObjCInterfaceDecl *superDecl = superType->getInterface()) {
      if (ObjCInterfaceDecl *superDef = superDecl->getDefinition())
        return superDef;

      return superDecl;
    }
  }

  return nullptr;
}

SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const {
  if (TypeSourceInfo *superTInfo = getSuperClassTInfo())
    return superTInfo->getTypeLoc().getLocStart();
  
  return SourceLocation();
}

/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
/// with name 'PropertyId' in the primary class; including those in protocols
/// (direct or indirect) used by the primary class.
///
ObjCPropertyDecl *
ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
                       IdentifierInfo *PropertyId,
                       ObjCPropertyQueryKind QueryKind) const {
  // FIXME: Should make sure no callers ever do this.
  if (!hasDefinition())
    return nullptr;

  if (data().ExternallyCompleted)
    LoadExternalDefinition();

  if (ObjCPropertyDecl *PD =
      ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId,
                                         QueryKind))
    return PD;

  // Look through protocols.
  for (const auto *I : all_referenced_protocols())
    if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
                                                         QueryKind))
      return P;

  return nullptr;
}

void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM,
                                                     PropertyDeclOrder &PO) const {
  for (auto *Prop : properties()) {
    PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
    PO.push_back(Prop);
  }
  for (const auto *Ext : known_extensions()) {
    const ObjCCategoryDecl *ClassExt = Ext;
    for (auto *Prop : ClassExt->properties()) {
      PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
      PO.push_back(Prop);
    }
  }
  for (const auto *PI : all_referenced_protocols())
    PI->collectPropertiesToImplement(PM, PO);
  // Note, the properties declared only in class extensions are still copied
  // into the main @interface's property list, and therefore we don't
  // explicitly, have to search class extension properties.
}

bool ObjCInterfaceDecl::isArcWeakrefUnavailable() const {
  const ObjCInterfaceDecl *Class = this;
  while (Class) {
    if (Class->hasAttr<ArcWeakrefUnavailableAttr>())
      return true;
    Class = Class->getSuperClass();
  }
  return false;
}

const ObjCInterfaceDecl *ObjCInterfaceDecl::isObjCRequiresPropertyDefs() const {
  const ObjCInterfaceDecl *Class = this;
  while (Class) {
    if (Class->hasAttr<ObjCRequiresPropertyDefsAttr>())
      return Class;
    Class = Class->getSuperClass();
  }
  return nullptr;
}

void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
                              ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
                              ASTContext &C)
{
  if (data().ExternallyCompleted)
    LoadExternalDefinition();

  if (data().AllReferencedProtocols.empty() && 
      data().ReferencedProtocols.empty()) {
    data().AllReferencedProtocols.set(ExtList, ExtNum, C);
    return;
  }
  
  // Check for duplicate protocol in class's protocol list.
  // This is O(n*m). But it is extremely rare and number of protocols in
  // class or its extension are very few.
  SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
  for (unsigned i = 0; i < ExtNum; i++) {
    bool protocolExists = false;
    ObjCProtocolDecl *ProtoInExtension = ExtList[i];
    for (auto *Proto : all_referenced_protocols()) {
      if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) {
        protocolExists = true;
        break;
      }      
    }
    // Do we want to warn on a protocol in extension class which
    // already exist in the class? Probably not.
    if (!protocolExists)
      ProtocolRefs.push_back(ProtoInExtension);
  }

  if (ProtocolRefs.empty())
    return;

  // Merge ProtocolRefs into class's protocol list;
  ProtocolRefs.append(all_referenced_protocol_begin(),
                      all_referenced_protocol_end());

  data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C);
}

const ObjCInterfaceDecl *
ObjCInterfaceDecl::findInterfaceWithDesignatedInitializers() const {
  const ObjCInterfaceDecl *IFace = this;
  while (IFace) {
    if (IFace->hasDesignatedInitializers())
      return IFace;
    if (!IFace->inheritsDesignatedInitializers())
      break;
    IFace = IFace->getSuperClass();
  }
  return nullptr;
}

static bool isIntroducingInitializers(const ObjCInterfaceDecl *D) {
  for (const auto *MD : D->instance_methods()) {
    if (MD->getMethodFamily() == OMF_init && !MD->isOverriding())
      return true;
  }
  for (const auto *Ext : D->visible_extensions()) {
    for (const auto *MD : Ext->instance_methods()) {
      if (MD->getMethodFamily() == OMF_init && !MD->isOverriding())
        return true;
    }
  }
  if (const auto *ImplD = D->getImplementation()) {
    for (const auto *MD : ImplD->instance_methods()) {
      if (MD->getMethodFamily() == OMF_init && !MD->isOverriding())
        return true;
    }
  }
  return false;
}

bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const {
  switch (data().InheritedDesignatedInitializers) {
  case DefinitionData::IDI_Inherited:
    return true;
  case DefinitionData::IDI_NotInherited:
    return false;
  case DefinitionData::IDI_Unknown: {
    // If the class introduced initializers we conservatively assume that we
    // don't know if any of them is a designated initializer to avoid possible
    // misleading warnings.
    if (isIntroducingInitializers(this)) {
      data().InheritedDesignatedInitializers = DefinitionData::IDI_NotInherited;
    } else {
      if (auto SuperD = getSuperClass()) {
        data().InheritedDesignatedInitializers =
          SuperD->declaresOrInheritsDesignatedInitializers() ?
            DefinitionData::IDI_Inherited :
            DefinitionData::IDI_NotInherited;
      } else {
        data().InheritedDesignatedInitializers =
          DefinitionData::IDI_NotInherited;
      }
    }
    assert(data().InheritedDesignatedInitializers
             != DefinitionData::IDI_Unknown);
    return data().InheritedDesignatedInitializers ==
        DefinitionData::IDI_Inherited;
  }
  }

  llvm_unreachable("unexpected InheritedDesignatedInitializers value");
}

void ObjCInterfaceDecl::getDesignatedInitializers(
    llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const {
  // Check for a complete definition and recover if not so.
  if (!isThisDeclarationADefinition())
    return;
  if (data().ExternallyCompleted)
    LoadExternalDefinition();

  const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers();
  if (!IFace)
    return;

  for (const auto *MD : IFace->instance_methods())
    if (MD->isThisDeclarationADesignatedInitializer())
      Methods.push_back(MD);
  for (const auto *Ext : IFace->visible_extensions()) {
    for (const auto *MD : Ext->instance_methods())
      if (MD->isThisDeclarationADesignatedInitializer())
        Methods.push_back(MD);
  }
}

bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel,
                                      const ObjCMethodDecl **InitMethod) const {
  bool HasCompleteDef = isThisDeclarationADefinition();
  // During deserialization the data record for the ObjCInterfaceDecl could
  // be made invariant by reusing the canonical decl. Take this into account
  // when checking for the complete definition.
  if (!HasCompleteDef && getCanonicalDecl()->hasDefinition() &&
      getCanonicalDecl()->getDefinition() == getDefinition())
    HasCompleteDef = true;

  // Check for a complete definition and recover if not so.
  if (!HasCompleteDef)
    return false;

  if (data().ExternallyCompleted)
    LoadExternalDefinition();

  const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers();
  if (!IFace)
    return false;

  if (const ObjCMethodDecl *MD = IFace->getInstanceMethod(Sel)) {
    if (MD->isThisDeclarationADesignatedInitializer()) {
      if (InitMethod)
        *InitMethod = MD;
      return true;
    }
  }
  for (const auto *Ext : IFace->visible_extensions()) {
    if (const ObjCMethodDecl *MD = Ext->getInstanceMethod(Sel)) {
      if (MD->isThisDeclarationADesignatedInitializer()) {
        if (InitMethod)
          *InitMethod = MD;
        return true;
      }
    }
  }
  return false;
}

void ObjCInterfaceDecl::allocateDefinitionData() {
  assert(!hasDefinition() && "ObjC class already has a definition");
  Data.setPointer(new (getASTContext()) DefinitionData());
  Data.getPointer()->Definition = this;

  // Make the type point at the definition, now that we have one.
  if (TypeForDecl)
    cast<ObjCInterfaceType>(TypeForDecl)->Decl = this;
}

void ObjCInterfaceDecl::startDefinition() {
  allocateDefinitionData();

  // Update all of the declarations with a pointer to the definition.
  for (auto RD : redecls()) {
    if (RD != this)
      RD->Data = Data;
  }
}

ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
                                              ObjCInterfaceDecl *&clsDeclared) {
  // FIXME: Should make sure no callers ever do this.
  if (!hasDefinition())
    return nullptr;

  if (data().ExternallyCompleted)
    LoadExternalDefinition();

  ObjCInterfaceDecl* ClassDecl = this;
  while (ClassDecl != nullptr) {
    if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) {
      clsDeclared = ClassDecl;
      return I;
    }

    for (const auto *Ext : ClassDecl->visible_extensions()) {
      if (ObjCIvarDecl *I = Ext->getIvarDecl(ID)) {
        clsDeclared = ClassDecl;
        return I;
      }
    }
      
    ClassDecl = ClassDecl->getSuperClass();
  }
  return nullptr;
}

/// lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super
/// class whose name is passed as argument. If it is not one of the super classes
/// the it returns NULL.
ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
                                        const IdentifierInfo*ICName) {
  // FIXME: Should make sure no callers ever do this.
  if (!hasDefinition())
    return nullptr;

  if (data().ExternallyCompleted)
    LoadExternalDefinition();

  ObjCInterfaceDecl* ClassDecl = this;
  while (ClassDecl != nullptr) {
    if (ClassDecl->getIdentifier() == ICName)
      return ClassDecl;
    ClassDecl = ClassDecl->getSuperClass();
  }
  return nullptr;
}

ObjCProtocolDecl *
ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) {
  for (auto *P : all_referenced_protocols())
    if (P->lookupProtocolNamed(Name))
      return P;
  ObjCInterfaceDecl *SuperClass = getSuperClass();
  return SuperClass ? SuperClass->lookupNestedProtocol(Name) : nullptr;
}

/// lookupMethod - This method returns an instance/class method by looking in
/// the class, its categories, and its super classes (using a linear search).
/// When argument category "C" is specified, any implicit method found
/// in this category is ignored.
ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, 
                                                bool isInstance,
                                                bool shallowCategoryLookup,
                                                bool followSuper,
                                                const ObjCCategoryDecl *C) const
{
  // FIXME: Should make sure no callers ever do this.
  if (!hasDefinition())
    return nullptr;

  const ObjCInterfaceDecl* ClassDecl = this;
  ObjCMethodDecl *MethodDecl = nullptr;

  if (data().ExternallyCompleted)
    LoadExternalDefinition();

  while (ClassDecl) {
    // 1. Look through primary class.
    if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance)))
      return MethodDecl;
    
    // 2. Didn't find one yet - now look through categories.
    for (const auto *Cat : ClassDecl->visible_categories())
      if ((MethodDecl = Cat->getMethod(Sel, isInstance)))
        if (C != Cat || !MethodDecl->isImplicit())
          return MethodDecl;

    // 3. Didn't find one yet - look through primary class's protocols.
    for (const auto *I : ClassDecl->protocols())
      if ((MethodDecl = I->lookupMethod(Sel, isInstance)))
        return MethodDecl;
    
    // 4. Didn't find one yet - now look through categories' protocols
    if (!shallowCategoryLookup)
      for (const auto *Cat : ClassDecl->visible_categories()) {
        // Didn't find one yet - look through protocols.
        const ObjCList<ObjCProtocolDecl> &Protocols =
          Cat->getReferencedProtocols();
        for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
             E = Protocols.end(); I != E; ++I)
          if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
            if (C != Cat || !MethodDecl->isImplicit())
              return MethodDecl;
      }
    
    
    if (!followSuper)
      return nullptr;

    // 5. Get to the super class (if any).
    ClassDecl = ClassDecl->getSuperClass();
  }
  return nullptr;
}

// Will search "local" class/category implementations for a method decl.
// If failed, then we search in class's root for an instance method.
// Returns 0 if no method is found.
ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
                                   const Selector &Sel,
                                   bool Instance) const {
  // FIXME: Should make sure no callers ever do this.
  if (!hasDefinition())
    return nullptr;

  if (data().ExternallyCompleted)
    LoadExternalDefinition();

  ObjCMethodDecl *Method = nullptr;
  if (ObjCImplementationDecl *ImpDecl = getImplementation())
    Method = Instance ? ImpDecl->getInstanceMethod(Sel) 
                      : ImpDecl->getClassMethod(Sel);

  // Look through local category implementations associated with the class.
  if (!Method)
    Method = getCategoryMethod(Sel, Instance);

  // Before we give up, check if the selector is an instance method.
  // But only in the root. This matches gcc's behavior and what the
  // runtime expects.
  if (!Instance && !Method && !getSuperClass()) {
    Method = lookupInstanceMethod(Sel);
    // Look through local category implementations associated
    // with the root class.
    if (!Method)
      Method = lookupPrivateMethod(Sel, true);
  }

  if (!Method && getSuperClass())
    return getSuperClass()->lookupPrivateMethod(Sel, Instance);
  return Method;
}

//===----------------------------------------------------------------------===//
// ObjCMethodDecl
//===----------------------------------------------------------------------===//

ObjCMethodDecl *ObjCMethodDecl::Create(
    ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
    Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
    DeclContext *contextDecl, bool isInstance, bool isVariadic,
    bool isPropertyAccessor, bool isImplicitlyDeclared, bool isDefined,
    ImplementationControl impControl, bool HasRelatedResultType) {
  return new (C, contextDecl) ObjCMethodDecl(
      beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance,
      isVariadic, isPropertyAccessor, isImplicitlyDeclared, isDefined,
      impControl, HasRelatedResultType);
}

ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(),
                                    Selector(), QualType(), nullptr, nullptr);
}

bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
  return getMethodFamily() == OMF_init &&
      hasAttr<ObjCDesignatedInitializerAttr>();
}

bool ObjCMethodDecl::isDesignatedInitializerForTheInterface(
    const ObjCMethodDecl **InitMethod) const {
  if (getMethodFamily() != OMF_init)
    return false;
  const DeclContext *DC = getDeclContext();
  if (isa<ObjCProtocolDecl>(DC))
    return false;
  if (const ObjCInterfaceDecl *ID = getClassInterface())
    return ID->isDesignatedInitializer(getSelector(), InitMethod);
  return false;
}

Stmt *ObjCMethodDecl::getBody() const {
  return Body.get(getASTContext().getExternalSource());
}

void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) {
  assert(PrevMethod);
  getASTContext().setObjCMethodRedeclaration(PrevMethod, this);
  IsRedeclaration = true;
  PrevMethod->HasRedeclaration = true;
}

void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C,
                                         ArrayRef<ParmVarDecl*> Params,
                                         ArrayRef<SourceLocation> SelLocs) {
  ParamsAndSelLocs = nullptr;
  NumParams = Params.size();
  if (Params.empty() && SelLocs.empty())
    return;

  static_assert(alignof(ParmVarDecl *) >= alignof(SourceLocation),
                "Alignment not sufficient for SourceLocation");

  unsigned Size = sizeof(ParmVarDecl *) * NumParams +
                  sizeof(SourceLocation) * SelLocs.size();
  ParamsAndSelLocs = C.Allocate(Size);
  std::copy(Params.begin(), Params.end(), getParams());
  std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
}

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

void ObjCMethodDecl::setMethodParams(ASTContext &C,
                                     ArrayRef<ParmVarDecl*> Params,
                                     ArrayRef<SourceLocation> SelLocs) {
  assert((!SelLocs.empty() || isImplicit()) &&
         "No selector locs for non-implicit method");
  if (isImplicit())
    return setParamsAndSelLocs(C, Params, llvm::None);

  SelLocsKind = hasStandardSelectorLocs(getSelector(), SelLocs, Params,
                                        DeclEndLoc);
  if (SelLocsKind != SelLoc_NonStandard)
    return setParamsAndSelLocs(C, Params, llvm::None);

  setParamsAndSelLocs(C, Params, SelLocs);
}

/// \brief A definition will return its interface declaration.
/// An interface declaration will return its definition.
/// Otherwise it will return itself.
ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() {
  ASTContext &Ctx = getASTContext();
  ObjCMethodDecl *Redecl = nullptr;
  if (HasRedeclaration)
    Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this));
  if (Redecl)
    return Redecl;

  Decl *CtxD = cast<Decl>(getDeclContext());

  if (!CtxD->isInvalidDecl()) {
    if (ObjCInterfaceDecl *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) {
      if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD))
        if (!ImplD->isInvalidDecl())
          Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());

    } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) {
      if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD))
        if (!ImplD->isInvalidDecl())
          Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());

    } else if (ObjCImplementationDecl *ImplD =
                 dyn_cast<ObjCImplementationDecl>(CtxD)) {
      if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
        if (!IFD->isInvalidDecl())
          Redecl = IFD->getMethod(getSelector(), isInstanceMethod());

    } else if (ObjCCategoryImplDecl *CImplD =
                 dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
      if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
        if (!CatD->isInvalidDecl())
          Redecl = CatD->getMethod(getSelector(), isInstanceMethod());
    }
  }

  // Ensure that the discovered method redeclaration has a valid declaration
  // context. Used to prevent infinite loops when iterating redeclarations in
  // a partially invalid AST.
  if (Redecl && cast<Decl>(Redecl->getDeclContext())->isInvalidDecl())
    Redecl = nullptr;

  if (!Redecl && isRedeclaration()) {
    // This is the last redeclaration, go back to the first method.
    return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
                                                    isInstanceMethod());
  }

  return Redecl ? Redecl : this;
}

ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
  Decl *CtxD = cast<Decl>(getDeclContext());

  if (ObjCImplementationDecl *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
    if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
      if (ObjCMethodDecl *MD = IFD->getMethod(getSelector(),
                                              isInstanceMethod()))
        return MD;

  } else if (ObjCCategoryImplDecl *CImplD =
               dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
    if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
      if (ObjCMethodDecl *MD = CatD->getMethod(getSelector(),
                                               isInstanceMethod()))
        return MD;
  }

  if (isRedeclaration()) {
    // It is possible that we have not done deserializing the ObjCMethod yet.
    ObjCMethodDecl *MD =
        cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
                                                 isInstanceMethod());
    return MD ? MD : this;
  }

  return this;
}

SourceLocation ObjCMethodDecl::getLocEnd() const {
  if (Stmt *Body = getBody())
    return Body->getLocEnd();
  return DeclEndLoc;
}

ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
  ObjCMethodFamily family = static_cast<ObjCMethodFamily>(Family);
  if (family != static_cast<unsigned>(InvalidObjCMethodFamily))
    return family;

  // Check for an explicit attribute.
  if (const ObjCMethodFamilyAttr *attr = getAttr<ObjCMethodFamilyAttr>()) {
    // The unfortunate necessity of mapping between enums here is due
    // to the attributes framework.
    switch (attr->getFamily()) {
    case ObjCMethodFamilyAttr::OMF_None: family = OMF_None; break;
    case ObjCMethodFamilyAttr::OMF_alloc: family = OMF_alloc; break;
    case ObjCMethodFamilyAttr::OMF_copy: family = OMF_copy; break;
    case ObjCMethodFamilyAttr::OMF_init: family = OMF_init; break;
    case ObjCMethodFamilyAttr::OMF_mutableCopy: family = OMF_mutableCopy; break;
    case ObjCMethodFamilyAttr::OMF_new: family = OMF_new; break;
    }
    Family = static_cast<unsigned>(family);
    return family;
  }

  family = getSelector().getMethodFamily();
  switch (family) {
  case OMF_None: break;

  // init only has a conventional meaning for an instance method, and
  // it has to return an object.
  case OMF_init:
    if (!isInstanceMethod() || !getReturnType()->isObjCObjectPointerType())
      family = OMF_None;
    break;

  // alloc/copy/new have a conventional meaning for both class and
  // instance methods, but they require an object return.
  case OMF_alloc:
  case OMF_copy:
  case OMF_mutableCopy:
  case OMF_new:
    if (!getReturnType()->isObjCObjectPointerType())
      family = OMF_None;
    break;

  // These selectors have a conventional meaning only for instance methods.
  case OMF_dealloc:
  case OMF_finalize:
  case OMF_retain:
  case OMF_release:
  case OMF_autorelease:
  case OMF_retainCount:
  case OMF_self:
    if (!isInstanceMethod())
      family = OMF_None;
    break;
      
  case OMF_initialize:
    if (isInstanceMethod() || !getReturnType()->isVoidType())
      family = OMF_None;
    break;
      
  case OMF_performSelector:
    if (!isInstanceMethod() || !getReturnType()->isObjCIdType())
      family = OMF_None;
    else {
      unsigned noParams = param_size();
      if (noParams < 1 || noParams > 3)
        family = OMF_None;
      else {
        ObjCMethodDecl::param_type_iterator it = param_type_begin();
        QualType ArgT = (*it);
        if (!ArgT->isObjCSelType()) {
          family = OMF_None;
          break;
        }
        while (--noParams) {
          it++;
          ArgT = (*it);
          if (!ArgT->isObjCIdType()) {
            family = OMF_None;
            break;
          }
        }
      }
    }
    break;
      
  }

  // Cache the result.
  Family = static_cast<unsigned>(family);
  return family;
}

QualType ObjCMethodDecl::getSelfType(ASTContext &Context,
                                     const ObjCInterfaceDecl *OID,
                                     bool &selfIsPseudoStrong,
                                     bool &selfIsConsumed) {
  QualType selfTy;
  selfIsPseudoStrong = false;
  selfIsConsumed = false;
  if (isInstanceMethod()) {
    // There may be no interface context due to error in declaration
    // of the interface (which has been reported). Recover gracefully.
    if (OID) {
      selfTy = Context.getObjCInterfaceType(OID);
      selfTy = Context.getObjCObjectPointerType(selfTy);
    } else {
      selfTy = Context.getObjCIdType();
    }
  } else // we have a factory method.
    selfTy = Context.getObjCClassType();

  if (Context.getLangOpts().ObjCAutoRefCount) {
    if (isInstanceMethod()) {
      selfIsConsumed = hasAttr<NSConsumesSelfAttr>();

      // 'self' is always __strong.  It's actually pseudo-strong except
      // in init methods (or methods labeled ns_consumes_self), though.
      Qualifiers qs;
      qs.setObjCLifetime(Qualifiers::OCL_Strong);
      selfTy = Context.getQualifiedType(selfTy, qs);

      // In addition, 'self' is const unless this is an init method.
      if (getMethodFamily() != OMF_init && !selfIsConsumed) {
        selfTy = selfTy.withConst();
        selfIsPseudoStrong = true;
      }
    }
    else {
      assert(isClassMethod());
      // 'self' is always const in class methods.
      selfTy = selfTy.withConst();
      selfIsPseudoStrong = true;
    }
  }
  return selfTy;
}

void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
                                          const ObjCInterfaceDecl *OID) {
  bool selfIsPseudoStrong, selfIsConsumed;
  QualType selfTy =
    getSelfType(Context, OID, selfIsPseudoStrong, selfIsConsumed);
  ImplicitParamDecl *self
    = ImplicitParamDecl::Create(Context, this, SourceLocation(),
                                &Context.Idents.get("self"), selfTy);
  setSelfDecl(self);

  if (selfIsConsumed)
    self->addAttr(NSConsumedAttr::CreateImplicit(Context));

  if (selfIsPseudoStrong)
    self->setARCPseudoStrong(true);

  setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(),
                                       &Context.Idents.get("_cmd"),
                                       Context.getObjCSelType()));
}

ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
  if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext()))
    return ID;
  if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
    return CD->getClassInterface();
  if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(getDeclContext()))
    return IMD->getClassInterface();
  if (isa<ObjCProtocolDecl>(getDeclContext()))
    return nullptr;
  llvm_unreachable("unknown method context");
}

SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const {
  const auto *TSI = getReturnTypeSourceInfo();
  if (TSI)
    return TSI->getTypeLoc().getSourceRange();
  return SourceRange();
}

QualType ObjCMethodDecl::getSendResultType() const {
  ASTContext &Ctx = getASTContext();
  return getReturnType().getNonLValueExprType(Ctx)
           .substObjCTypeArgs(Ctx, {}, ObjCSubstitutionContext::Result);
}

QualType ObjCMethodDecl::getSendResultType(QualType receiverType) const {
  // FIXME: Handle related result types here.

  return getReturnType().getNonLValueExprType(getASTContext())
           .substObjCMemberType(receiverType, getDeclContext(),
                                ObjCSubstitutionContext::Result);
}

static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container,
                                            const ObjCMethodDecl *Method,
                               SmallVectorImpl<const ObjCMethodDecl *> &Methods,
                                            bool MovedToSuper) {
  if (!Container)
    return;

  // In categories look for overriden methods from protocols. A method from
  // category is not "overriden" since it is considered as the "same" method
  // (same USR) as the one from the interface.
  if (const ObjCCategoryDecl *
        Category = dyn_cast<ObjCCategoryDecl>(Container)) {
    // Check whether we have a matching method at this category but only if we
    // are at the super class level.
    if (MovedToSuper)
      if (ObjCMethodDecl *
            Overridden = Container->getMethod(Method->getSelector(),
                                              Method->isInstanceMethod(),
                                              /*AllowHidden=*/true))
        if (Method != Overridden) {
          // We found an override at this category; there is no need to look
          // into its protocols.
          Methods.push_back(Overridden);
          return;
        }

    for (const auto *P : Category->protocols())
      CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper);
    return;
  }

  // Check whether we have a matching method at this level.
  if (const ObjCMethodDecl *
        Overridden = Container->getMethod(Method->getSelector(),
                                          Method->isInstanceMethod(),
                                          /*AllowHidden=*/true))
    if (Method != Overridden) {
      // We found an override at this level; there is no need to look
      // into other protocols or categories.
      Methods.push_back(Overridden);
      return;
    }

  if (const ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)){
    for (const auto *P : Protocol->protocols())
      CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper);
  }

  if (const ObjCInterfaceDecl *
        Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
    for (const auto *P : Interface->protocols())
      CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper);

    for (const auto *Cat : Interface->known_categories())
      CollectOverriddenMethodsRecurse(Cat, Method, Methods, MovedToSuper);

    if (const ObjCInterfaceDecl *Super = Interface->getSuperClass())
      return CollectOverriddenMethodsRecurse(Super, Method, Methods,
                                             /*MovedToSuper=*/true);
  }
}

static inline void CollectOverriddenMethods(const ObjCContainerDecl *Container,
                                            const ObjCMethodDecl *Method,
                             SmallVectorImpl<const ObjCMethodDecl *> &Methods) {
  CollectOverriddenMethodsRecurse(Container, Method, Methods,
                                  /*MovedToSuper=*/false);
}

static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method,
                          SmallVectorImpl<const ObjCMethodDecl *> &overridden) {
  assert(Method->isOverriding());

  if (const ObjCProtocolDecl *
        ProtD = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) {
    CollectOverriddenMethods(ProtD, Method, overridden);

  } else if (const ObjCImplDecl *
               IMD = dyn_cast<ObjCImplDecl>(Method->getDeclContext())) {
    const ObjCInterfaceDecl *ID = IMD->getClassInterface();
    if (!ID)
      return;
    // Start searching for overridden methods using the method from the
    // interface as starting point.
    if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(),
                                                    Method->isInstanceMethod(),
                                                    /*AllowHidden=*/true))
      Method = IFaceMeth;
    CollectOverriddenMethods(ID, Method, overridden);

  } else if (const ObjCCategoryDecl *
               CatD = dyn_cast<ObjCCategoryDecl>(Method->getDeclContext())) {
    const ObjCInterfaceDecl *ID = CatD->getClassInterface();
    if (!ID)
      return;
    // Start searching for overridden methods using the method from the
    // interface as starting point.
    if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(),
                                                     Method->isInstanceMethod(),
                                                     /*AllowHidden=*/true))
      Method = IFaceMeth;
    CollectOverriddenMethods(ID, Method, overridden);

  } else {
    CollectOverriddenMethods(
                  dyn_cast_or_null<ObjCContainerDecl>(Method->getDeclContext()),
                  Method, overridden);
  }
}

void ObjCMethodDecl::getOverriddenMethods(
                    SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const {
  const ObjCMethodDecl *Method = this;

  if (Method->isRedeclaration()) {
    Method = cast<ObjCContainerDecl>(Method->getDeclContext())->
                   getMethod(Method->getSelector(), Method->isInstanceMethod());
  }

  if (Method->isOverriding()) {
    collectOverriddenMethodsSlow(Method, Overridden);
    assert(!Overridden.empty() &&
           "ObjCMethodDecl's overriding bit is not as expected");
  }
}

const ObjCPropertyDecl *
ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
  Selector Sel = getSelector();
  unsigned NumArgs = Sel.getNumArgs();
  if (NumArgs > 1)
    return nullptr;

  if (isPropertyAccessor()) {
    const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent());
    bool IsGetter = (NumArgs == 0);
    bool IsInstance = isInstanceMethod();

    /// Local function that attempts to find a matching property within the
    /// given Objective-C container.
    auto findMatchingProperty =
      [&](const ObjCContainerDecl *Container) -> const ObjCPropertyDecl * {
      if (IsInstance) {
        for (const auto *I : Container->instance_properties()) {
          Selector NextSel = IsGetter ? I->getGetterName()
                                      : I->getSetterName();
          if (NextSel == Sel)
            return I;
        }
      } else {
        for (const auto *I : Container->class_properties()) {
          Selector NextSel = IsGetter ? I->getGetterName()
                                      : I->getSetterName();
          if (NextSel == Sel)
            return I;
        }
      }

      return nullptr;
    };

    // Look in the container we were given.
    if (const auto *Found = findMatchingProperty(Container))
      return Found;

    // If we're in a category or extension, look in the main class.
    const ObjCInterfaceDecl *ClassDecl = nullptr;
    if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
      ClassDecl = Category->getClassInterface();
      if (const auto *Found = findMatchingProperty(ClassDecl))
        return Found;
    } else {
      // Determine whether the container is a class.
      ClassDecl = dyn_cast<ObjCInterfaceDecl>(Container);
    }

    // If we have a class, check its visible extensions.
    if (ClassDecl) {
      for (const auto *Ext : ClassDecl->visible_extensions()) {
        if (Ext == Container)
          continue;

        if (const auto *Found = findMatchingProperty(Ext))
          return Found;
      }
    }

    llvm_unreachable("Marked as a property accessor but no property found!");
  }

  if (!CheckOverrides)
    return nullptr;

  typedef SmallVector<const ObjCMethodDecl *, 8> OverridesTy;
  OverridesTy Overrides;
  getOverriddenMethods(Overrides);
  for (OverridesTy::const_iterator I = Overrides.begin(), E = Overrides.end();
       I != E; ++I) {
    if (const ObjCPropertyDecl *Prop = (*I)->findPropertyDecl(false))
      return Prop;
  }

  return nullptr;
}

//===----------------------------------------------------------------------===//
// ObjCTypeParamDecl
//===----------------------------------------------------------------------===//

void ObjCTypeParamDecl::anchor() { }

ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc,
                                             ObjCTypeParamVariance variance,
                                             SourceLocation varianceLoc,
                                             unsigned index,
                                             SourceLocation nameLoc,
                                             IdentifierInfo *name,
                                             SourceLocation colonLoc,
                                             TypeSourceInfo *boundInfo) {
  return new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index,
                                         nameLoc, name, colonLoc, boundInfo);
}

ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx,
                                                         unsigned ID) {
  return new (ctx, ID) ObjCTypeParamDecl(ctx, nullptr,
                                         ObjCTypeParamVariance::Invariant,
                                         SourceLocation(), 0, SourceLocation(),
                                         nullptr, SourceLocation(), nullptr);
}

SourceRange ObjCTypeParamDecl::getSourceRange() const {
  SourceLocation startLoc = VarianceLoc;
  if (startLoc.isInvalid())
    startLoc = getLocation();

  if (hasExplicitBound()) {
    return SourceRange(startLoc,
                       getTypeSourceInfo()->getTypeLoc().getEndLoc());
  }

  return SourceRange(startLoc);
}

//===----------------------------------------------------------------------===//
// ObjCTypeParamList
//===----------------------------------------------------------------------===//
ObjCTypeParamList::ObjCTypeParamList(SourceLocation lAngleLoc,
                                     ArrayRef<ObjCTypeParamDecl *> typeParams,
                                     SourceLocation rAngleLoc)
  : NumParams(typeParams.size())
{
  Brackets.Begin = lAngleLoc.getRawEncoding();
  Brackets.End = rAngleLoc.getRawEncoding();
  std::copy(typeParams.begin(), typeParams.end(), begin());
}


ObjCTypeParamList *ObjCTypeParamList::create(
                     ASTContext &ctx,
                     SourceLocation lAngleLoc,
                     ArrayRef<ObjCTypeParamDecl *> typeParams,
                     SourceLocation rAngleLoc) {
  void *mem =
      ctx.Allocate(totalSizeToAlloc<ObjCTypeParamDecl *>(typeParams.size()),
                   alignof(ObjCTypeParamList));
  return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc);
}

void ObjCTypeParamList::gatherDefaultTypeArgs(
       SmallVectorImpl<QualType> &typeArgs) const {
  typeArgs.reserve(size());
  for (auto typeParam : *this)
    typeArgs.push_back(typeParam->getUnderlyingType());
}

//===----------------------------------------------------------------------===//
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//

ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C,
                                             DeclContext *DC,
                                             SourceLocation atLoc,
                                             IdentifierInfo *Id,
                                             ObjCTypeParamList *typeParamList,
                                             ObjCInterfaceDecl *PrevDecl,
                                             SourceLocation ClassLoc,
                                             bool isInternal){
  ObjCInterfaceDecl *Result = new (C, DC)
      ObjCInterfaceDecl(C, DC, atLoc, Id, typeParamList, ClassLoc, PrevDecl,
                        isInternal);
  Result->Data.setInt(!C.getLangOpts().Modules);
  C.getObjCInterfaceType(Result, PrevDecl);
  return Result;
}

ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C,
                                                         unsigned ID) {
  ObjCInterfaceDecl *Result = new (C, ID) ObjCInterfaceDecl(C, nullptr,
                                                            SourceLocation(),
                                                            nullptr,
                                                            nullptr,
                                                            SourceLocation(),
                                                            nullptr, false);
  Result->Data.setInt(!C.getLangOpts().Modules);
  return Result;
}

ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC,
                                     SourceLocation AtLoc, IdentifierInfo *Id,
                                     ObjCTypeParamList *typeParamList,
                                     SourceLocation CLoc,
                                     ObjCInterfaceDecl *PrevDecl,
                                     bool IsInternal)
    : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc),
      redeclarable_base(C), TypeForDecl(nullptr), TypeParamList(nullptr),
      Data() {
  setPreviousDecl(PrevDecl);
  
  // Copy the 'data' pointer over.
  if (PrevDecl)
    Data = PrevDecl->Data;
  
  setImplicit(IsInternal);

  setTypeParamList(typeParamList);
}

void ObjCInterfaceDecl::LoadExternalDefinition() const {
  assert(data().ExternallyCompleted && "Class is not externally completed");
  data().ExternallyCompleted = false;
  getASTContext().getExternalSource()->CompleteType(
                                        const_cast<ObjCInterfaceDecl *>(this));
}

void ObjCInterfaceDecl::setExternallyCompleted() {
  assert(getASTContext().getExternalSource() && 
         "Class can't be externally completed without an external source");
  assert(hasDefinition() && 
         "Forward declarations can't be externally completed");
  data().ExternallyCompleted = true;
}

void ObjCInterfaceDecl::setHasDesignatedInitializers() {
  // Check for a complete definition and recover if not so.
  if (!isThisDeclarationADefinition())
    return;
  data().HasDesignatedInitializers = true;
}

bool ObjCInterfaceDecl::hasDesignatedInitializers() const {
  // Check for a complete definition and recover if not so.
  if (!isThisDeclarationADefinition())
    return false;
  if (data().ExternallyCompleted)
    LoadExternalDefinition();

  return data().HasDesignatedInitializers;
}

StringRef
ObjCInterfaceDecl::getObjCRuntimeNameAsString() const {
  if (ObjCRuntimeNameAttr *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
    return ObjCRTName->getMetadataName();

  return getName();
}

StringRef
ObjCImplementationDecl::getObjCRuntimeNameAsString() const {
  if (ObjCInterfaceDecl *ID =
      const_cast<ObjCImplementationDecl*>(this)->getClassInterface())
    return ID->getObjCRuntimeNameAsString();
    
  return getName();
}

ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
  if (const ObjCInterfaceDecl *Def = getDefinition()) {
    if (data().ExternallyCompleted)
      LoadExternalDefinition();
    
    return getASTContext().getObjCImplementation(
             const_cast<ObjCInterfaceDecl*>(Def));
  }
  
  // FIXME: Should make sure no callers ever do this.
  return nullptr;
}

void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
  getASTContext().setObjCImplementation(getDefinition(), ImplD);
}

namespace {
  struct SynthesizeIvarChunk {
    uint64_t Size;
    ObjCIvarDecl *Ivar;
    SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar)
      : Size(size), Ivar(ivar) {}
  };

  bool operator<(const SynthesizeIvarChunk & LHS,
                 const SynthesizeIvarChunk &RHS) {
      return LHS.Size < RHS.Size;
  }
}

/// all_declared_ivar_begin - return first ivar declared in this class,
/// its extensions and its implementation. Lazily build the list on first
/// access.
///
/// Caveat: The list returned by this method reflects the current
/// state of the parser. The cache will be updated for every ivar
/// added by an extension or the implementation when they are
/// encountered.
/// See also ObjCIvarDecl::Create().
ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
  // FIXME: Should make sure no callers ever do this.
  if (!hasDefinition())
    return nullptr;

  ObjCIvarDecl *curIvar = nullptr;
  if (!data().IvarList) {
    if (!ivar_empty()) {
      ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end();
      data().IvarList = *I; ++I;
      for (curIvar = data().IvarList; I != E; curIvar = *I, ++I)
        curIvar->setNextIvar(*I);
    }

    for (const auto *Ext : known_extensions()) {
      if (!Ext->ivar_empty()) {
        ObjCCategoryDecl::ivar_iterator
          I = Ext->ivar_begin(),
          E = Ext->ivar_end();
        if (!data().IvarList) {
          data().IvarList = *I; ++I;
          curIvar = data().IvarList;
        }
        for ( ;I != E; curIvar = *I, ++I)
          curIvar->setNextIvar(*I);
      }
    }
    data().IvarListMissingImplementation = true;
  }

  // cached and complete!
  if (!data().IvarListMissingImplementation)
      return data().IvarList;
  
  if (ObjCImplementationDecl *ImplDecl = getImplementation()) {
    data().IvarListMissingImplementation = false;
    if (!ImplDecl->ivar_empty()) {
      SmallVector<SynthesizeIvarChunk, 16> layout;
      for (auto *IV : ImplDecl->ivars()) {
        if (IV->getSynthesize() && !IV->isInvalidDecl()) {
          layout.push_back(SynthesizeIvarChunk(
                             IV->getASTContext().getTypeSize(IV->getType()), IV));
          continue;
        }
        if (!data().IvarList)
          data().IvarList = IV;
        else
          curIvar->setNextIvar(IV);
        curIvar = IV;
      }
      
      if (!layout.empty()) {
        // Order synthesized ivars by their size.
        std::stable_sort(layout.begin(), layout.end());
        unsigned Ix = 0, EIx = layout.size();
        if (!data().IvarList) {
          data().IvarList = layout[0].Ivar; Ix++;
          curIvar = data().IvarList;
        }
        for ( ; Ix != EIx; curIvar = layout[Ix].Ivar, Ix++)
          curIvar->setNextIvar(layout[Ix].Ivar);
      }
    }
  }
  return data().IvarList;
}

/// FindCategoryDeclaration - Finds category declaration in the list of
/// categories for this class and returns it. Name of the category is passed
/// in 'CategoryId'. If category not found, return 0;
///
ObjCCategoryDecl *
ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
  // FIXME: Should make sure no callers ever do this.
  if (!hasDefinition())
    return nullptr;

  if (data().ExternallyCompleted)
    LoadExternalDefinition();

  for (auto *Cat : visible_categories())
    if (Cat->getIdentifier() == CategoryId)
      return Cat;

  return nullptr;
}

ObjCMethodDecl *
ObjCInterfaceDecl::getCategoryInstanceMethod(Selector Sel) const {
  for (const auto *Cat : visible_categories()) {
    if (ObjCCategoryImplDecl *Impl = Cat->getImplementation())
      if (ObjCMethodDecl *MD = Impl->getInstanceMethod(Sel))
        return MD;
  }

  return nullptr;
}

ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const {
  for (const auto *Cat : visible_categories()) {
    if (ObjCCategoryImplDecl *Impl = Cat->getImplementation())
      if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel))
        return MD;
  }

  return nullptr;
}

/// ClassImplementsProtocol - Checks that 'lProto' protocol
/// has been implemented in IDecl class, its super class or categories (if
/// lookupCategory is true).
bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
                                    bool lookupCategory,
                                    bool RHSIsQualifiedID) {
  if (!hasDefinition())
    return false;
  
  ObjCInterfaceDecl *IDecl = this;
  // 1st, look up the class.
  for (auto *PI : IDecl->protocols()){
    if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI))
      return true;
    // This is dubious and is added to be compatible with gcc.  In gcc, it is
    // also allowed assigning a protocol-qualified 'id' type to a LHS object
    // when protocol in qualified LHS is in list of protocols in the rhs 'id'
    // object. This IMO, should be a bug.
    // FIXME: Treat this as an extension, and flag this as an error when GCC
    // extensions are not enabled.
    if (RHSIsQualifiedID &&
        getASTContext().ProtocolCompatibleWithProtocol(PI, lProto))
      return true;
  }

  // 2nd, look up the category.
  if (lookupCategory)
    for (const auto *Cat : visible_categories()) {
      for (auto *PI : Cat->protocols())
        if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI))
          return true;
    }

  // 3rd, look up the super class(s)
  if (IDecl->getSuperClass())
    return
  IDecl->getSuperClass()->ClassImplementsProtocol(lProto, lookupCategory,
                                                  RHSIsQualifiedID);

  return false;
}

//===----------------------------------------------------------------------===//
// ObjCIvarDecl
//===----------------------------------------------------------------------===//

void ObjCIvarDecl::anchor() { }

ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
                                   SourceLocation StartLoc,
                                   SourceLocation IdLoc, IdentifierInfo *Id,
                                   QualType T, TypeSourceInfo *TInfo,
                                   AccessControl ac, Expr *BW,
                                   bool synthesized) {
  if (DC) {
    // Ivar's can only appear in interfaces, implementations (via synthesized
    // properties), and class extensions (via direct declaration, or synthesized
    // properties).
    //
    // FIXME: This should really be asserting this:
    //   (isa<ObjCCategoryDecl>(DC) &&
    //    cast<ObjCCategoryDecl>(DC)->IsClassExtension()))
    // but unfortunately we sometimes place ivars into non-class extension
    // categories on error. This breaks an AST invariant, and should not be
    // fixed.
    assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) ||
            isa<ObjCCategoryDecl>(DC)) &&
           "Invalid ivar decl context!");
    // Once a new ivar is created in any of class/class-extension/implementation
    // decl contexts, the previously built IvarList must be rebuilt.
    ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(DC);
    if (!ID) {
      if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC))
        ID = IM->getClassInterface();
      else
        ID = cast<ObjCCategoryDecl>(DC)->getClassInterface();
    }
    ID->setIvarList(nullptr);
  }

  return new (C, DC) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, ac, BW,
                                  synthesized);
}

ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID) ObjCIvarDecl(nullptr, SourceLocation(), SourceLocation(),
                                  nullptr, QualType(), nullptr,
                                  ObjCIvarDecl::None, nullptr, false);
}

const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
  const ObjCContainerDecl *DC = cast<ObjCContainerDecl>(getDeclContext());

  switch (DC->getKind()) {
  default:
  case ObjCCategoryImpl:
  case ObjCProtocol:
    llvm_unreachable("invalid ivar container!");

    // Ivars can only appear in class extension categories.
  case ObjCCategory: {
    const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC);
    assert(CD->IsClassExtension() && "invalid container for ivar!");
    return CD->getClassInterface();
  }

  case ObjCImplementation:
    return cast<ObjCImplementationDecl>(DC)->getClassInterface();

  case ObjCInterface:
    return cast<ObjCInterfaceDecl>(DC);
  }
}

QualType ObjCIvarDecl::getUsageType(QualType objectType) const {
  return getType().substObjCMemberType(objectType, getDeclContext(),
                                       ObjCSubstitutionContext::Property);
}

//===----------------------------------------------------------------------===//
// ObjCAtDefsFieldDecl
//===----------------------------------------------------------------------===//

void ObjCAtDefsFieldDecl::anchor() { }

ObjCAtDefsFieldDecl
*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC,
                             SourceLocation StartLoc,  SourceLocation IdLoc,
                             IdentifierInfo *Id, QualType T, Expr *BW) {
  return new (C, DC) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW);
}

ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C,
                                                             unsigned ID) {
  return new (C, ID) ObjCAtDefsFieldDecl(nullptr, SourceLocation(),
                                         SourceLocation(), nullptr, QualType(),
                                         nullptr);
}

//===----------------------------------------------------------------------===//
// ObjCProtocolDecl
//===----------------------------------------------------------------------===//

void ObjCProtocolDecl::anchor() { }

ObjCProtocolDecl::ObjCProtocolDecl(ASTContext &C, DeclContext *DC,
                                   IdentifierInfo *Id, SourceLocation nameLoc,
                                   SourceLocation atStartLoc,
                                   ObjCProtocolDecl *PrevDecl)
    : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc),
      redeclarable_base(C), Data() {
  setPreviousDecl(PrevDecl);
  if (PrevDecl)
    Data = PrevDecl->Data;
}

ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
                                           IdentifierInfo *Id,
                                           SourceLocation nameLoc,
                                           SourceLocation atStartLoc,
                                           ObjCProtocolDecl *PrevDecl) {
  ObjCProtocolDecl *Result =
      new (C, DC) ObjCProtocolDecl(C, DC, Id, nameLoc, atStartLoc, PrevDecl);
  Result->Data.setInt(!C.getLangOpts().Modules);
  return Result;
}

ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C,
                                                       unsigned ID) {
  ObjCProtocolDecl *Result =
      new (C, ID) ObjCProtocolDecl(C, nullptr, nullptr, SourceLocation(),
                                   SourceLocation(), nullptr);
  Result->Data.setInt(!C.getLangOpts().Modules);
  return Result;
}

ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
  ObjCProtocolDecl *PDecl = this;

  if (Name == getIdentifier())
    return PDecl;

  for (auto *I : protocols())
    if ((PDecl = I->lookupProtocolNamed(Name)))
      return PDecl;

  return nullptr;
}

// lookupMethod - Lookup a instance/class method in the protocol and protocols
// it inherited.
ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
                                               bool isInstance) const {
  ObjCMethodDecl *MethodDecl = nullptr;

  // If there is no definition or the definition is hidden, we don't find
  // anything.
  const ObjCProtocolDecl *Def = getDefinition();
  if (!Def || Def->isHidden())
    return nullptr;

  if ((MethodDecl = getMethod(Sel, isInstance)))
    return MethodDecl;

  for (const auto *I : protocols())
    if ((MethodDecl = I->lookupMethod(Sel, isInstance)))
      return MethodDecl;
  return nullptr;
}

void ObjCProtocolDecl::allocateDefinitionData() {
  assert(!Data.getPointer() && "Protocol already has a definition!");
  Data.setPointer(new (getASTContext()) DefinitionData);
  Data.getPointer()->Definition = this;
}

void ObjCProtocolDecl::startDefinition() {
  allocateDefinitionData();
  
  // Update all of the declarations with a pointer to the definition.
  for (auto RD : redecls())
    RD->Data = this->Data;
}

void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM,
                                                    PropertyDeclOrder &PO) const {
  
  if (const ObjCProtocolDecl *PDecl = getDefinition()) {
    for (auto *Prop : PDecl->properties()) {
      // Insert into PM if not there already.
      PM.insert(std::make_pair(
          std::make_pair(Prop->getIdentifier(), Prop->isClassProperty()),
          Prop));
      PO.push_back(Prop);
    }
    // Scan through protocol's protocols.
    for (const auto *PI : PDecl->protocols())
      PI->collectPropertiesToImplement(PM, PO);
  }
}

    
void ObjCProtocolDecl::collectInheritedProtocolProperties(
                                                const ObjCPropertyDecl *Property,
                                                ProtocolPropertyMap &PM) const {
  if (const ObjCProtocolDecl *PDecl = getDefinition()) {
    bool MatchFound = false;
    for (auto *Prop : PDecl->properties()) {
      if (Prop == Property)
        continue;
      if (Prop->getIdentifier() == Property->getIdentifier()) {
        PM[PDecl] = Prop;
        MatchFound = true;
        break;
      }
    }
    // Scan through protocol's protocols which did not have a matching property.
    if (!MatchFound)
      for (const auto *PI : PDecl->protocols())
        PI->collectInheritedProtocolProperties(Property, PM);
  }
}

StringRef
ObjCProtocolDecl::getObjCRuntimeNameAsString() const {
  if (ObjCRuntimeNameAttr *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
    return ObjCRTName->getMetadataName();

  return getName();
}

//===----------------------------------------------------------------------===//
// ObjCCategoryDecl
//===----------------------------------------------------------------------===//

void ObjCCategoryDecl::anchor() { }

ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
                                   SourceLocation ClassNameLoc, 
                                   SourceLocation CategoryNameLoc,
                                   IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
                                   ObjCTypeParamList *typeParamList,
                                   SourceLocation IvarLBraceLoc,
                                   SourceLocation IvarRBraceLoc)
  : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
    ClassInterface(IDecl), TypeParamList(nullptr),
    NextClassCategory(nullptr), CategoryNameLoc(CategoryNameLoc),
    IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) 
{
  setTypeParamList(typeParamList);
}

ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
                                           SourceLocation AtLoc,
                                           SourceLocation ClassNameLoc,
                                           SourceLocation CategoryNameLoc,
                                           IdentifierInfo *Id,
                                           ObjCInterfaceDecl *IDecl,
                                           ObjCTypeParamList *typeParamList,
                                           SourceLocation IvarLBraceLoc,
                                           SourceLocation IvarRBraceLoc) {
  ObjCCategoryDecl *CatDecl =
      new (C, DC) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id,
                                   IDecl, typeParamList, IvarLBraceLoc,
                                   IvarRBraceLoc);
  if (IDecl) {
    // Link this category into its class's category list.
    CatDecl->NextClassCategory = IDecl->getCategoryListRaw();
    if (IDecl->hasDefinition()) {
      IDecl->setCategoryListRaw(CatDecl);
      if (ASTMutationListener *L = C.getASTMutationListener())
        L->AddedObjCCategoryToInterface(CatDecl, IDecl);
    }
  }

  return CatDecl;
}

ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C,
                                                       unsigned ID) {
  return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(),
                                      SourceLocation(), SourceLocation(),
                                      nullptr, nullptr, nullptr);
}

ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
  return getASTContext().getObjCImplementation(
                                           const_cast<ObjCCategoryDecl*>(this));
}

void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
  getASTContext().setObjCImplementation(this, ImplD);
}

void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) {
  TypeParamList = TPL;
  if (!TPL)
    return;
  // Set the declaration context of each of the type parameters.
  for (auto typeParam : *TypeParamList)
    typeParam->setDeclContext(this);
}


//===----------------------------------------------------------------------===//
// ObjCCategoryImplDecl
//===----------------------------------------------------------------------===//

void ObjCCategoryImplDecl::anchor() { }

ObjCCategoryImplDecl *
ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
                             IdentifierInfo *Id,
                             ObjCInterfaceDecl *ClassInterface,
                             SourceLocation nameLoc,
                             SourceLocation atStartLoc,
                             SourceLocation CategoryNameLoc) {
  if (ClassInterface && ClassInterface->hasDefinition())
    ClassInterface = ClassInterface->getDefinition();
  return new (C, DC) ObjCCategoryImplDecl(DC, Id, ClassInterface, nameLoc,
                                          atStartLoc, CategoryNameLoc);
}

ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C, 
                                                               unsigned ID) {
  return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr,
                                          SourceLocation(), SourceLocation(),
                                          SourceLocation());
}

ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
  // The class interface might be NULL if we are working with invalid code.
  if (const ObjCInterfaceDecl *ID = getClassInterface())
    return ID->FindCategoryDeclaration(getIdentifier());
  return nullptr;
}


void ObjCImplDecl::anchor() { }

void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) {
  // FIXME: The context should be correct before we get here.
  property->setLexicalDeclContext(this);
  addDecl(property);
}

void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) {
  ASTContext &Ctx = getASTContext();

  if (ObjCImplementationDecl *ImplD
        = dyn_cast_or_null<ObjCImplementationDecl>(this)) {
    if (IFace)
      Ctx.setObjCImplementation(IFace, ImplD);

  } else if (ObjCCategoryImplDecl *ImplD =
             dyn_cast_or_null<ObjCCategoryImplDecl>(this)) {
    if (ObjCCategoryDecl *CD = IFace->FindCategoryDeclaration(getIdentifier()))
      Ctx.setObjCImplementation(CD, ImplD);
  }

  ClassInterface = IFace;
}

/// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
/// properties implemented in this \@implementation block and returns
/// the implemented property that uses it.
///
ObjCPropertyImplDecl *ObjCImplDecl::
FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
  for (auto *PID : property_impls())
    if (PID->getPropertyIvarDecl() &&
        PID->getPropertyIvarDecl()->getIdentifier() == ivarId)
      return PID;
  return nullptr;
}

/// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl
/// added to the list of those properties \@synthesized/\@dynamic in this
/// category \@implementation block.
///
ObjCPropertyImplDecl *ObjCImplDecl::
FindPropertyImplDecl(IdentifierInfo *Id,
                     ObjCPropertyQueryKind QueryKind) const {
  ObjCPropertyImplDecl *ClassPropImpl = nullptr;
  for (auto *PID : property_impls())
    // If queryKind is unknown, we return the instance property if one
    // exists; otherwise we return the class property.
    if (PID->getPropertyDecl()->getIdentifier() == Id) {
      if ((QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown &&
           !PID->getPropertyDecl()->isClassProperty()) ||
          (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_class &&
           PID->getPropertyDecl()->isClassProperty()) ||
          (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance &&
           !PID->getPropertyDecl()->isClassProperty()))
        return PID;

      if (PID->getPropertyDecl()->isClassProperty())
        ClassPropImpl = PID;
    }

  if (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown)
    // We can't find the instance property, return the class property.
    return ClassPropImpl;

  return nullptr;
}

raw_ostream &clang::operator<<(raw_ostream &OS,
                               const ObjCCategoryImplDecl &CID) {
  OS << CID.getName();
  return OS;
}

//===----------------------------------------------------------------------===//
// ObjCImplementationDecl
//===----------------------------------------------------------------------===//

void ObjCImplementationDecl::anchor() { }

ObjCImplementationDecl *
ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC,
                               ObjCInterfaceDecl *ClassInterface,
                               ObjCInterfaceDecl *SuperDecl,
                               SourceLocation nameLoc,
                               SourceLocation atStartLoc,
                               SourceLocation superLoc,
                               SourceLocation IvarLBraceLoc,
                               SourceLocation IvarRBraceLoc) {
  if (ClassInterface && ClassInterface->hasDefinition())
    ClassInterface = ClassInterface->getDefinition();
  return new (C, DC) ObjCImplementationDecl(DC, ClassInterface, SuperDecl,
                                            nameLoc, atStartLoc, superLoc,
                                            IvarLBraceLoc, IvarRBraceLoc);
}

ObjCImplementationDecl *
ObjCImplementationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID) ObjCImplementationDecl(nullptr, nullptr, nullptr,
                                            SourceLocation(), SourceLocation());
}

void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
                                             CXXCtorInitializer ** initializers,
                                                 unsigned numInitializers) {
  if (numInitializers > 0) {
    NumIvarInitializers = numInitializers;
    CXXCtorInitializer **ivarInitializers =
    new (C) CXXCtorInitializer*[NumIvarInitializers];
    memcpy(ivarInitializers, initializers,
           numInitializers * sizeof(CXXCtorInitializer*));
    IvarInitializers = ivarInitializers;
  }
}

ObjCImplementationDecl::init_const_iterator
ObjCImplementationDecl::init_begin() const {
  return IvarInitializers.get(getASTContext().getExternalSource());
}

raw_ostream &clang::operator<<(raw_ostream &OS,
                               const ObjCImplementationDecl &ID) {
  OS << ID.getName();
  return OS;
}

//===----------------------------------------------------------------------===//
// ObjCCompatibleAliasDecl
//===----------------------------------------------------------------------===//

void ObjCCompatibleAliasDecl::anchor() { }

ObjCCompatibleAliasDecl *
ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
                                SourceLocation L,
                                IdentifierInfo *Id,
                                ObjCInterfaceDecl* AliasedClass) {
  return new (C, DC) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass);
}

ObjCCompatibleAliasDecl *
ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID) ObjCCompatibleAliasDecl(nullptr, SourceLocation(),
                                             nullptr, nullptr);
}

//===----------------------------------------------------------------------===//
// ObjCPropertyDecl
//===----------------------------------------------------------------------===//

void ObjCPropertyDecl::anchor() { }

ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
                                           SourceLocation L,
                                           IdentifierInfo *Id,
                                           SourceLocation AtLoc,
                                           SourceLocation LParenLoc,
                                           QualType T,
                                           TypeSourceInfo *TSI,
                                           PropertyControl propControl) {
  return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T, TSI,
                                      propControl);
}

ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C,
                                                       unsigned ID) {
  return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr,
                                      SourceLocation(), SourceLocation(),
                                      QualType(), nullptr, None);
}

QualType ObjCPropertyDecl::getUsageType(QualType objectType) const {
  return DeclType.substObjCMemberType(objectType, getDeclContext(),
                                      ObjCSubstitutionContext::Property);
}

//===----------------------------------------------------------------------===//
// ObjCPropertyImplDecl
//===----------------------------------------------------------------------===//

ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C,
                                                   DeclContext *DC,
                                                   SourceLocation atLoc,
                                                   SourceLocation L,
                                                   ObjCPropertyDecl *property,
                                                   Kind PK,
                                                   ObjCIvarDecl *ivar,
                                                   SourceLocation ivarLoc) {
  return new (C, DC) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar,
                                          ivarLoc);
}

ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C,
                                                               unsigned ID) {
  return new (C, ID) ObjCPropertyImplDecl(nullptr, SourceLocation(),
                                          SourceLocation(), nullptr, Dynamic,
                                          nullptr, SourceLocation());
}

SourceRange ObjCPropertyImplDecl::getSourceRange() const {
  SourceLocation EndLoc = getLocation();
  if (IvarLoc.isValid())
    EndLoc = IvarLoc;

  return SourceRange(AtLoc, EndLoc);
}
