//===- DeclObjC.h - Classes for representing declarations -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file 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/DeclObjCCommon.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];
  }
};

/// 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 {
  // This class stores some data in DeclContext::ObjCMethodDeclBits
  // to save some space. Use the provided accessors to access it.

public:
  enum ImplementationControl { None, Required, Optional };

private:
  /// Return type of this method.
  QualType MethodDeclType;

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

  /// 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 isSynthesizedAccessorStub = false, 
                 bool isImplicitlyDeclared = false, bool isDefined = false,
                 ImplementationControl impControl = None,
                 bool HasRelatedResultType = false);

  SelectorLocationsKind getSelLocsKind() const {
    return static_cast<SelectorLocationsKind>(ObjCMethodDeclBits.SelLocsKind);
  }

  void setSelLocsKind(SelectorLocationsKind Kind) {
    ObjCMethodDeclBits.SelLocsKind = Kind;
  }

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

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

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

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

  /// 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 isSynthesizedAccessorStub = 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 static_cast<ObjCDeclQualifier>(ObjCMethodDeclBits.objcDeclQualifier);
  }

  void setObjCDeclQualifier(ObjCDeclQualifier QV) {
    ObjCMethodDeclBits.objcDeclQualifier = QV;
  }

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

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

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

  /// True if redeclared in the same interface.
  bool hasRedeclaration() const { return ObjCMethodDeclBits.HasRedeclaration; }
  void setHasRedeclaration(bool HRD) const {
    ObjCMethodDeclBits.HasRedeclaration = HRD;
  }

  /// 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 getBeginLoc() const LLVM_READONLY { return getLocation(); }
  SourceLocation getEndLoc() const LLVM_READONLY;
  SourceRange getSourceRange() const override LLVM_READONLY {
    return SourceRange(getLocation(), getEndLoc());
  }

  SourceLocation getSelectorStartLoc() const {
    if (isImplicit())
      return getBeginLoc();
    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();
  }

  /// If this method is declared or implemented in a category, return
  /// that category.
  ObjCCategoryDecl *getCategory();
  const ObjCCategoryDecl *getCategory() const {
    return const_cast<ObjCMethodDecl*>(this)->getCategory();
  }

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

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

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

  ParmVarDecl *getParamDecl(unsigned Idx) {
    assert(Idx < NumParams && "Index out of bounds!");
    return getParams()[Idx];
  }
  const ParmVarDecl *getParamDecl(unsigned Idx) const {
    return const_cast<ObjCMethodDecl *>(this)->getParamDecl(Idx);
  }

  /// 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
  /// implicit 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) const;

  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 ObjCMethodDeclBits.IsInstance; }
  void setInstanceMethod(bool isInst) {
    ObjCMethodDeclBits.IsInstance = isInst;
  }

  bool isVariadic() const { return ObjCMethodDeclBits.IsVariadic; }
  void setVariadic(bool isVar) { ObjCMethodDeclBits.IsVariadic = isVar; }

  bool isClassMethod() const { return !isInstanceMethod(); }

  bool isPropertyAccessor() const {
    return ObjCMethodDeclBits.IsPropertyAccessor;
  }

  void setPropertyAccessor(bool isAccessor) {
    ObjCMethodDeclBits.IsPropertyAccessor = isAccessor;
  }

  bool isSynthesizedAccessorStub() const {
    return ObjCMethodDeclBits.IsSynthesizedAccessorStub;
  }

  void setSynthesizedAccessorStub(bool isSynthesizedAccessorStub) {
    ObjCMethodDeclBits.IsSynthesizedAccessorStub = isSynthesizedAccessorStub;
  }

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

  /// 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 ObjCMethodDeclBits.IsOverriding; }
  void setOverriding(bool IsOver) { ObjCMethodDeclBits.IsOverriding = IsOver; }

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

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

  /// True if the method is tagged as objc_direct
  bool isDirectMethod() const;

  /// True if the method has a parameter that's destroyed in the callee.
  bool hasParamDestroyedInCallee() const;

  /// 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) {
    ObjCMethodDeclBits.DeclImplementation = ic;
  }

  ImplementationControl getImplementationControl() const {
    return ImplementationControl(ObjCMethodDeclBits.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;

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

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

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

  /// Is this method defined in the NSObject base class?
  bool definedInNSObject(const ASTContext &) const;

  // 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 *> {
  /// Location of the left and right angle brackets.
  SourceRange Brackets;
  /// 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 Brackets.getBegin(); }
  SourceLocation getRAngleLoc() const { return Brackets.getEnd(); }
  SourceRange getSourceRange() const { return Brackets; }

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

/// 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 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 : NumObjCPropertyAttrsBits;
  unsigned PropertyAttributesAsWritten : NumObjCPropertyAttrsBits;

  // \@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(ObjCPropertyAttribute::kind_noattr),
        PropertyAttributesAsWritten(ObjCPropertyAttribute::kind_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;

  ObjCPropertyAttribute::Kind getPropertyAttributes() const {
    return ObjCPropertyAttribute::Kind(PropertyAttributes);
  }

  void setPropertyAttributes(ObjCPropertyAttribute::Kind PRVal) {
    PropertyAttributes |= PRVal;
  }

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

  ObjCPropertyAttribute::Kind getPropertyAttributesAsWritten() const {
    return ObjCPropertyAttribute::Kind(PropertyAttributesAsWritten);
  }

  void setPropertyAttributesAsWritten(ObjCPropertyAttribute::Kind PRVal) {
    PropertyAttributesAsWritten = PRVal;
  }

  // Helper methods for accessing attributes.

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

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

  /// isRetaining - Return true if the property retains its value.
  bool isRetaining() const {
    return (PropertyAttributes & (ObjCPropertyAttribute::kind_retain |
                                  ObjCPropertyAttribute::kind_strong |
                                  ObjCPropertyAttribute::kind_copy));
  }

  bool isInstanceProperty() const { return !isClassProperty(); }
  bool isClassProperty() const {
    return PropertyAttributes & ObjCPropertyAttribute::kind_class;
  }
  bool isDirectProperty() const;

  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 & ObjCPropertyAttribute::kind_strong)
      return getType()->isBlockPointerType() ? Copy : Retain;
    if (PropertyAttributes & ObjCPropertyAttribute::kind_retain)
      return Retain;
    if (PropertyAttributes & ObjCPropertyAttribute::kind_copy)
      return Copy;
    if (PropertyAttributes & ObjCPropertyAttribute::kind_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 {
  // This class stores some data in DeclContext::ObjCContainerDeclBits
  // to save some space. Use the provided accessors to access it.

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

  // 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 ObjCContainerDeclBits.AtStart; }

  void setAtStartLoc(SourceLocation Loc) {
    ObjCContainerDeclBits.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(getAtStartLoc(), 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));
  }
};

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

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

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

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

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

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

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

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

  /// Determine whether this particular declaration of this class is
  /// actually also a definition.
  bool isThisDeclarationADefinition() const {
    return getDefinition() == this;
  }

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

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

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

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

  /// 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:
  /// Test whether the given category is visible.
  ///
  /// Used in the \c visible_categories_iterator.
  static bool isVisibleCategory(ObjCCategoryDecl *Cat);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  ObjCIvarDecl *getCanonicalDecl() override {
    return cast<ObjCIvarDecl>(FieldDecl::getCanonicalDecl());
  }
  const ObjCIvarDecl *getCanonicalDecl() const {
    return const_cast<ObjCIvarDecl *>(this)->getCanonicalDecl();
  }

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

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

/// 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 {
    // The declaration that defines this protocol.
    ObjCProtocolDecl *Definition;

    /// Referenced protocols
    ObjCProtocolList ReferencedProtocols;
  };

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

  /// This is true iff the protocol is tagged with the
  /// `objc_non_runtime_protocol` attribute.
  bool isNonRuntimeProtocol() const;

  /// Get the set of all protocols implied by this protocols inheritance
  /// hierarchy.
  void getImpliedProtocols(llvm::DenseSet<const ObjCProtocolDecl *> &IPs) const;

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

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

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

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

  /// Determine whether this particular declaration is also the
  /// definition.
  bool isThisDeclarationADefinition() const {
    return getDefinition() == this;
  }

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

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

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

  /// Get the name of the class associated with this interface.
  //
  // FIXME: Move to StringRef API.
  std::string getNameAsString() const { return std::string(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

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

  /// The getter's definition, which has an empty body if synthesized.
  ObjCMethodDecl *GetterMethodDecl = nullptr;
  /// The getter's definition, which has an empty body if synthesized.
  ObjCMethodDecl *SetterMethodDecl = nullptr;

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

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

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

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

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

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

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

} // namespace clang

#endif // LLVM_CLANG_AST_DECLOBJC_H
