//===- DeclObjC.cpp - ObjC Declaration AST Node Implementation ------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// 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/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <queue>
#include <utility>

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
//===----------------------------------------------------------------------===//

ObjCContainerDecl::ObjCContainerDecl(Kind DK, DeclContext *DC,
                                     IdentifierInfo *Id, SourceLocation nameLoc,
                                     SourceLocation atStartLoc)
    : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK) {
  setAtStartLoc(atStartLoc);
}

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 (auto *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 auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
    if (const ObjCProtocolDecl *Def = Proto->getDefinition())
      if (!Def->isUnconditionallyVisible() && !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) {
    auto *MD = dyn_cast<ObjCMethodDecl>(*Meth);
    if (MD && MD->isInstanceMethod() == isInstance)
      return MD;
  }
  return nullptr;
}

/// 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) {
    auto *MD = dyn_cast<ObjCMethodDecl>(*Meth);
    if (MD && MD->isInstanceMethod() && !MD->isImplicit())
      return true;
  }

  if (const auto *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() &
              ObjCPropertyAttribute::kind_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 auto *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 auto *Proto = dyn_cast<ObjCProtocolDecl>(DC)) {
    if (const ObjCProtocolDecl *Def = Proto->getDefinition())
      if (!Def->isUnconditionallyVisible())
        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 (auto *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());
}

ObjCPropertyDecl *ObjCContainerDecl::getProperty(const IdentifierInfo *Id,
                                                 bool IsInstance) const {
  for (auto *LookupResult : lookup(Id)) {
    if (auto *Prop = dyn_cast<ObjCPropertyDecl>(LookupResult)) {
      if (Prop->isInstanceProperty() == IsInstance) {
        return Prop;
      }
    }
  }
  return nullptr;
}

/// 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 auto *Proto = dyn_cast<ObjCProtocolDecl>(this)) {
    if (const ObjCProtocolDecl *Def = Proto->getDefinition())
      if (!Def->isUnconditionallyVisible())
        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 auto *PID = cast<ObjCProtocolDecl>(this);
      for (const auto *I : PID->protocols())
        if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId,
                                                             QueryKind))
          return P;
      break;
    }
    case Decl::ObjCInterface: {
      const auto *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 auto *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 (const ObjCInterfaceDecl *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().getBeginLoc();

  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;
}

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 (auto *Protocol : Protocols)
          if ((MethodDecl = Protocol->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(
    SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo,
    QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl,
    bool isInstance, bool isVariadic, bool isPropertyAccessor,
    bool isSynthesizedAccessorStub, bool isImplicitlyDeclared, bool isDefined,
    ImplementationControl impControl, bool HasRelatedResultType)
    : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
      DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo),
      DeclEndLoc(endLoc) {

  // Initialized the bits stored in DeclContext.
  ObjCMethodDeclBits.Family =
      static_cast<ObjCMethodFamily>(InvalidObjCMethodFamily);
  setInstanceMethod(isInstance);
  setVariadic(isVariadic);
  setPropertyAccessor(isPropertyAccessor);
  setSynthesizedAccessorStub(isSynthesizedAccessorStub);
  setDefined(isDefined);
  setIsRedeclaration(false);
  setHasRedeclaration(false);
  setDeclImplementation(impControl);
  setObjCDeclQualifier(OBJC_TQ_None);
  setRelatedResultType(HasRelatedResultType);
  setSelLocsKind(SelLoc_StandardNoSpace);
  setOverriding(false);
  setHasSkippedBody(false);

  setImplicit(isImplicitlyDeclared);
}

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

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

bool ObjCMethodDecl::isDirectMethod() const {
  return hasAttr<ObjCDirectAttr>() &&
         !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting;
}

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

bool ObjCMethodDecl::definedInNSObject(const ASTContext &Ctx) const {
  if (const auto *PD = dyn_cast<const ObjCProtocolDecl>(getDeclContext()))
    return PD->getIdentifier() == Ctx.getNSObjectName();
  if (const auto *ID = dyn_cast<const ObjCInterfaceDecl>(getDeclContext()))
    return ID->getIdentifier() == Ctx.getNSObjectName();
  return false;
}

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;
}

bool ObjCMethodDecl::hasParamDestroyedInCallee() const {
  for (auto param : parameters()) {
    if (param->isDestroyedInCallee())
      return true;
  }
  return false;
}

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

void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) {
  assert(PrevMethod);
  getASTContext().setObjCMethodRedeclaration(PrevMethod, this);
  setIsRedeclaration(true);
  PrevMethod->setHasRedeclaration(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);

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

  setParamsAndSelLocs(C, Params, SelLocs);
}

/// 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;

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

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

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

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

    } else if (auto *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(),
                                                    /*AllowHidden=*/true);
  }

  return Redecl ? Redecl : this;
}

ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
  auto *CtxD = cast<Decl>(getDeclContext());
  const auto &Sel = getSelector();

  if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
    if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) {
      // When the container is the ObjCImplementationDecl (the primary
      // @implementation), then the canonical Decl is either in
      // the class Interface, or in any of its extension.
      //
      // So when we don't find it in the ObjCInterfaceDecl,
      // sift through extensions too.
      if (ObjCMethodDecl *MD = IFD->getMethod(Sel, isInstanceMethod()))
        return MD;
      for (auto *Ext : IFD->known_extensions())
        if (ObjCMethodDecl *MD = Ext->getMethod(Sel, isInstanceMethod()))
          return MD;
    }
  } else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
    if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
      if (ObjCMethodDecl *MD = CatD->getMethod(Sel, isInstanceMethod()))
        return MD;
  }

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

  return this;
}

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

ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
  auto family = static_cast<ObjCMethodFamily>(ObjCMethodDeclBits.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;
    }
    ObjCMethodDeclBits.Family = 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.
  ObjCMethodDeclBits.Family = family;
  return family;
}

QualType ObjCMethodDecl::getSelfType(ASTContext &Context,
                                     const ObjCInterfaceDecl *OID,
                                     bool &selfIsPseudoStrong,
                                     bool &selfIsConsumed) const {
  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);
  auto *Self = ImplicitParamDecl::Create(Context, this, SourceLocation(),
                                         &Context.Idents.get("self"), selfTy,
                                         ImplicitParamDecl::ObjCSelf);
  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(), ImplicitParamDecl::ObjCCmd));
}

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

ObjCCategoryDecl *ObjCMethodDecl::getCategory() {
  if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
    return CD;
  if (auto *IMD = dyn_cast<ObjCCategoryImplDecl>(getDeclContext()))
    return IMD->getCategoryDecl();
  return nullptr;
}

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 overridden methods from protocols. A method from
  // category is not "overridden" since it is considered as the "same" method
  // (same USR) as the one from the interface.
  if (const auto *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 auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)){
    for (const auto *P : Protocol->protocols())
      CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper);
  }

  if (const auto *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 auto *ProtD =
          dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) {
    CollectOverriddenMethods(ProtD, Method, overridden);

  } else if (const auto *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 auto *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(),
                             /*AllowHidden=*/true);
  }

  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 auto *Container = cast<ObjCContainerDecl>(getParent());
    // For accessor stubs, go back to the interface.
    if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container))
      if (isSynthesizedAccessorStub())
        Container = ImplDecl->getClassInterface();

    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 = cast<ObjCInterfaceDecl>(Container);
    }
    assert(ClassDecl && "Failed to find main class");

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

    assert(isSynthesizedAccessorStub() && "expected an accessor stub");

    for (const auto *Cat : ClassDecl->known_categories()) {
      if (Cat == Container)
        continue;
      if (const auto *Found = findMatchingProperty(Cat))
        return Found;
    }

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

  if (!CheckOverrides)
    return nullptr;

  using OverridesTy = SmallVector<const ObjCMethodDecl *, 8>;

  OverridesTy Overrides;
  getOverriddenMethods(Overrides);
  for (const auto *Override : Overrides)
    if (const ObjCPropertyDecl *Prop = Override->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) {
  auto *TPDecl =
    new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index,
                                    nameLoc, name, colonLoc, boundInfo);
  QualType TPType = ctx.getObjCTypeParamType(TPDecl, {});
  TPDecl->setTypeForDecl(TPType.getTypePtr());
  return TPDecl;
}

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)
    : Brackets(lAngleLoc, rAngleLoc), NumParams(typeParams.size()) {
  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){
  auto *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) {
  auto *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) {
  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 (const auto *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;
}

} // namespace

/// 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) {
    // Force ivar deserialization upfront, before building IvarList.
    (void)ivar_empty();
    for (const auto *Ext : known_extensions()) {
      (void)Ext->ivar_empty();
    }
    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.
        llvm::stable_sort(layout);
        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.
    auto *ID = dyn_cast<ObjCInterfaceDecl>(DC);
    if (!ID) {
      if (auto *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);
}

ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() {
  auto *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: {
    auto *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) {
  setPreviousDecl(PrevDecl);
  if (PrevDecl)
    Data = PrevDecl->Data;
}

ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
                                           IdentifierInfo *Id,
                                           SourceLocation nameLoc,
                                           SourceLocation atStartLoc,
                                           ObjCProtocolDecl *PrevDecl) {
  auto *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;
}

bool ObjCProtocolDecl::isNonRuntimeProtocol() const {
  return hasAttr<ObjCNonRuntimeProtocolAttr>();
}

void ObjCProtocolDecl::getImpliedProtocols(
    llvm::DenseSet<const ObjCProtocolDecl *> &IPs) const {
  std::queue<const ObjCProtocolDecl *> WorkQueue;
  WorkQueue.push(this);

  while (!WorkQueue.empty()) {
    const auto *PD = WorkQueue.front();
    WorkQueue.pop();
    for (const auto *Parent : PD->protocols()) {
      const auto *Can = Parent->getCanonicalDecl();
      auto Result = IPs.insert(Can);
      if (Result.second)
        WorkQueue.push(Parent);
    }
  }
}

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->isUnconditionallyVisible())
    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, ProtocolPropertySet &PS,
    PropertyDeclOrder &PO) const {
  if (const ObjCProtocolDecl *PDecl = getDefinition()) {
    if (!PS.insert(PDecl).second)
      return;
    for (auto *Prop : PDecl->properties()) {
      if (Prop == Property)
        continue;
      if (Prop->getIdentifier() == Property->getIdentifier()) {
        PO.push_back(Prop);
        return;
      }
    }
    // Scan through protocol's protocols which did not have a matching property.
    for (const auto *PI : PDecl->protocols())
      PI->collectInheritedProtocolProperties(Property, PS, PO);
  }
}

StringRef
ObjCProtocolDecl::getObjCRuntimeNameAsString() const {
  if (const auto *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), 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) {
  auto *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 (auto *ImplD = dyn_cast_or_null<ObjCImplementationDecl>(this)) {
    if (IFace)
      Ctx.setObjCImplementation(IFace, ImplD);

  } else if (auto *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;
    auto **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);
}

bool ObjCPropertyDecl::isDirectProperty() const {
  return (PropertyAttributes & ObjCPropertyAttribute::kind_direct) &&
         !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting;
}

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