//===- DeclObjC.h - Classes for representing declarations -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the DeclObjC interface and subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_DECLOBJC_H
#define LLVM_CLANG_AST_DECLOBJC_H

#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/SelectorLocationsKind.h"
#include "clang/AST/Type.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <string>
#include <utility>

namespace clang {

class ASTContext;
class CompoundStmt;
class CXXCtorInitializer;
class Expr;
class ObjCCategoryDecl;
class ObjCCategoryImplDecl;
class ObjCImplementationDecl;
class ObjCInterfaceDecl;
class ObjCIvarDecl;
class ObjCPropertyDecl;
class ObjCPropertyImplDecl;
class ObjCProtocolDecl;
class Stmt;

class ObjCListBase {
protected:
  /// List is an array of pointers to objects that are not owned by this object.
  void **List = nullptr;
  unsigned NumElts = 0;

public:
  ObjCListBase() = default;
  ObjCListBase(const ObjCListBase &) = delete;
  ObjCListBase &operator=(const ObjCListBase &) = delete;

  unsigned size() const { return NumElts; }
  bool empty() const { return NumElts == 0; }

protected:
  void set(void *const* InList, unsigned Elts, ASTContext &Ctx);
};

/// ObjCList - This is a simple template class used to hold various lists of
/// decls etc, which is heavily used by the ObjC front-end.  This only use case
/// this supports is setting the list all at once and then reading elements out
/// of it.
template <typename T>
class ObjCList : public ObjCListBase {
public:
  void set(T* const* InList, unsigned Elts, ASTContext &Ctx) {
    ObjCListBase::set(reinterpret_cast<void*const*>(InList), Elts, Ctx);
  }

  using iterator = T* const *;

  iterator begin() const { return (iterator)List; }
  iterator end() const { return (iterator)List+NumElts; }

  T* operator[](unsigned Idx) const {
    assert(Idx < NumElts && "Invalid access");
    return (T*)List[Idx];
  }
};

/// \brief A list of Objective-C protocols, along with the source
/// locations at which they were referenced.
class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> {
  SourceLocation *Locations = nullptr;

  using ObjCList<ObjCProtocolDecl>::set;

public:
  ObjCProtocolList() = default;

  using loc_iterator = const SourceLocation *;

  loc_iterator loc_begin() const { return Locations; }
  loc_iterator loc_end() const { return Locations + size(); }

  void set(ObjCProtocolDecl* const* InList, unsigned Elts,
           const SourceLocation *Locs, ASTContext &Ctx);
};

/// ObjCMethodDecl - Represents an instance or class method declaration.
/// ObjC methods can be declared within 4 contexts: class interfaces,
/// categories, protocols, and class implementations. While C++ member
/// functions leverage C syntax, Objective-C method syntax is modeled after
/// Smalltalk (using colons to specify argument types/expressions).
/// Here are some brief examples:
///
/// Setter/getter instance methods:
/// - (void)setMenu:(NSMenu *)menu;
/// - (NSMenu *)menu;
///
/// Instance method that takes 2 NSView arguments:
/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView;
///
/// Getter class method:
/// + (NSMenu *)defaultMenu;
///
/// A selector represents a unique name for a method. The selector names for
/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
///
class ObjCMethodDecl : public NamedDecl, public DeclContext {
public:
  enum ImplementationControl { None, Required, Optional };

private:
  // The conventional meaning of this method; an ObjCMethodFamily.
  // This is not serialized; instead, it is computed on demand and
  // cached.
  mutable unsigned Family : ObjCMethodFamilyBitWidth;

  /// instance (true) or class (false) method.
  unsigned IsInstance : 1;
  unsigned IsVariadic : 1;

  /// True if this method is the getter or setter for an explicit property.
  unsigned IsPropertyAccessor : 1;

  // Method has a definition.
  unsigned IsDefined : 1;

  /// \brief Method redeclaration in the same interface.
  unsigned IsRedeclaration : 1;

  /// \brief Is redeclared in the same interface.
  mutable unsigned HasRedeclaration : 1;

  // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
  /// \@required/\@optional
  unsigned DeclImplementation : 2;

  // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum
  /// in, inout, etc.
  unsigned objcDeclQualifier : 7;

  /// \brief Indicates whether this method has a related result type.
  unsigned RelatedResultType : 1;

  /// \brief Whether the locations of the selector identifiers are in a
  /// "standard" position, a enum SelectorLocationsKind.
  unsigned SelLocsKind : 2;

  /// \brief Whether this method overrides any other in the class hierarchy.
  ///
  /// A method is said to override any method in the class's
  /// base classes, its protocols, or its categories' protocols, that has
  /// the same selector and is of the same kind (class or instance).
  /// A method in an implementation is not considered as overriding the same
  /// method in the interface or its categories.
  unsigned IsOverriding : 1;

  /// \brief Indicates if the method was a definition but its body was skipped.
  unsigned HasSkippedBody : 1;

  // Return type of this method.
  QualType MethodDeclType;

  // Type source information for the return type.
  TypeSourceInfo *ReturnTInfo;

  /// \brief Array of ParmVarDecls for the formal parameters of this method
  /// and optionally followed by selector locations.
  void *ParamsAndSelLocs = nullptr;
  unsigned NumParams = 0;

  /// List of attributes for this method declaration.
  SourceLocation DeclEndLoc; // the location of the ';' or '{'.

  // The following are only used for method definitions, null otherwise.
  LazyDeclStmtPtr Body;

  /// SelfDecl - Decl for the implicit self parameter. This is lazily
  /// constructed by createImplicitParams.
  ImplicitParamDecl *SelfDecl = nullptr;

  /// CmdDecl - Decl for the implicit _cmd parameter. This is lazily
  /// constructed by createImplicitParams.
  ImplicitParamDecl *CmdDecl = nullptr;

  ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
                 Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
                 DeclContext *contextDecl, bool isInstance = true,
                 bool isVariadic = false, bool isPropertyAccessor = false,
                 bool isImplicitlyDeclared = false, bool isDefined = false,
                 ImplementationControl impControl = None,
                 bool HasRelatedResultType = false)
      : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
        DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily),
        IsInstance(isInstance), IsVariadic(isVariadic),
        IsPropertyAccessor(isPropertyAccessor), IsDefined(isDefined),
        IsRedeclaration(0), HasRedeclaration(0), DeclImplementation(impControl),
        objcDeclQualifier(OBJC_TQ_None),
        RelatedResultType(HasRelatedResultType),
        SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0),
        MethodDeclType(T), ReturnTInfo(ReturnTInfo), DeclEndLoc(endLoc) {
    setImplicit(isImplicitlyDeclared);
  }

  SelectorLocationsKind getSelLocsKind() const {
    return (SelectorLocationsKind)SelLocsKind;
  }

  bool hasStandardSelLocs() const {
    return getSelLocsKind() != SelLoc_NonStandard;
  }

  /// \brief Get a pointer to the stored selector identifiers locations array.
  /// No locations will be stored if HasStandardSelLocs is true.
  SourceLocation *getStoredSelLocs() {
    return reinterpret_cast<SourceLocation*>(getParams() + NumParams);
  }
  const SourceLocation *getStoredSelLocs() const {
    return reinterpret_cast<const SourceLocation*>(getParams() + NumParams);
  }

  /// \brief Get a pointer to the stored selector identifiers locations array.
  /// No locations will be stored if HasStandardSelLocs is true.
  ParmVarDecl **getParams() {
    return reinterpret_cast<ParmVarDecl **>(ParamsAndSelLocs);
  }
  const ParmVarDecl *const *getParams() const {
    return reinterpret_cast<const ParmVarDecl *const *>(ParamsAndSelLocs);
  }

  /// \brief Get the number of stored selector identifiers locations.
  /// No locations will be stored if HasStandardSelLocs is true.
  unsigned getNumStoredSelLocs() const {
    if (hasStandardSelLocs())
      return 0;
    return getNumSelectorLocs();
  }

  void setParamsAndSelLocs(ASTContext &C,
                           ArrayRef<ParmVarDecl*> Params,
                           ArrayRef<SourceLocation> SelLocs);

  /// \brief A definition will return its interface declaration.
  /// An interface declaration will return its definition.
  /// Otherwise it will return itself.
  ObjCMethodDecl *getNextRedeclarationImpl() override;

public:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;

  static ObjCMethodDecl *
  Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
         Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
         DeclContext *contextDecl, bool isInstance = true,
         bool isVariadic = false, bool isPropertyAccessor = false,
         bool isImplicitlyDeclared = false, bool isDefined = false,
         ImplementationControl impControl = None,
         bool HasRelatedResultType = false);

  static ObjCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID);

  ObjCMethodDecl *getCanonicalDecl() override;
  const ObjCMethodDecl *getCanonicalDecl() const {
    return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl();
  }

  ObjCDeclQualifier getObjCDeclQualifier() const {
    return ObjCDeclQualifier(objcDeclQualifier);
  }
  void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; }

  /// \brief Determine whether this method has a result type that is related
  /// to the message receiver's type.
  bool hasRelatedResultType() const { return RelatedResultType; }

  /// \brief Note whether this method has a related result type.
  void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; }

  /// \brief True if this is a method redeclaration in the same interface.
  bool isRedeclaration() const { return IsRedeclaration; }
  void setAsRedeclaration(const ObjCMethodDecl *PrevMethod);

  /// \brief Returns the location where the declarator ends. It will be
  /// the location of ';' for a method declaration and the location of '{'
  /// for a method definition.
  SourceLocation getDeclaratorEndLoc() const { return DeclEndLoc; }

  // Location information, modeled after the Stmt API.
  SourceLocation getLocStart() const LLVM_READONLY { return getLocation(); }
  SourceLocation getLocEnd() const LLVM_READONLY;
  SourceRange getSourceRange() const override LLVM_READONLY {
    return SourceRange(getLocation(), getLocEnd());
  }

  SourceLocation getSelectorStartLoc() const {
    if (isImplicit())
      return getLocStart();
    return getSelectorLoc(0);
  }

  SourceLocation getSelectorLoc(unsigned Index) const {
    assert(Index < getNumSelectorLocs() && "Index out of range!");
    if (hasStandardSelLocs())
      return getStandardSelectorLoc(Index, getSelector(),
                                   getSelLocsKind() == SelLoc_StandardWithSpace,
                                    parameters(),
                                   DeclEndLoc);
    return getStoredSelLocs()[Index];
  }

  void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;

  unsigned getNumSelectorLocs() const {
    if (isImplicit())
      return 0;
    Selector Sel = getSelector();
    if (Sel.isUnarySelector())
      return 1;
    return Sel.getNumArgs();
  }

  ObjCInterfaceDecl *getClassInterface();
  const ObjCInterfaceDecl *getClassInterface() const {
    return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
  }

  Selector getSelector() const { return getDeclName().getObjCSelector(); }

  QualType getReturnType() const { return MethodDeclType; }
  void setReturnType(QualType T) { MethodDeclType = T; }
  SourceRange getReturnTypeSourceRange() const;

  /// \brief Determine the type of an expression that sends a message to this
  /// function. This replaces the type parameters with the types they would
  /// get if the receiver was parameterless (e.g. it may replace the type
  /// parameter with 'id').
  QualType getSendResultType() const;

  /// Determine the type of an expression that sends a message to this
  /// function with the given receiver type.
  QualType getSendResultType(QualType receiverType) const;

  TypeSourceInfo *getReturnTypeSourceInfo() const { return ReturnTInfo; }
  void setReturnTypeSourceInfo(TypeSourceInfo *TInfo) { ReturnTInfo = TInfo; }

  // Iterator access to formal parameters.
  unsigned param_size() const { return NumParams; }

  using param_const_iterator = const ParmVarDecl *const *;
  using param_iterator = ParmVarDecl *const *;
  using param_range = llvm::iterator_range<param_iterator>;
  using param_const_range = llvm::iterator_range<param_const_iterator>;

  param_const_iterator param_begin() const {
    return param_const_iterator(getParams());
  }

  param_const_iterator param_end() const {
    return param_const_iterator(getParams() + NumParams);
  }

  param_iterator param_begin() { return param_iterator(getParams()); }
  param_iterator param_end() { return param_iterator(getParams() + NumParams); }

  // This method returns and of the parameters which are part of the selector
  // name mangling requirements.
  param_const_iterator sel_param_end() const {
    return param_begin() + getSelector().getNumArgs();
  }

  // ArrayRef access to formal parameters.  This should eventually
  // replace the iterator interface above.
  ArrayRef<ParmVarDecl*> parameters() const {
    return llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()),
                              NumParams);
  }

  /// \brief Sets the method's parameters and selector source locations.
  /// If the method is implicit (not coming from source) \p SelLocs is
  /// ignored.
  void setMethodParams(ASTContext &C,
                       ArrayRef<ParmVarDecl*> Params,
                       ArrayRef<SourceLocation> SelLocs = llvm::None);

  // Iterator access to parameter types.
  struct GetTypeFn {
    QualType operator()(const ParmVarDecl *PD) const { return PD->getType(); }
  };

  using param_type_iterator =
      llvm::mapped_iterator<param_const_iterator, GetTypeFn>;

  param_type_iterator param_type_begin() const {
    return llvm::map_iterator(param_begin(), GetTypeFn());
  }

  param_type_iterator param_type_end() const {
    return llvm::map_iterator(param_end(), GetTypeFn());
  }

  /// createImplicitParams - Used to lazily create the self and cmd
  /// implict parameters. This must be called prior to using getSelfDecl()
  /// or getCmdDecl(). The call is ignored if the implicit parameters
  /// have already been created.
  void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID);

  /// \return the type for \c self and set \arg selfIsPseudoStrong and
  /// \arg selfIsConsumed accordingly.
  QualType getSelfType(ASTContext &Context, const ObjCInterfaceDecl *OID,
                       bool &selfIsPseudoStrong, bool &selfIsConsumed);

  ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
  void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; }
  ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
  void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; }

  /// Determines the family of this method.
  ObjCMethodFamily getMethodFamily() const;

  bool isInstanceMethod() const { return IsInstance; }
  void setInstanceMethod(bool isInst) { IsInstance = isInst; }
  bool isVariadic() const { return IsVariadic; }
  void setVariadic(bool isVar) { IsVariadic = isVar; }

  bool isClassMethod() const { return !IsInstance; }

  bool isPropertyAccessor() const { return IsPropertyAccessor; }
  void setPropertyAccessor(bool isAccessor) { IsPropertyAccessor = isAccessor; }

  bool isDefined() const { return IsDefined; }
  void setDefined(bool isDefined) { IsDefined = isDefined; }

  /// \brief Whether this method overrides any other in the class hierarchy.
  ///
  /// A method is said to override any method in the class's
  /// base classes, its protocols, or its categories' protocols, that has
  /// the same selector and is of the same kind (class or instance).
  /// A method in an implementation is not considered as overriding the same
  /// method in the interface or its categories.
  bool isOverriding() const { return IsOverriding; }
  void setOverriding(bool isOverriding) { IsOverriding = isOverriding; }

  /// \brief Return overridden methods for the given \p Method.
  ///
  /// An ObjC method is considered to override any method in the class's
  /// base classes (and base's categories), its protocols, or its categories'
  /// protocols, that has
  /// the same selector and is of the same kind (class or instance).
  /// A method in an implementation is not considered as overriding the same
  /// method in the interface or its categories.
  void getOverriddenMethods(
                     SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const;

  /// \brief True if the method was a definition but its body was skipped.
  bool hasSkippedBody() const { return HasSkippedBody; }
  void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; }

  /// \brief Returns the property associated with this method's selector.
  ///
  /// Note that even if this particular method is not marked as a property
  /// accessor, it is still possible for it to match a property declared in a
  /// superclass. Pass \c false if you only want to check the current class.
  const ObjCPropertyDecl *findPropertyDecl(bool CheckOverrides = true) const;

  // Related to protocols declared in  \@protocol
  void setDeclImplementation(ImplementationControl ic) {
    DeclImplementation = ic;
  }

  ImplementationControl getImplementationControl() const {
    return ImplementationControl(DeclImplementation);
  }

  bool isOptional() const {
    return getImplementationControl() == Optional;
  }

  /// Returns true if this specific method declaration is marked with the
  /// designated initializer attribute.
  bool isThisDeclarationADesignatedInitializer() const;

  /// Returns true if the method selector resolves to a designated initializer
  /// in the class's interface.
  ///
  /// \param InitMethod if non-null and the function returns true, it receives
  /// the method declaration that was marked with the designated initializer
  /// attribute.
  bool isDesignatedInitializerForTheInterface(
      const ObjCMethodDecl **InitMethod = nullptr) const;

  /// \brief Determine whether this method has a body.
  bool hasBody() const override { return Body.isValid(); }

  /// \brief Retrieve the body of this method, if it has one.
  Stmt *getBody() const override;

  void setLazyBody(uint64_t Offset) { Body = Offset; }

  CompoundStmt *getCompoundBody() { return (CompoundStmt*)getBody(); }
  void setBody(Stmt *B) { Body = B; }

  /// \brief Returns whether this specific method is a definition.
  bool isThisDeclarationADefinition() const { return hasBody(); }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ObjCMethod; }

  static DeclContext *castToDeclContext(const ObjCMethodDecl *D) {
    return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D));
  }

  static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) {
    return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC));
  }
};

/// Describes the variance of a given generic parameter.
enum class ObjCTypeParamVariance : uint8_t {
  /// The parameter is invariant: must match exactly.
  Invariant,

  /// The parameter is covariant, e.g., X<T> is a subtype of X<U> when
  /// the type parameter is covariant and T is a subtype of U.
  Covariant,

  /// The parameter is contravariant, e.g., X<T> is a subtype of X<U>
  /// when the type parameter is covariant and U is a subtype of T.
  Contravariant,
};

/// Represents the declaration of an Objective-C type parameter.
///
/// \code
/// @interface NSDictionary<Key : id<NSCopying>, Value>
/// @end
/// \endcode
///
/// In the example above, both \c Key and \c Value are represented by
/// \c ObjCTypeParamDecl. \c Key has an explicit bound of \c id<NSCopying>,
/// while \c Value gets an implicit bound of \c id.
///
/// Objective-C type parameters are typedef-names in the grammar,
class ObjCTypeParamDecl : public TypedefNameDecl {
  /// Index of this type parameter in the type parameter list.
  unsigned Index : 14;

  /// The variance of the type parameter.
  unsigned Variance : 2;

  /// The location of the variance, if any.
  SourceLocation VarianceLoc;

  /// The location of the ':', which will be valid when the bound was
  /// explicitly specified.
  SourceLocation ColonLoc;

  ObjCTypeParamDecl(ASTContext &ctx, DeclContext *dc, 
                    ObjCTypeParamVariance variance, SourceLocation varianceLoc,
                    unsigned index,
                    SourceLocation nameLoc, IdentifierInfo *name,
                    SourceLocation colonLoc, TypeSourceInfo *boundInfo)
      : TypedefNameDecl(ObjCTypeParam, ctx, dc, nameLoc, nameLoc, name,
                        boundInfo),
        Index(index), Variance(static_cast<unsigned>(variance)),
        VarianceLoc(varianceLoc), ColonLoc(colonLoc) {}

  void anchor() override;

public:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;

  static ObjCTypeParamDecl *Create(ASTContext &ctx, DeclContext *dc,
                                   ObjCTypeParamVariance variance,
                                   SourceLocation varianceLoc,
                                   unsigned index,
                                   SourceLocation nameLoc,
                                   IdentifierInfo *name,
                                   SourceLocation colonLoc,
                                   TypeSourceInfo *boundInfo);
  static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx, unsigned ID);

  SourceRange getSourceRange() const override LLVM_READONLY;

  /// Determine the variance of this type parameter.
  ObjCTypeParamVariance getVariance() const {
    return static_cast<ObjCTypeParamVariance>(Variance);
  }

  /// Set the variance of this type parameter.
  void setVariance(ObjCTypeParamVariance variance) {
    Variance = static_cast<unsigned>(variance);
  }

  /// Retrieve the location of the variance keyword.
  SourceLocation getVarianceLoc() const { return VarianceLoc; }

  /// Retrieve the index into its type parameter list.
  unsigned getIndex() const { return Index; }

  /// Whether this type parameter has an explicitly-written type bound, e.g.,
  /// "T : NSView".
  bool hasExplicitBound() const { return ColonLoc.isValid(); }

  /// Retrieve the location of the ':' separating the type parameter name
  /// from the explicitly-specified bound.
  SourceLocation getColonLoc() const { return ColonLoc; }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ObjCTypeParam; }
};

/// Stores a list of Objective-C type parameters for a parameterized class
/// or a category/extension thereof.
///
/// \code
/// @interface NSArray<T> // stores the <T>
/// @end
/// \endcode
class ObjCTypeParamList final
    : private llvm::TrailingObjects<ObjCTypeParamList, ObjCTypeParamDecl *> {
  /// Stores the components of a SourceRange as a POD.
  struct PODSourceRange {
    unsigned Begin;
    unsigned End;
  };

  union { 
    /// Location of the left and right angle brackets.
    PODSourceRange Brackets;

    // Used only for alignment.
    ObjCTypeParamDecl *AlignmentHack;
  };

  /// The number of parameters in the list, which are tail-allocated.
  unsigned NumParams;

  ObjCTypeParamList(SourceLocation lAngleLoc,
                    ArrayRef<ObjCTypeParamDecl *> typeParams,
                    SourceLocation rAngleLoc);

public:
  friend TrailingObjects;

  /// Create a new Objective-C type parameter list.
  static ObjCTypeParamList *create(ASTContext &ctx,
                                   SourceLocation lAngleLoc,
                                   ArrayRef<ObjCTypeParamDecl *> typeParams,
                                   SourceLocation rAngleLoc);

  /// Iterate through the type parameters in the list.
  using iterator = ObjCTypeParamDecl **;

  iterator begin() { return getTrailingObjects<ObjCTypeParamDecl *>(); }

  iterator end() { return begin() + size(); }

  /// Determine the number of type parameters in this list.
  unsigned size() const { return NumParams; }

  // Iterate through the type parameters in the list.
  using const_iterator = ObjCTypeParamDecl * const *;

  const_iterator begin() const {
    return getTrailingObjects<ObjCTypeParamDecl *>();
  }

  const_iterator end() const {
    return begin() + size();
  }

  ObjCTypeParamDecl *front() const {
    assert(size() > 0 && "empty Objective-C type parameter list");
    return *begin();
  }

  ObjCTypeParamDecl *back() const {
    assert(size() > 0 && "empty Objective-C type parameter list");
    return *(end() - 1);
  }

  SourceLocation getLAngleLoc() const {
    return SourceLocation::getFromRawEncoding(Brackets.Begin);
  }

  SourceLocation getRAngleLoc() const {
    return SourceLocation::getFromRawEncoding(Brackets.End);
  }

  SourceRange getSourceRange() const {
    return SourceRange(getLAngleLoc(), getRAngleLoc());
  }

  /// Gather the default set of type arguments to be substituted for
  /// these type parameters when dealing with an unspecialized type.
  void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const;
};

enum class ObjCPropertyQueryKind : uint8_t {
  OBJC_PR_query_unknown = 0x00,
  OBJC_PR_query_instance,
  OBJC_PR_query_class
};

/// \brief Represents one property declaration in an Objective-C interface.
///
/// For example:
/// \code{.mm}
/// \@property (assign, readwrite) int MyProperty;
/// \endcode
class ObjCPropertyDecl : public NamedDecl {
  void anchor() override;

public:
  enum PropertyAttributeKind {
    OBJC_PR_noattr    = 0x00,
    OBJC_PR_readonly  = 0x01,
    OBJC_PR_getter    = 0x02,
    OBJC_PR_assign    = 0x04,
    OBJC_PR_readwrite = 0x08,
    OBJC_PR_retain    = 0x10,
    OBJC_PR_copy      = 0x20,
    OBJC_PR_nonatomic = 0x40,
    OBJC_PR_setter    = 0x80,
    OBJC_PR_atomic    = 0x100,
    OBJC_PR_weak      = 0x200,
    OBJC_PR_strong    = 0x400,
    OBJC_PR_unsafe_unretained = 0x800,
    /// Indicates that the nullability of the type was spelled with a
    /// property attribute rather than a type qualifier.
    OBJC_PR_nullability = 0x1000,
    OBJC_PR_null_resettable = 0x2000,
    OBJC_PR_class = 0x4000
    // Adding a property should change NumPropertyAttrsBits
  };

  enum {
    /// \brief Number of bits fitting all the property attributes.
    NumPropertyAttrsBits = 15
  };

  enum SetterKind { Assign, Retain, Copy, Weak };
  enum PropertyControl { None, Required, Optional };

private:
  // location of \@property
  SourceLocation AtLoc;

  // location of '(' starting attribute list or null.
  SourceLocation LParenLoc;

  QualType DeclType;
  TypeSourceInfo *DeclTypeSourceInfo;
  unsigned PropertyAttributes : NumPropertyAttrsBits;
  unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits;

  // \@required/\@optional
  unsigned PropertyImplementation : 2;

  // getter name of NULL if no getter
  Selector GetterName;

  // setter name of NULL if no setter
  Selector SetterName;

  // location of the getter attribute's value
  SourceLocation GetterNameLoc;

  // location of the setter attribute's value
  SourceLocation SetterNameLoc;

  // Declaration of getter instance method
  ObjCMethodDecl *GetterMethodDecl = nullptr;

  // Declaration of setter instance method
  ObjCMethodDecl *SetterMethodDecl = nullptr;

  // Synthesize ivar for this property
  ObjCIvarDecl *PropertyIvarDecl = nullptr;

  ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
                   SourceLocation AtLocation,  SourceLocation LParenLocation,
                   QualType T, TypeSourceInfo *TSI,
                   PropertyControl propControl)
    : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation),
      LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI),
      PropertyAttributes(OBJC_PR_noattr),
      PropertyAttributesAsWritten(OBJC_PR_noattr),
      PropertyImplementation(propControl), GetterName(Selector()),
      SetterName(Selector()) {}

public:
  static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
                                  SourceLocation L,
                                  IdentifierInfo *Id, SourceLocation AtLocation,
                                  SourceLocation LParenLocation,
                                  QualType T,
                                  TypeSourceInfo *TSI,
                                  PropertyControl propControl = None);

  static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);

  SourceLocation getAtLoc() const { return AtLoc; }
  void setAtLoc(SourceLocation L) { AtLoc = L; }

  SourceLocation getLParenLoc() const { return LParenLoc; }
  void setLParenLoc(SourceLocation L) { LParenLoc = L; }

  TypeSourceInfo *getTypeSourceInfo() const { return DeclTypeSourceInfo; }

  QualType getType() const { return DeclType; }

  void setType(QualType T, TypeSourceInfo *TSI) {
    DeclType = T;
    DeclTypeSourceInfo = TSI;
  }

  /// Retrieve the type when this property is used with a specific base object
  /// type.
  QualType getUsageType(QualType objectType) const;

  PropertyAttributeKind getPropertyAttributes() const {
    return PropertyAttributeKind(PropertyAttributes);
  }

  void setPropertyAttributes(PropertyAttributeKind PRVal) {
    PropertyAttributes |= PRVal;
  }

  void overwritePropertyAttributes(unsigned PRVal) {
    PropertyAttributes = PRVal;
  }

  PropertyAttributeKind getPropertyAttributesAsWritten() const {
    return PropertyAttributeKind(PropertyAttributesAsWritten);
  }

  void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) {
    PropertyAttributesAsWritten = PRVal;
  }

  // Helper methods for accessing attributes.

  /// isReadOnly - Return true iff the property has a setter.
  bool isReadOnly() const {
    return (PropertyAttributes & OBJC_PR_readonly);
  }

  /// isAtomic - Return true if the property is atomic.
  bool isAtomic() const {
    return (PropertyAttributes & OBJC_PR_atomic);
  }

  /// isRetaining - Return true if the property retains its value.
  bool isRetaining() const {
    return (PropertyAttributes &
            (OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_copy));
  }

  bool isInstanceProperty() const { return !isClassProperty(); }
  bool isClassProperty() const { return PropertyAttributes & OBJC_PR_class; }

  ObjCPropertyQueryKind getQueryKind() const {
    return isClassProperty() ? ObjCPropertyQueryKind::OBJC_PR_query_class :
                               ObjCPropertyQueryKind::OBJC_PR_query_instance;
  }

  static ObjCPropertyQueryKind getQueryKind(bool isClassProperty) {
    return isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class :
                             ObjCPropertyQueryKind::OBJC_PR_query_instance;
  }

  /// getSetterKind - Return the method used for doing assignment in
  /// the property setter. This is only valid if the property has been
  /// defined to have a setter.
  SetterKind getSetterKind() const {
    if (PropertyAttributes & OBJC_PR_strong)
      return getType()->isBlockPointerType() ? Copy : Retain;
    if (PropertyAttributes & OBJC_PR_retain)
      return Retain;
    if (PropertyAttributes & OBJC_PR_copy)
      return Copy;
    if (PropertyAttributes & OBJC_PR_weak)
      return Weak;
    return Assign;
  }

  Selector getGetterName() const { return GetterName; }
  SourceLocation getGetterNameLoc() const { return GetterNameLoc; }

  void setGetterName(Selector Sel, SourceLocation Loc = SourceLocation()) {
    GetterName = Sel;
    GetterNameLoc = Loc;
  }

  Selector getSetterName() const { return SetterName; }
  SourceLocation getSetterNameLoc() const { return SetterNameLoc; }

  void setSetterName(Selector Sel, SourceLocation Loc = SourceLocation()) {
    SetterName = Sel;
    SetterNameLoc = Loc;
  }

  ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
  void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; }

  ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
  void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; }

  // Related to \@optional/\@required declared in \@protocol
  void setPropertyImplementation(PropertyControl pc) {
    PropertyImplementation = pc;
  }

  PropertyControl getPropertyImplementation() const {
    return PropertyControl(PropertyImplementation);
  }

  bool isOptional() const {
    return getPropertyImplementation() == PropertyControl::Optional;
  }

  void setPropertyIvarDecl(ObjCIvarDecl *Ivar) {
    PropertyIvarDecl = Ivar;
  }

  ObjCIvarDecl *getPropertyIvarDecl() const {
    return PropertyIvarDecl;
  }

  SourceRange getSourceRange() const override LLVM_READONLY {
    return SourceRange(AtLoc, getLocation());
  }

  /// Get the default name of the synthesized ivar.
  IdentifierInfo *getDefaultSynthIvarName(ASTContext &Ctx) const;

  /// Lookup a property by name in the specified DeclContext.
  static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC,
                                            const IdentifierInfo *propertyID,
                                            ObjCPropertyQueryKind queryKind);

  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ObjCProperty; }
};

/// ObjCContainerDecl - Represents a container for method declarations.
/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
/// ObjCProtocolDecl, and ObjCImplDecl.
///
class ObjCContainerDecl : public NamedDecl, public DeclContext {
  SourceLocation AtStart;

  // These two locations in the range mark the end of the method container.
  // The first points to the '@' token, and the second to the 'end' token.
  SourceRange AtEnd;

  void anchor() override;

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

  // Iterator access to instance/class properties.
  using prop_iterator = specific_decl_iterator<ObjCPropertyDecl>;
  using prop_range =
      llvm::iterator_range<specific_decl_iterator<ObjCPropertyDecl>>;

  prop_range properties() const { return prop_range(prop_begin(), prop_end()); }

  prop_iterator prop_begin() const {
    return prop_iterator(decls_begin());
  }

  prop_iterator prop_end() const {
    return prop_iterator(decls_end());
  }

  using instprop_iterator =
      filtered_decl_iterator<ObjCPropertyDecl,
                             &ObjCPropertyDecl::isInstanceProperty>;
  using instprop_range = llvm::iterator_range<instprop_iterator>;

  instprop_range instance_properties() const {
    return instprop_range(instprop_begin(), instprop_end());
  }

  instprop_iterator instprop_begin() const {
    return instprop_iterator(decls_begin());
  }

  instprop_iterator instprop_end() const {
    return instprop_iterator(decls_end());
  }

  using classprop_iterator =
      filtered_decl_iterator<ObjCPropertyDecl,
                             &ObjCPropertyDecl::isClassProperty>;
  using classprop_range = llvm::iterator_range<classprop_iterator>;

  classprop_range class_properties() const {
    return classprop_range(classprop_begin(), classprop_end());
  }

  classprop_iterator classprop_begin() const {
    return classprop_iterator(decls_begin());
  }

  classprop_iterator classprop_end() const {
    return classprop_iterator(decls_end());
  }

  // Iterator access to instance/class methods.
  using method_iterator = specific_decl_iterator<ObjCMethodDecl>;
  using method_range =
      llvm::iterator_range<specific_decl_iterator<ObjCMethodDecl>>;

  method_range methods() const {
    return method_range(meth_begin(), meth_end());
  }

  method_iterator meth_begin() const {
    return method_iterator(decls_begin());
  }

  method_iterator meth_end() const {
    return method_iterator(decls_end());
  }

  using instmeth_iterator =
      filtered_decl_iterator<ObjCMethodDecl,
                             &ObjCMethodDecl::isInstanceMethod>;
  using instmeth_range = llvm::iterator_range<instmeth_iterator>;

  instmeth_range instance_methods() const {
    return instmeth_range(instmeth_begin(), instmeth_end());
  }

  instmeth_iterator instmeth_begin() const {
    return instmeth_iterator(decls_begin());
  }

  instmeth_iterator instmeth_end() const {
    return instmeth_iterator(decls_end());
  }

  using classmeth_iterator =
      filtered_decl_iterator<ObjCMethodDecl,
                             &ObjCMethodDecl::isClassMethod>;
  using classmeth_range = llvm::iterator_range<classmeth_iterator>;

  classmeth_range class_methods() const {
    return classmeth_range(classmeth_begin(), classmeth_end());
  }

  classmeth_iterator classmeth_begin() const {
    return classmeth_iterator(decls_begin());
  }

  classmeth_iterator classmeth_end() const {
    return classmeth_iterator(decls_end());
  }

  // Get the local instance/class method declared in this interface.
  ObjCMethodDecl *getMethod(Selector Sel, bool isInstance,
                            bool AllowHidden = false) const;

  ObjCMethodDecl *getInstanceMethod(Selector Sel,
                                    bool AllowHidden = false) const {
    return getMethod(Sel, true/*isInstance*/, AllowHidden);
  }

  ObjCMethodDecl *getClassMethod(Selector Sel, bool AllowHidden = false) const {
    return getMethod(Sel, false/*isInstance*/, AllowHidden);
  }

  bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const;
  ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;

  ObjCPropertyDecl *
  FindPropertyDeclaration(const IdentifierInfo *PropertyId,
                          ObjCPropertyQueryKind QueryKind) const;

  using PropertyMap =
      llvm::DenseMap<std::pair<IdentifierInfo *, unsigned/*isClassProperty*/>,
                     ObjCPropertyDecl *>;
  using ProtocolPropertySet = llvm::SmallDenseSet<const ObjCProtocolDecl *, 8>;
  using PropertyDeclOrder = llvm::SmallVector<ObjCPropertyDecl *, 8>;
  
  /// This routine collects list of properties to be implemented in the class.
  /// This includes, class's and its conforming protocols' properties.
  /// Note, the superclass's properties are not included in the list.
  virtual void collectPropertiesToImplement(PropertyMap &PM,
                                            PropertyDeclOrder &PO) const {}

  SourceLocation getAtStartLoc() const { return AtStart; }
  void setAtStartLoc(SourceLocation Loc) { AtStart = Loc; }

  // Marks the end of the container.
  SourceRange getAtEndRange() const {
    return AtEnd;
  }

  void setAtEndRange(SourceRange atEnd) {
    AtEnd = atEnd;
  }

  SourceRange getSourceRange() const override LLVM_READONLY {
    return SourceRange(AtStart, getAtEndRange().getEnd());
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }

  static bool classofKind(Kind K) {
    return K >= firstObjCContainer &&
           K <= lastObjCContainer;
  }

  static DeclContext *castToDeclContext(const ObjCContainerDecl *D) {
    return static_cast<DeclContext *>(const_cast<ObjCContainerDecl*>(D));
  }

  static ObjCContainerDecl *castFromDeclContext(const DeclContext *DC) {
    return static_cast<ObjCContainerDecl *>(const_cast<DeclContext*>(DC));
  }
};

/// \brief Represents an ObjC class declaration.
///
/// For example:
///
/// \code
///   // MostPrimitive declares no super class (not particularly useful).
///   \@interface MostPrimitive
///     // no instance variables or methods.
///   \@end
///
///   // NSResponder inherits from NSObject & implements NSCoding (a protocol).
///   \@interface NSResponder : NSObject \<NSCoding>
///   { // instance variables are represented by ObjCIvarDecl.
///     id nextResponder; // nextResponder instance variable.
///   }
///   - (NSResponder *)nextResponder; // return a pointer to NSResponder.
///   - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer
///   \@end                                    // to an NSEvent.
/// \endcode
///
///   Unlike C/C++, forward class declarations are accomplished with \@class.
///   Unlike C/C++, \@class allows for a list of classes to be forward declared.
///   Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes
///   typically inherit from NSObject (an exception is NSProxy).
///
class ObjCInterfaceDecl : public ObjCContainerDecl
                        , public Redeclarable<ObjCInterfaceDecl> {
  friend class ASTContext;

  /// TypeForDecl - This indicates the Type object that represents this
  /// TypeDecl.  It is a cache maintained by ASTContext::getObjCInterfaceType
  mutable const Type *TypeForDecl = nullptr;
  
  struct DefinitionData {
    /// \brief The definition of this class, for quick access from any 
    /// declaration.
    ObjCInterfaceDecl *Definition = nullptr;
    
    /// When non-null, this is always an ObjCObjectType.
    TypeSourceInfo *SuperClassTInfo = nullptr;
    
    /// Protocols referenced in the \@interface  declaration
    ObjCProtocolList ReferencedProtocols;

    /// Protocols reference in both the \@interface and class extensions.
    ObjCList<ObjCProtocolDecl> AllReferencedProtocols;

    /// \brief List of categories and class extensions defined for this class.
    ///
    /// Categories are stored as a linked list in the AST, since the categories
    /// and class extensions come long after the initial interface declaration,
    /// and we avoid dynamically-resized arrays in the AST wherever possible.
    ObjCCategoryDecl *CategoryList = nullptr;

    /// IvarList - List of all ivars defined by this class; including class
    /// extensions and implementation. This list is built lazily.
    ObjCIvarDecl *IvarList = nullptr;

    /// \brief Indicates that the contents of this Objective-C class will be
    /// completed by the external AST source when required.
    mutable unsigned ExternallyCompleted : 1;

    /// \brief Indicates that the ivar cache does not yet include ivars
    /// declared in the implementation.
    mutable unsigned IvarListMissingImplementation : 1;

    /// Indicates that this interface decl contains at least one initializer
    /// marked with the 'objc_designated_initializer' attribute.
    unsigned HasDesignatedInitializers : 1;

    enum InheritedDesignatedInitializersState {
      /// We didn't calculate whether the designated initializers should be
      /// inherited or not.
      IDI_Unknown = 0,

      /// Designated initializers are inherited for the super class.
      IDI_Inherited = 1,

      /// The class does not inherit designated initializers.
      IDI_NotInherited = 2
    };

    /// One of the \c InheritedDesignatedInitializersState enumeratos.
    mutable unsigned InheritedDesignatedInitializers : 2;
    
    /// \brief The location of the last location in this declaration, before
    /// the properties/methods. For example, this will be the '>', '}', or 
    /// identifier, 
    SourceLocation EndLoc; 

    DefinitionData()
        : ExternallyCompleted(false), IvarListMissingImplementation(true),
          HasDesignatedInitializers(false),
          InheritedDesignatedInitializers(IDI_Unknown) {}
  };

  /// The type parameters associated with this class, if any.
  ObjCTypeParamList *TypeParamList = nullptr;

  /// \brief Contains a pointer to the data associated with this class,
  /// which will be NULL if this class has not yet been defined.
  ///
  /// The bit indicates when we don't need to check for out-of-date
  /// declarations. It will be set unless modules are enabled.
  llvm::PointerIntPair<DefinitionData *, 1, bool> Data;

  ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
                    IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
                    SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
                    bool IsInternal);

  void anchor() override;

  void LoadExternalDefinition() const;

  DefinitionData &data() const {
    assert(Data.getPointer() && "Declaration has no definition!");
    return *Data.getPointer();
  }

  /// \brief Allocate the definition data for this class.
  void allocateDefinitionData();
  
  using redeclarable_base = Redeclarable<ObjCInterfaceDecl>;

  ObjCInterfaceDecl *getNextRedeclarationImpl() override {
    return getNextRedeclaration();
  }

  ObjCInterfaceDecl *getPreviousDeclImpl() override {
    return getPreviousDecl();
  }

  ObjCInterfaceDecl *getMostRecentDeclImpl() override {
    return getMostRecentDecl();
  }

public:
  static ObjCInterfaceDecl *Create(const ASTContext &C, DeclContext *DC,
                                   SourceLocation atLoc,
                                   IdentifierInfo *Id,
                                   ObjCTypeParamList *typeParamList,
                                   ObjCInterfaceDecl *PrevDecl,
                                   SourceLocation ClassLoc = SourceLocation(),
                                   bool isInternal = false);

  static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID);

  /// Retrieve the type parameters of this class.
  ///
  /// This function looks for a type parameter list for the given
  /// class; if the class has been declared (with \c \@class) but not
  /// defined (with \c \@interface), it will search for a declaration that
  /// has type parameters, skipping any declarations that do not.
  ObjCTypeParamList *getTypeParamList() const;

  /// Set the type parameters of this class.
  ///
  /// This function is used by the AST importer, which must import the type
  /// parameters after creating their DeclContext to avoid loops.
  void setTypeParamList(ObjCTypeParamList *TPL);

  /// Retrieve the type parameters written on this particular declaration of
  /// the class.
  ObjCTypeParamList *getTypeParamListAsWritten() const {
    return TypeParamList;
  }

  SourceRange getSourceRange() const override LLVM_READONLY {
    if (isThisDeclarationADefinition())
      return ObjCContainerDecl::getSourceRange();
    
    return SourceRange(getAtStartLoc(), getLocation());
  }

  /// \brief Indicate that this Objective-C class is complete, but that
  /// the external AST source will be responsible for filling in its contents
  /// when a complete class is required.
  void setExternallyCompleted();

  /// Indicate that this interface decl contains at least one initializer
  /// marked with the 'objc_designated_initializer' attribute.
  void setHasDesignatedInitializers();

  /// Returns true if this interface decl contains at least one initializer
  /// marked with the 'objc_designated_initializer' attribute.
  bool hasDesignatedInitializers() const;

  /// Returns true if this interface decl declares a designated initializer
  /// or it inherites one from its super class.
  bool declaresOrInheritsDesignatedInitializers() const {
    return hasDesignatedInitializers() || inheritsDesignatedInitializers();
  }

  const ObjCProtocolList &getReferencedProtocols() const {
    assert(hasDefinition() && "Caller did not check for forward reference!");
    if (data().ExternallyCompleted)
      LoadExternalDefinition();

    return data().ReferencedProtocols;
  }

  ObjCImplementationDecl *getImplementation() const;
  void setImplementation(ObjCImplementationDecl *ImplD);

  ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;

  // Get the local instance/class method declared in a category.
  ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const;
  ObjCMethodDecl *getCategoryClassMethod(Selector Sel) const;

  ObjCMethodDecl *getCategoryMethod(Selector Sel, bool isInstance) const {
    return isInstance ? getCategoryInstanceMethod(Sel)
                      : getCategoryClassMethod(Sel);
  }

  using protocol_iterator = ObjCProtocolList::iterator;
  using protocol_range = llvm::iterator_range<protocol_iterator>;

  protocol_range protocols() const {
    return protocol_range(protocol_begin(), protocol_end());
  }

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

    return data().ReferencedProtocols.begin();
  }

  protocol_iterator protocol_end() const {
    // FIXME: Should make sure no callers ever do this.
    if (!hasDefinition())
      return protocol_iterator();

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

    return data().ReferencedProtocols.end();
  }

  using protocol_loc_iterator = ObjCProtocolList::loc_iterator;
  using protocol_loc_range = llvm::iterator_range<protocol_loc_iterator>;

  protocol_loc_range protocol_locs() const {
    return protocol_loc_range(protocol_loc_begin(), protocol_loc_end());
  }

  protocol_loc_iterator protocol_loc_begin() const {
    // FIXME: Should make sure no callers ever do this.
    if (!hasDefinition())
      return protocol_loc_iterator();

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

    return data().ReferencedProtocols.loc_begin();
  }

  protocol_loc_iterator protocol_loc_end() const {
    // FIXME: Should make sure no callers ever do this.
    if (!hasDefinition())
      return protocol_loc_iterator();

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

    return data().ReferencedProtocols.loc_end();
  }

  using all_protocol_iterator = ObjCList<ObjCProtocolDecl>::iterator;
  using all_protocol_range = llvm::iterator_range<all_protocol_iterator>;

  all_protocol_range all_referenced_protocols() const {
    return all_protocol_range(all_referenced_protocol_begin(),
                              all_referenced_protocol_end());
  }

  all_protocol_iterator all_referenced_protocol_begin() const {
    // FIXME: Should make sure no callers ever do this.
    if (!hasDefinition())
      return all_protocol_iterator();

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

    return data().AllReferencedProtocols.empty()  
             ? protocol_begin()
             : data().AllReferencedProtocols.begin();
  }

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

    return data().AllReferencedProtocols.empty() 
             ? protocol_end()
             : data().AllReferencedProtocols.end();
  }

  using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>;
  using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>;

  ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }

  ivar_iterator ivar_begin() const { 
    if (const ObjCInterfaceDecl *Def = getDefinition())
      return ivar_iterator(Def->decls_begin()); 
    
    // FIXME: Should make sure no callers ever do this.
    return ivar_iterator();
  }

  ivar_iterator ivar_end() const { 
    if (const ObjCInterfaceDecl *Def = getDefinition())
      return ivar_iterator(Def->decls_end()); 

    // FIXME: Should make sure no callers ever do this.
    return ivar_iterator();
  }

  unsigned ivar_size() const {
    return std::distance(ivar_begin(), ivar_end());
  }

  bool ivar_empty() const { return ivar_begin() == ivar_end(); }

  ObjCIvarDecl *all_declared_ivar_begin();
  const ObjCIvarDecl *all_declared_ivar_begin() const {
    // Even though this modifies IvarList, it's conceptually const:
    // the ivar chain is essentially a cached property of ObjCInterfaceDecl.
    return const_cast<ObjCInterfaceDecl *>(this)->all_declared_ivar_begin();
  }
  void setIvarList(ObjCIvarDecl *ivar) { data().IvarList = ivar; }

  /// setProtocolList - Set the list of protocols that this interface
  /// implements.
  void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
                       const SourceLocation *Locs, ASTContext &C) {
    data().ReferencedProtocols.set(List, Num, Locs, C);
  }

  /// mergeClassExtensionProtocolList - Merge class extension's protocol list
  /// into the protocol list for this class.
  void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List,
                                       unsigned Num,
                                       ASTContext &C);

  /// Produce a name to be used for class's metadata. It comes either via
  /// objc_runtime_name attribute or class name.
  StringRef getObjCRuntimeNameAsString() const;

  /// Returns the designated initializers for the interface.
  ///
  /// If this declaration does not have methods marked as designated
  /// initializers then the interface inherits the designated initializers of
  /// its super class.
  void getDesignatedInitializers(
                  llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const;

  /// Returns true if the given selector is a designated initializer for the
  /// interface.
  ///
  /// If this declaration does not have methods marked as designated
  /// initializers then the interface inherits the designated initializers of
  /// its super class.
  ///
  /// \param InitMethod if non-null and the function returns true, it receives
  /// the method that was marked as a designated initializer.
  bool
  isDesignatedInitializer(Selector Sel,
                          const ObjCMethodDecl **InitMethod = nullptr) const;

  /// \brief Determine whether this particular declaration of this class is
  /// actually also a definition.
  bool isThisDeclarationADefinition() const { 
    return getDefinition() == this;
  }
                          
  /// \brief Determine whether this class has been defined.
  bool hasDefinition() const {
    // If the name of this class is out-of-date, bring it up-to-date, which
    // might bring in a definition.
    // Note: a null value indicates that we don't have a definition and that
    // modules are enabled.
    if (!Data.getOpaqueValue())
      getMostRecentDecl();

    return Data.getPointer();
  }
                        
  /// \brief Retrieve the definition of this class, or NULL if this class 
  /// has been forward-declared (with \@class) but not yet defined (with 
  /// \@interface).
  ObjCInterfaceDecl *getDefinition() {
    return hasDefinition()? Data.getPointer()->Definition : nullptr;
  }

  /// \brief Retrieve the definition of this class, or NULL if this class 
  /// has been forward-declared (with \@class) but not yet defined (with 
  /// \@interface).
  const ObjCInterfaceDecl *getDefinition() const {
    return hasDefinition()? Data.getPointer()->Definition : nullptr;
  }

  /// \brief Starts the definition of this Objective-C class, taking it from
  /// a forward declaration (\@class) to a definition (\@interface).
  void startDefinition();
  
  /// Retrieve the superclass type.
  const ObjCObjectType *getSuperClassType() const {
    if (TypeSourceInfo *TInfo = getSuperClassTInfo())
      return TInfo->getType()->castAs<ObjCObjectType>();

    return nullptr;
  }

  // Retrieve the type source information for the superclass.
  TypeSourceInfo *getSuperClassTInfo() const {
    // FIXME: Should make sure no callers ever do this.
    if (!hasDefinition())
      return nullptr;
    
    if (data().ExternallyCompleted)
      LoadExternalDefinition();

    return data().SuperClassTInfo;
  }

  // Retrieve the declaration for the superclass of this class, which
  // does not include any type arguments that apply to the superclass.
  ObjCInterfaceDecl *getSuperClass() const;

  void setSuperClass(TypeSourceInfo *superClass) { 
    data().SuperClassTInfo = superClass;
  }

  /// \brief Iterator that walks over the list of categories, filtering out
  /// those that do not meet specific criteria.
  ///
  /// This class template is used for the various permutations of category
  /// and extension iterators.
  template<bool (*Filter)(ObjCCategoryDecl *)>
  class filtered_category_iterator {
    ObjCCategoryDecl *Current = nullptr;

    void findAcceptableCategory();
    
  public:
    using value_type = ObjCCategoryDecl *;
    using reference = value_type;
    using pointer = value_type;
    using difference_type = std::ptrdiff_t;
    using iterator_category = std::input_iterator_tag;

    filtered_category_iterator() = default;
    explicit filtered_category_iterator(ObjCCategoryDecl *Current)
        : Current(Current) {
      findAcceptableCategory();
    }

    reference operator*() const { return Current; }
    pointer operator->() const { return Current; }

    filtered_category_iterator &operator++();

    filtered_category_iterator operator++(int) {
      filtered_category_iterator Tmp = *this;
      ++(*this);
      return Tmp;
    }

    friend bool operator==(filtered_category_iterator X,
                           filtered_category_iterator Y) {
      return X.Current == Y.Current;
    }

    friend bool operator!=(filtered_category_iterator X,
                           filtered_category_iterator Y) {
      return X.Current != Y.Current;
    }
  };

private:
  /// \brief Test whether the given category is visible.
  ///
  /// Used in the \c visible_categories_iterator.
  static bool isVisibleCategory(ObjCCategoryDecl *Cat);
                        
public:
  /// \brief Iterator that walks over the list of categories and extensions
  /// that are visible, i.e., not hidden in a non-imported submodule.
  using visible_categories_iterator =
      filtered_category_iterator<isVisibleCategory>;

  using visible_categories_range =
      llvm::iterator_range<visible_categories_iterator>;

  visible_categories_range visible_categories() const {
    return visible_categories_range(visible_categories_begin(),
                                    visible_categories_end());
  }

  /// \brief Retrieve an iterator to the beginning of the visible-categories
  /// list.
  visible_categories_iterator visible_categories_begin() const {
    return visible_categories_iterator(getCategoryListRaw());
  }

  /// \brief Retrieve an iterator to the end of the visible-categories list.
  visible_categories_iterator visible_categories_end() const {
    return visible_categories_iterator();
  }

  /// \brief Determine whether the visible-categories list is empty.
  bool visible_categories_empty() const {
    return visible_categories_begin() == visible_categories_end();
  }

private:
  /// \brief Test whether the given category... is a category.
  ///
  /// Used in the \c known_categories_iterator.
  static bool isKnownCategory(ObjCCategoryDecl *) { return true; }

public:
  /// \brief Iterator that walks over all of the known categories and
  /// extensions, including those that are hidden.
  using known_categories_iterator = filtered_category_iterator<isKnownCategory>;
  using known_categories_range =
     llvm::iterator_range<known_categories_iterator>;

  known_categories_range known_categories() const {
    return known_categories_range(known_categories_begin(),
                                  known_categories_end());
  }

  /// \brief Retrieve an iterator to the beginning of the known-categories
  /// list.
  known_categories_iterator known_categories_begin() const {
    return known_categories_iterator(getCategoryListRaw());
  }

  /// \brief Retrieve an iterator to the end of the known-categories list.
  known_categories_iterator known_categories_end() const {
    return known_categories_iterator();
  }

  /// \brief Determine whether the known-categories list is empty.
  bool known_categories_empty() const {
    return known_categories_begin() == known_categories_end();
  }

private:
  /// \brief Test whether the given category is a visible extension.
  ///
  /// Used in the \c visible_extensions_iterator.
  static bool isVisibleExtension(ObjCCategoryDecl *Cat);

public:
  /// \brief Iterator that walks over all of the visible extensions, skipping
  /// any that are known but hidden.
  using visible_extensions_iterator =
      filtered_category_iterator<isVisibleExtension>;

  using visible_extensions_range =
      llvm::iterator_range<visible_extensions_iterator>;

  visible_extensions_range visible_extensions() const {
    return visible_extensions_range(visible_extensions_begin(),
                                    visible_extensions_end());
  }

  /// \brief Retrieve an iterator to the beginning of the visible-extensions
  /// list.
  visible_extensions_iterator visible_extensions_begin() const {
    return visible_extensions_iterator(getCategoryListRaw());
  }

  /// \brief Retrieve an iterator to the end of the visible-extensions list.
  visible_extensions_iterator visible_extensions_end() const {
    return visible_extensions_iterator();
  }

  /// \brief Determine whether the visible-extensions list is empty.
  bool visible_extensions_empty() const {
    return visible_extensions_begin() == visible_extensions_end();
  }

private:
  /// \brief Test whether the given category is an extension.
  ///
  /// Used in the \c known_extensions_iterator.
  static bool isKnownExtension(ObjCCategoryDecl *Cat);
  
public:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;
  friend class ASTReader;

  /// \brief Iterator that walks over all of the known extensions.
  using known_extensions_iterator =
      filtered_category_iterator<isKnownExtension>;
  using known_extensions_range =
      llvm::iterator_range<known_extensions_iterator>;

  known_extensions_range known_extensions() const {
    return known_extensions_range(known_extensions_begin(),
                                  known_extensions_end());
  }

  /// \brief Retrieve an iterator to the beginning of the known-extensions
  /// list.
  known_extensions_iterator known_extensions_begin() const {
    return known_extensions_iterator(getCategoryListRaw());
  }
  
  /// \brief Retrieve an iterator to the end of the known-extensions list.
  known_extensions_iterator known_extensions_end() const {
    return known_extensions_iterator();
  }

  /// \brief Determine whether the known-extensions list is empty.
  bool known_extensions_empty() const {
    return known_extensions_begin() == known_extensions_end();
  }

  /// \brief Retrieve the raw pointer to the start of the category/extension
  /// list.
  ObjCCategoryDecl* getCategoryListRaw() const {
    // FIXME: Should make sure no callers ever do this.
    if (!hasDefinition())
      return nullptr;
    
    if (data().ExternallyCompleted)
      LoadExternalDefinition();

    return data().CategoryList;
  }

  /// \brief Set the raw pointer to the start of the category/extension
  /// list.
  void setCategoryListRaw(ObjCCategoryDecl *category) {
    data().CategoryList = category;
  }

  ObjCPropertyDecl
    *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId,
                                       ObjCPropertyQueryKind QueryKind) const;

  void collectPropertiesToImplement(PropertyMap &PM,
                                    PropertyDeclOrder &PO) const override;

  /// isSuperClassOf - Return true if this class is the specified class or is a
  /// super class of the specified interface class.
  bool isSuperClassOf(const ObjCInterfaceDecl *I) const {
    // If RHS is derived from LHS it is OK; else it is not OK.
    while (I != nullptr) {
      if (declaresSameEntity(this, I))
        return true;
      
      I = I->getSuperClass();
    }
    return false;
  }

  /// isArcWeakrefUnavailable - Checks for a class or one of its super classes
  /// to be incompatible with __weak references. Returns true if it is.
  bool isArcWeakrefUnavailable() const;

  /// isObjCRequiresPropertyDefs - Checks that a class or one of its super 
  /// classes must not be auto-synthesized. Returns class decl. if it must not
  /// be; 0, otherwise.
  const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const;

  ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName,
                                       ObjCInterfaceDecl *&ClassDeclared);
  ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) {
    ObjCInterfaceDecl *ClassDeclared;
    return lookupInstanceVariable(IVarName, ClassDeclared);
  }

  ObjCProtocolDecl *lookupNestedProtocol(IdentifierInfo *Name);
                          
  // Lookup a method. First, we search locally. If a method isn't
  // found, we search referenced protocols and class categories.
  ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance,
                               bool shallowCategoryLookup = false,
                               bool followSuper = true,
                               const ObjCCategoryDecl *C = nullptr) const;

  /// Lookup an instance method for a given selector.
  ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
    return lookupMethod(Sel, true/*isInstance*/);
  }

  /// Lookup a class method for a given selector.
  ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
    return lookupMethod(Sel, false/*isInstance*/);
  }

  ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);

  /// \brief Lookup a method in the classes implementation hierarchy.
  ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel,
                                      bool Instance=true) const;

  ObjCMethodDecl *lookupPrivateClassMethod(const Selector &Sel) {
    return lookupPrivateMethod(Sel, false);
  }

  /// \brief Lookup a setter or getter in the class hierarchy,
  /// including in all categories except for category passed
  /// as argument.
  ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel,
                                         const ObjCCategoryDecl *Cat,
                                         bool IsClassProperty) const {
    return lookupMethod(Sel, !IsClassProperty/*isInstance*/,
                        false/*shallowCategoryLookup*/,
                        true /* followsSuper */,
                        Cat);
  }
                          
  SourceLocation getEndOfDefinitionLoc() const { 
    if (!hasDefinition())
      return getLocation();
    
    return data().EndLoc; 
  }
                          
  void setEndOfDefinitionLoc(SourceLocation LE) { data().EndLoc = LE; }

  /// Retrieve the starting location of the superclass.
  SourceLocation getSuperClassLoc() const;

  /// isImplicitInterfaceDecl - check that this is an implicitly declared
  /// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation
  /// declaration without an \@interface declaration.
  bool isImplicitInterfaceDecl() const { 
    return hasDefinition() ? data().Definition->isImplicit() : isImplicit();
  }

  /// ClassImplementsProtocol - Checks that 'lProto' protocol
  /// has been implemented in IDecl class, its super class or categories (if
  /// lookupCategory is true).
  bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
                               bool lookupCategory,
                               bool RHSIsQualifiedID = false);

  using redecl_range = redeclarable_base::redecl_range;
  using redecl_iterator = redeclarable_base::redecl_iterator;

  using redeclarable_base::redecls_begin;
  using redeclarable_base::redecls_end;
  using redeclarable_base::redecls;
  using redeclarable_base::getPreviousDecl;
  using redeclarable_base::getMostRecentDecl;
  using redeclarable_base::isFirstDecl;

  /// Retrieves the canonical declaration of this Objective-C class.
  ObjCInterfaceDecl *getCanonicalDecl() override { return getFirstDecl(); }
  const ObjCInterfaceDecl *getCanonicalDecl() const { return getFirstDecl(); }

  // Low-level accessor
  const Type *getTypeForDecl() const { return TypeForDecl; }
  void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }

  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ObjCInterface; }

private:
  const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const;
  bool inheritsDesignatedInitializers() const;
};

/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
/// instance variables are identical to C. The only exception is Objective-C
/// supports C++ style access control. For example:
///
///   \@interface IvarExample : NSObject
///   {
///     id defaultToProtected;
///   \@public:
///     id canBePublic; // same as C++.
///   \@protected:
///     id canBeProtected; // same as C++.
///   \@package:
///     id canBePackage; // framework visibility (not available in C++).
///   }
///
class ObjCIvarDecl : public FieldDecl {
  void anchor() override;

public:
  enum AccessControl {
    None, Private, Protected, Public, Package
  };

private:
  ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc,
               SourceLocation IdLoc, IdentifierInfo *Id,
               QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
               bool synthesized)
      : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
                  /*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
        DeclAccess(ac), Synthesized(synthesized) {}

public:
  static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
                              SourceLocation StartLoc, SourceLocation IdLoc,
                              IdentifierInfo *Id, QualType T,
                              TypeSourceInfo *TInfo,
                              AccessControl ac, Expr *BW = nullptr,
                              bool synthesized=false);

  static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
  
  /// \brief Return the class interface that this ivar is logically contained
  /// in; this is either the interface where the ivar was declared, or the
  /// interface the ivar is conceptually a part of in the case of synthesized
  /// ivars.
  const ObjCInterfaceDecl *getContainingInterface() const;

  ObjCIvarDecl *getNextIvar() { return NextIvar; }
  const ObjCIvarDecl *getNextIvar() const { return NextIvar; }
  void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; }

  void setAccessControl(AccessControl ac) { DeclAccess = ac; }

  AccessControl getAccessControl() const { return AccessControl(DeclAccess); }

  AccessControl getCanonicalAccessControl() const {
    return DeclAccess == None ? Protected : AccessControl(DeclAccess);
  }

  void setSynthesize(bool synth) { Synthesized = synth; }
  bool getSynthesize() const { return Synthesized; }

  /// Retrieve the type of this instance variable when viewed as a member of a
  /// specific object type.
  QualType getUsageType(QualType objectType) const;

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ObjCIvar; }

private:
  /// NextIvar - Next Ivar in the list of ivars declared in class; class's
  /// extensions and class's implementation
  ObjCIvarDecl *NextIvar = nullptr;

  // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
  unsigned DeclAccess : 3;
  unsigned Synthesized : 1;
};

/// \brief Represents a field declaration created by an \@defs(...).
class ObjCAtDefsFieldDecl : public FieldDecl {
  ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc,
                      SourceLocation IdLoc, IdentifierInfo *Id,
                      QualType T, Expr *BW)
      : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T,
                  /*TInfo=*/nullptr, // FIXME: Do ObjCAtDefs have declarators ?
                  BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {}

  void anchor() override;

public:
  static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
                                     SourceLocation StartLoc,
                                     SourceLocation IdLoc, IdentifierInfo *Id,
                                     QualType T, Expr *BW);

  static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
  
  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ObjCAtDefsField; }
};

/// \brief Represents an Objective-C protocol declaration.
///
/// Objective-C protocols declare a pure abstract type (i.e., no instance
/// variables are permitted).  Protocols originally drew inspiration from
/// C++ pure virtual functions (a C++ feature with nice semantics and lousy
/// syntax:-). Here is an example:
///
/// \code
/// \@protocol NSDraggingInfo <refproto1, refproto2>
/// - (NSWindow *)draggingDestinationWindow;
/// - (NSImage *)draggedImage;
/// \@end
/// \endcode
///
/// This says that NSDraggingInfo requires two methods and requires everything
/// that the two "referenced protocols" 'refproto1' and 'refproto2' require as
/// well.
///
/// \code
/// \@interface ImplementsNSDraggingInfo : NSObject \<NSDraggingInfo>
/// \@end
/// \endcode
///
/// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and
/// protocols are in distinct namespaces. For example, Cocoa defines both
/// an NSObject protocol and class (which isn't allowed in Java). As a result,
/// protocols are referenced using angle brackets as follows:
///
/// id \<NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
class ObjCProtocolDecl : public ObjCContainerDecl,
                         public Redeclarable<ObjCProtocolDecl> {
  struct DefinitionData {
    // \brief The declaration that defines this protocol.
    ObjCProtocolDecl *Definition;

    /// \brief Referenced protocols
    ObjCProtocolList ReferencedProtocols;    
  };

  /// \brief Contains a pointer to the data associated with this class,
  /// which will be NULL if this class has not yet been defined.
  ///
  /// The bit indicates when we don't need to check for out-of-date
  /// declarations. It will be set unless modules are enabled.
  llvm::PointerIntPair<DefinitionData *, 1, bool> Data;

  ObjCProtocolDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
                   SourceLocation nameLoc, SourceLocation atStartLoc,
                   ObjCProtocolDecl *PrevDecl);

  void anchor() override;

  DefinitionData &data() const {
    assert(Data.getPointer() && "Objective-C protocol has no definition!");
    return *Data.getPointer();
  }
  
  void allocateDefinitionData();

  using redeclarable_base = Redeclarable<ObjCProtocolDecl>;

  ObjCProtocolDecl *getNextRedeclarationImpl() override {
    return getNextRedeclaration();
  }

  ObjCProtocolDecl *getPreviousDeclImpl() override {
    return getPreviousDecl();
  }

  ObjCProtocolDecl *getMostRecentDeclImpl() override {
    return getMostRecentDecl();
  }

public:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;
  friend class ASTReader;

  static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
                                  IdentifierInfo *Id,
                                  SourceLocation nameLoc,
                                  SourceLocation atStartLoc,
                                  ObjCProtocolDecl *PrevDecl);

  static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, unsigned ID);

  const ObjCProtocolList &getReferencedProtocols() const {
    assert(hasDefinition() && "No definition available!");
    return data().ReferencedProtocols;
  }

  using protocol_iterator = ObjCProtocolList::iterator;
  using protocol_range = llvm::iterator_range<protocol_iterator>;

  protocol_range protocols() const {
    return protocol_range(protocol_begin(), protocol_end());
  }

  protocol_iterator protocol_begin() const {
    if (!hasDefinition())
      return protocol_iterator();
    
    return data().ReferencedProtocols.begin();
  }

  protocol_iterator protocol_end() const { 
    if (!hasDefinition())
      return protocol_iterator();
    
    return data().ReferencedProtocols.end(); 
  }

  using protocol_loc_iterator = ObjCProtocolList::loc_iterator;
  using protocol_loc_range = llvm::iterator_range<protocol_loc_iterator>;

  protocol_loc_range protocol_locs() const {
    return protocol_loc_range(protocol_loc_begin(), protocol_loc_end());
  }

  protocol_loc_iterator protocol_loc_begin() const {
    if (!hasDefinition())
      return protocol_loc_iterator();
    
    return data().ReferencedProtocols.loc_begin();
  }

  protocol_loc_iterator protocol_loc_end() const {
    if (!hasDefinition())
      return protocol_loc_iterator();
    
    return data().ReferencedProtocols.loc_end();
  }

  unsigned protocol_size() const { 
    if (!hasDefinition())
      return 0;
    
    return data().ReferencedProtocols.size(); 
  }

  /// setProtocolList - Set the list of protocols that this interface
  /// implements.
  void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
                       const SourceLocation *Locs, ASTContext &C) {
    assert(hasDefinition() && "Protocol is not defined");
    data().ReferencedProtocols.set(List, Num, Locs, C);
  }

  ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName);

  // Lookup a method. First, we search locally. If a method isn't
  // found, we search referenced protocols and class categories.
  ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const;

  ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
    return lookupMethod(Sel, true/*isInstance*/);
  }

  ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
    return lookupMethod(Sel, false/*isInstance*/);
  }

  /// \brief Determine whether this protocol has a definition.
  bool hasDefinition() const {
    // If the name of this protocol is out-of-date, bring it up-to-date, which
    // might bring in a definition.
    // Note: a null value indicates that we don't have a definition and that
    // modules are enabled.
    if (!Data.getOpaqueValue())
      getMostRecentDecl();

    return Data.getPointer();
  }

  /// \brief Retrieve the definition of this protocol, if any.
  ObjCProtocolDecl *getDefinition() {
    return hasDefinition()? Data.getPointer()->Definition : nullptr;
  }

  /// \brief Retrieve the definition of this protocol, if any.
  const ObjCProtocolDecl *getDefinition() const {
    return hasDefinition()? Data.getPointer()->Definition : nullptr;
  }

  /// \brief Determine whether this particular declaration is also the 
  /// definition.
  bool isThisDeclarationADefinition() const {
    return getDefinition() == this;
  }
  
  /// \brief Starts the definition of this Objective-C protocol.
  void startDefinition();

  /// Produce a name to be used for protocol's metadata. It comes either via
  /// objc_runtime_name attribute or protocol name.
  StringRef getObjCRuntimeNameAsString() const;

  SourceRange getSourceRange() const override LLVM_READONLY {
    if (isThisDeclarationADefinition())
      return ObjCContainerDecl::getSourceRange();
   
    return SourceRange(getAtStartLoc(), getLocation());
  }
   
  using redecl_range = redeclarable_base::redecl_range;
  using redecl_iterator = redeclarable_base::redecl_iterator;

  using redeclarable_base::redecls_begin;
  using redeclarable_base::redecls_end;
  using redeclarable_base::redecls;
  using redeclarable_base::getPreviousDecl;
  using redeclarable_base::getMostRecentDecl;
  using redeclarable_base::isFirstDecl;

  /// Retrieves the canonical declaration of this Objective-C protocol.
  ObjCProtocolDecl *getCanonicalDecl() override { return getFirstDecl(); }
  const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); }

  void collectPropertiesToImplement(PropertyMap &PM,
                                    PropertyDeclOrder &PO) const override;

  void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
                                          ProtocolPropertySet &PS,
                                          PropertyDeclOrder &PO) const;

  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ObjCProtocol; }
};

/// ObjCCategoryDecl - Represents a category declaration. A category allows
/// you to add methods to an existing class (without subclassing or modifying
/// the original class interface or implementation:-). Categories don't allow
/// you to add instance data. The following example adds "myMethod" to all
/// NSView's within a process:
///
/// \@interface NSView (MyViewMethods)
/// - myMethod;
/// \@end
///
/// Categories also allow you to split the implementation of a class across
/// several files (a feature more naturally supported in C++).
///
/// Categories were originally inspired by dynamic languages such as Common
/// Lisp and Smalltalk.  More traditional class-based languages (C++, Java)
/// don't support this level of dynamism, which is both powerful and dangerous.
class ObjCCategoryDecl : public ObjCContainerDecl {
  /// Interface belonging to this category
  ObjCInterfaceDecl *ClassInterface;

  /// The type parameters associated with this category, if any.
  ObjCTypeParamList *TypeParamList = nullptr;

  /// referenced protocols in this category.
  ObjCProtocolList ReferencedProtocols;

  /// Next category belonging to this class.
  /// FIXME: this should not be a singly-linked list.  Move storage elsewhere.
  ObjCCategoryDecl *NextClassCategory = nullptr;

  /// \brief The location of the category name in this declaration.
  SourceLocation CategoryNameLoc;

  /// class extension may have private ivars.
  SourceLocation IvarLBraceLoc;
  SourceLocation IvarRBraceLoc;
  
  ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
                   SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
                   IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
                   ObjCTypeParamList *typeParamList,
                   SourceLocation IvarLBraceLoc = SourceLocation(),
                   SourceLocation IvarRBraceLoc = SourceLocation());

  void anchor() override;

public:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;

  static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
                                  SourceLocation AtLoc,
                                  SourceLocation ClassNameLoc,
                                  SourceLocation CategoryNameLoc,
                                  IdentifierInfo *Id,
                                  ObjCInterfaceDecl *IDecl,
                                  ObjCTypeParamList *typeParamList,
                                  SourceLocation IvarLBraceLoc=SourceLocation(),
                                  SourceLocation IvarRBraceLoc=SourceLocation());
  static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID);

  ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
  const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }

  /// Retrieve the type parameter list associated with this category or
  /// extension.
  ObjCTypeParamList *getTypeParamList() const { return TypeParamList; }

  /// Set the type parameters of this category.
  ///
  /// This function is used by the AST importer, which must import the type
  /// parameters after creating their DeclContext to avoid loops.
  void setTypeParamList(ObjCTypeParamList *TPL);


  ObjCCategoryImplDecl *getImplementation() const;
  void setImplementation(ObjCCategoryImplDecl *ImplD);

  /// setProtocolList - Set the list of protocols that this interface
  /// implements.
  void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
                       const SourceLocation *Locs, ASTContext &C) {
    ReferencedProtocols.set(List, Num, Locs, C);
  }

  const ObjCProtocolList &getReferencedProtocols() const {
    return ReferencedProtocols;
  }

  using protocol_iterator = ObjCProtocolList::iterator;
  using protocol_range = llvm::iterator_range<protocol_iterator>;

  protocol_range protocols() const {
    return protocol_range(protocol_begin(), protocol_end());
  }

  protocol_iterator protocol_begin() const {
    return ReferencedProtocols.begin();
  }

  protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
  unsigned protocol_size() const { return ReferencedProtocols.size(); }

  using protocol_loc_iterator = ObjCProtocolList::loc_iterator;
  using protocol_loc_range = llvm::iterator_range<protocol_loc_iterator>;

  protocol_loc_range protocol_locs() const {
    return protocol_loc_range(protocol_loc_begin(), protocol_loc_end());
  }

  protocol_loc_iterator protocol_loc_begin() const {
    return ReferencedProtocols.loc_begin();
  }

  protocol_loc_iterator protocol_loc_end() const {
    return ReferencedProtocols.loc_end();
  }

  ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }

  /// \brief Retrieve the pointer to the next stored category (or extension),
  /// which may be hidden.
  ObjCCategoryDecl *getNextClassCategoryRaw() const {
    return NextClassCategory;
  }

  bool IsClassExtension() const { return getIdentifier() == nullptr; }

  using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>;
  using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>;

  ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }

  ivar_iterator ivar_begin() const {
    return ivar_iterator(decls_begin());
  }

  ivar_iterator ivar_end() const {
    return ivar_iterator(decls_end());
  }

  unsigned ivar_size() const {
    return std::distance(ivar_begin(), ivar_end());
  }

  bool ivar_empty() const {
    return ivar_begin() == ivar_end();
  }

  SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
  void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; }
  
  void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; }
  SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
  void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
  SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; }

  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ObjCCategory; }
};

class ObjCImplDecl : public ObjCContainerDecl {
  /// Class interface for this class/category implementation
  ObjCInterfaceDecl *ClassInterface;

  void anchor() override;

protected:
  ObjCImplDecl(Kind DK, DeclContext *DC,
               ObjCInterfaceDecl *classInterface,
               IdentifierInfo *Id,
               SourceLocation nameLoc, SourceLocation atStartLoc)
      : ObjCContainerDecl(DK, DC, Id, nameLoc, atStartLoc),
        ClassInterface(classInterface) {}

public:
  const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
  ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
  void setClassInterface(ObjCInterfaceDecl *IFace);

  void addInstanceMethod(ObjCMethodDecl *method) {
    // FIXME: Context should be set correctly before we get here.
    method->setLexicalDeclContext(this);
    addDecl(method);
  }

  void addClassMethod(ObjCMethodDecl *method) {
    // FIXME: Context should be set correctly before we get here.
    method->setLexicalDeclContext(this);
    addDecl(method);
  }

  void addPropertyImplementation(ObjCPropertyImplDecl *property);

  ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId,
                            ObjCPropertyQueryKind queryKind) const;
  ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const;

  // Iterator access to properties.
  using propimpl_iterator = specific_decl_iterator<ObjCPropertyImplDecl>;
  using propimpl_range =
      llvm::iterator_range<specific_decl_iterator<ObjCPropertyImplDecl>>;

  propimpl_range property_impls() const {
    return propimpl_range(propimpl_begin(), propimpl_end());
  }

  propimpl_iterator propimpl_begin() const {
    return propimpl_iterator(decls_begin());
  }

  propimpl_iterator propimpl_end() const {
    return propimpl_iterator(decls_end());
  }

  static bool classof(const Decl *D) { return classofKind(D->getKind()); }

  static bool classofKind(Kind K) {
    return K >= firstObjCImpl && K <= lastObjCImpl;
  }
};

/// ObjCCategoryImplDecl - An object of this class encapsulates a category
/// \@implementation declaration. If a category class has declaration of a
/// property, its implementation must be specified in the category's
/// \@implementation declaration. Example:
/// \@interface I \@end
/// \@interface I(CATEGORY)
///    \@property int p1, d1;
/// \@end
/// \@implementation I(CATEGORY)
///  \@dynamic p1,d1;
/// \@end
///
/// ObjCCategoryImplDecl
class ObjCCategoryImplDecl : public ObjCImplDecl {
  // Category name location
  SourceLocation CategoryNameLoc;

  ObjCCategoryImplDecl(DeclContext *DC, IdentifierInfo *Id,
                       ObjCInterfaceDecl *classInterface,
                       SourceLocation nameLoc, SourceLocation atStartLoc,
                       SourceLocation CategoryNameLoc)
      : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, Id,
                     nameLoc, atStartLoc),
        CategoryNameLoc(CategoryNameLoc) {}

  void anchor() override;

public:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;

  static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
                                      IdentifierInfo *Id,
                                      ObjCInterfaceDecl *classInterface,
                                      SourceLocation nameLoc,
                                      SourceLocation atStartLoc,
                                      SourceLocation CategoryNameLoc);
  static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);

  ObjCCategoryDecl *getCategoryDecl() const;

  SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }

  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ObjCCategoryImpl;}
};

raw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID);

/// ObjCImplementationDecl - Represents a class definition - this is where
/// method definitions are specified. For example:
///
/// @code
/// \@implementation MyClass
/// - (void)myMethod { /* do something */ }
/// \@end
/// @endcode
///
/// In a non-fragile runtime, instance variables can appear in the class
/// interface, class extensions (nameless categories), and in the implementation
/// itself, as well as being synthesized as backing storage for properties.
///
/// In a fragile runtime, instance variables are specified in the class
/// interface, \em not in the implementation. Nevertheless (for legacy reasons),
/// we allow instance variables to be specified in the implementation. When
/// specified, they need to be \em identical to the interface.
class ObjCImplementationDecl : public ObjCImplDecl {
  /// Implementation Class's super class.
  ObjCInterfaceDecl *SuperClass;
  SourceLocation SuperLoc;

  /// \@implementation may have private ivars.
  SourceLocation IvarLBraceLoc;
  SourceLocation IvarRBraceLoc;
  
  /// Support for ivar initialization.
  /// \brief The arguments used to initialize the ivars
  LazyCXXCtorInitializersPtr IvarInitializers;
  unsigned NumIvarInitializers = 0;

  /// Do the ivars of this class require initialization other than
  /// zero-initialization?
  bool HasNonZeroConstructors : 1;

  /// Do the ivars of this class require non-trivial destruction?
  bool HasDestructors : 1;

  ObjCImplementationDecl(DeclContext *DC,
                         ObjCInterfaceDecl *classInterface,
                         ObjCInterfaceDecl *superDecl,
                         SourceLocation nameLoc, SourceLocation atStartLoc,
                         SourceLocation superLoc = SourceLocation(),
                         SourceLocation IvarLBraceLoc=SourceLocation(), 
                         SourceLocation IvarRBraceLoc=SourceLocation())
      : ObjCImplDecl(ObjCImplementation, DC, classInterface,
                     classInterface ? classInterface->getIdentifier()
                                    : nullptr,
                     nameLoc, atStartLoc),
         SuperClass(superDecl), SuperLoc(superLoc),
         IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc),
         HasNonZeroConstructors(false), HasDestructors(false) {}

  void anchor() override;

public:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;

  static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
                                        ObjCInterfaceDecl *classInterface,
                                        ObjCInterfaceDecl *superDecl,
                                        SourceLocation nameLoc,
                                        SourceLocation atStartLoc,
                                     SourceLocation superLoc = SourceLocation(),
                                        SourceLocation IvarLBraceLoc=SourceLocation(), 
                                        SourceLocation IvarRBraceLoc=SourceLocation());

  static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID);

  /// init_iterator - Iterates through the ivar initializer list.
  using init_iterator = CXXCtorInitializer **;

  /// init_const_iterator - Iterates through the ivar initializer list.
  using init_const_iterator = CXXCtorInitializer * const *;

  using init_range = llvm::iterator_range<init_iterator>;
  using init_const_range = llvm::iterator_range<init_const_iterator>;

  init_range inits() { return init_range(init_begin(), init_end()); }

  init_const_range inits() const {
    return init_const_range(init_begin(), init_end());
  }

  /// init_begin() - Retrieve an iterator to the first initializer.
  init_iterator init_begin() {
    const auto *ConstThis = this;
    return const_cast<init_iterator>(ConstThis->init_begin());
  }

  /// begin() - Retrieve an iterator to the first initializer.
  init_const_iterator init_begin() const;

  /// init_end() - Retrieve an iterator past the last initializer.
  init_iterator       init_end()       {
    return init_begin() + NumIvarInitializers;
  }

  /// end() - Retrieve an iterator past the last initializer.
  init_const_iterator init_end() const {
    return init_begin() + NumIvarInitializers;
  }

  /// getNumArgs - Number of ivars which must be initialized.
  unsigned getNumIvarInitializers() const {
    return NumIvarInitializers;
  }

  void setNumIvarInitializers(unsigned numNumIvarInitializers) {
    NumIvarInitializers = numNumIvarInitializers;
  }

  void setIvarInitializers(ASTContext &C,
                           CXXCtorInitializer ** initializers,
                           unsigned numInitializers);

  /// Do any of the ivars of this class (not counting its base classes)
  /// require construction other than zero-initialization?
  bool hasNonZeroConstructors() const { return HasNonZeroConstructors; }
  void setHasNonZeroConstructors(bool val) { HasNonZeroConstructors = val; }

  /// Do any of the ivars of this class (not counting its base classes)
  /// require non-trivial destruction?
  bool hasDestructors() const { return HasDestructors; }
  void setHasDestructors(bool val) { HasDestructors = val; }

  /// getIdentifier - Get the identifier that names the class
  /// interface associated with this implementation.
  IdentifierInfo *getIdentifier() const {
    return getClassInterface()->getIdentifier();
  }

  /// getName - Get the name of identifier for the class interface associated
  /// with this implementation as a StringRef.
  //
  // FIXME: This is a bad API, we are hiding NamedDecl::getName with a different
  // meaning.
  StringRef getName() const {
    assert(getIdentifier() && "Name is not a simple identifier");
    return getIdentifier()->getName();
  }

  /// @brief Get the name of the class associated with this interface.
  //
  // FIXME: Move to StringRef API.
  std::string getNameAsString() const {
    return getName();
  }
    
  /// Produce a name to be used for class's metadata. It comes either via
  /// class's objc_runtime_name attribute or class name.
  StringRef getObjCRuntimeNameAsString() const;

  const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
  ObjCInterfaceDecl *getSuperClass() { return SuperClass; }
  SourceLocation getSuperClassLoc() const { return SuperLoc; }

  void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }

  void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; }
  SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
  void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
  SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; }
  
  using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>;
  using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>;

  ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }

  ivar_iterator ivar_begin() const {
    return ivar_iterator(decls_begin());
  }

  ivar_iterator ivar_end() const {
    return ivar_iterator(decls_end());
  }

  unsigned ivar_size() const {
    return std::distance(ivar_begin(), ivar_end());
  }

  bool ivar_empty() const {
    return ivar_begin() == ivar_end();
  }

  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ObjCImplementation; }
};

raw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID);

/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
/// declared as \@compatibility_alias alias class.
class ObjCCompatibleAliasDecl : public NamedDecl {
  /// Class that this is an alias of.
  ObjCInterfaceDecl *AliasedClass;

  ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
                          ObjCInterfaceDecl* aliasedClass)
      : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {}

  void anchor() override;

public:
  static ObjCCompatibleAliasDecl *Create(ASTContext &C, DeclContext *DC,
                                         SourceLocation L, IdentifierInfo *Id,
                                         ObjCInterfaceDecl* aliasedClass);

  static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C, 
                                                     unsigned ID);
  
  const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; }
  ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
  void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; }

  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ObjCCompatibleAlias; }
};

/// ObjCPropertyImplDecl - Represents implementation declaration of a property
/// in a class or category implementation block. For example:
/// \@synthesize prop1 = ivar1;
///
class ObjCPropertyImplDecl : public Decl {
public:
  enum Kind {
    Synthesize,
    Dynamic
  };

private:
  SourceLocation AtLoc;   // location of \@synthesize or \@dynamic

  /// \brief For \@synthesize, the location of the ivar, if it was written in
  /// the source code.
  ///
  /// \code
  /// \@synthesize int a = b
  /// \endcode
  SourceLocation IvarLoc;

  /// Property declaration being implemented
  ObjCPropertyDecl *PropertyDecl;

  /// Null for \@dynamic. Required for \@synthesize.
  ObjCIvarDecl *PropertyIvarDecl;

  /// Null for \@dynamic. Non-null if property must be copy-constructed in
  /// getter.
  Expr *GetterCXXConstructor = nullptr;

  /// Null for \@dynamic. Non-null if property has assignment operator to call
  /// in Setter synthesis.
  Expr *SetterCXXAssignment = nullptr;

  ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L,
                       ObjCPropertyDecl *property,
                       Kind PK,
                       ObjCIvarDecl *ivarDecl,
                       SourceLocation ivarLoc)
      : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
        IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl) {
    assert(PK == Dynamic || PropertyIvarDecl);
  }

public:
  friend class ASTDeclReader;

  static ObjCPropertyImplDecl *Create(ASTContext &C, DeclContext *DC,
                                      SourceLocation atLoc, SourceLocation L,
                                      ObjCPropertyDecl *property,
                                      Kind PK,
                                      ObjCIvarDecl *ivarDecl,
                                      SourceLocation ivarLoc);

  static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);

  SourceRange getSourceRange() const override LLVM_READONLY;

  SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
  void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }

  ObjCPropertyDecl *getPropertyDecl() const {
    return PropertyDecl;
  }
  void setPropertyDecl(ObjCPropertyDecl *Prop) { PropertyDecl = Prop; }

  Kind getPropertyImplementation() const {
    return PropertyIvarDecl ? Synthesize : Dynamic;
  }

  ObjCIvarDecl *getPropertyIvarDecl() const {
    return PropertyIvarDecl;
  }
  SourceLocation getPropertyIvarDeclLoc() const { return IvarLoc; }

  void setPropertyIvarDecl(ObjCIvarDecl *Ivar,
                           SourceLocation IvarLoc) {
    PropertyIvarDecl = Ivar;
    this->IvarLoc = IvarLoc;
  }

  /// \brief For \@synthesize, returns true if an ivar name was explicitly
  /// specified.
  ///
  /// \code
  /// \@synthesize int a = b; // true
  /// \@synthesize int a; // false
  /// \endcode
  bool isIvarNameSpecified() const {
    return IvarLoc.isValid() && IvarLoc != getLocation();
  }

  Expr *getGetterCXXConstructor() const {
    return GetterCXXConstructor;
  }

  void setGetterCXXConstructor(Expr *getterCXXConstructor) {
    GetterCXXConstructor = getterCXXConstructor;
  }

  Expr *getSetterCXXAssignment() const {
    return SetterCXXAssignment;
  }

  void setSetterCXXAssignment(Expr *setterCXXAssignment) {
    SetterCXXAssignment = setterCXXAssignment;
  }

  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; }
};

template<bool (*Filter)(ObjCCategoryDecl *)>
void
ObjCInterfaceDecl::filtered_category_iterator<Filter>::
findAcceptableCategory() {
  while (Current && !Filter(Current))
    Current = Current->getNextClassCategoryRaw();
}

template<bool (*Filter)(ObjCCategoryDecl *)>
inline ObjCInterfaceDecl::filtered_category_iterator<Filter> &
ObjCInterfaceDecl::filtered_category_iterator<Filter>::operator++() {
  Current = Current->getNextClassCategoryRaw();
  findAcceptableCategory();
  return *this;
}

inline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) {
  return !Cat->isHidden();
}

inline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) {
  return Cat->IsClassExtension() && !Cat->isHidden();
}

inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) {
  return Cat->IsClassExtension();
}

} // namespace clang

#endif // LLVM_CLANG_AST_DECLOBJC_H
